文章目录
- OOTest01
- OOTest02
- OOTest03
- OOTest04:空指针异常
- java虚拟机内存
- 结语
OOTest01
首先我们看一个学生类:
学生类是一个模板,描述了所有学生得共同特征(状态+行为),当前类只描述学生的状态信息(属性)。
public class Student {
//Student是类,属于引用数据类型,这个类型名就是:Student
//类体=属性+方法
//属性(存储数据采用变量的形式)
//由于变量定义在类体当中,方法体之外,这种变量成为成员变量
//所有学生都有学号信息,但是每一个学生的学号都是不同的
//所以要访问这个学号必须先创建对象,通过对象去访问学号信息
//学号信息不能直接通过类去访问,所以这种成员变量又叫做:实例变量
//对象又被称作实例,实例变量又被称为对象变量(对象级别的变量)
//不创建对象,这个no变量的内存空间是不存在的,只有创建了对象,这个no变量内存空间才会创建
int no;//学号
String name;//姓名
int age;//年龄
Boolean sex;//性别
String addr;//住址
}
如果成员变量没有手动赋值的话,系统就会赋默认值
数据类型 | 默认值 |
byte,short,long,int | 0 |
float,double | 0.0 |
boolean | false |
char | \u0000 |
引用数据类型 | null |
那么,我们进行java对象的创建和引用吧:
首先我要说的是:
- 通过一个类可以实例化n个对象
- 实例化对象的语法:new 类名();
- new是Java语言中的一个运算符,它的作用是创建对象,在JVM堆内存中开辟新的内存空间
而java虚拟机内有三大块:
- 方法区内存:在类加载的时候,class字节码文件代码片段被加载到该内存空间中
- 栈内存(局部变量):方法代码片段执行的时候,会给该方法分配内存空间,在栈内存中压栈
- 堆内存:new的对象在堆内存中存储
public class OOTest01 {
public static void main(String[] args) {
//int i=10;
//int是基本数据类型
//i是一个变量名
//10是一个int类型的字面值
Student s=new Student();//[^1]
//Student是一个引用数据类型,s是一个变量名
//new Student()是一个学生对象
//s是局部变量,在栈中存储
//什么是对象?new运算符在堆内存中开辟的内存空间称为对象
//什么是对象引用?对象引用是一个变量,只不过这个变量中保存了另一个Java对象的内存地址
//java程序员要想访问堆内存当中的对象内部的实例变量,必须得通过引用,和c不一样,c只需要用指针便可以
//访问实例变量的语法格式:
//读取数据:引用.变量名
//修改数据:引用.变量名=值
int stuNo=s.no;
String stuName=s.name;
int stuAge=s.age;
boolean stuSex=s.sex;
String stuAddr=s.addr;
System.out.println("学号:"+stuNo);//0
System.out.println("姓名:"+stuName);//null
System.out.println("年龄:"+stuAge);//0
System.out.println("性别:"+stuSex);//false
System.out.println("住址:"+stuAddr);//null
s.no=10;
s.name="奥特曼";
s.age=45000;
s.sex=true;
s.addr="光之国";
System.out.println("学号:"+s.no);//10
System.out.println("姓名:"+s.name);//奥特曼
System.out.println("年龄:"+s.age);//45000
System.out.println("性别:"+s.sex);//true
System.out.println("住址:"+s.addr);//光之国
//再通过类实例化一个全新的对象
Student stu=new Student();
//stu同时也是一个局部变量
//Student是变量的数据类型
System.out.println(stu.no);
System.out.println(stu.name);
System.out.println(stu.age);
System.out.println(stu.sex);
System.out.println(stu.addr);
//System.out.println(Student.addr);
//此时编译报错,因为addr是实例变量,对象级别的变量,变量存储在java对象的内部,必须先有对象
//通过对象才能访问addr这个实例变量,不能直接通过类名
}
}
这里,局部变量在栈内存中存储
成员变量中的实例变量在堆内存中的java对象内部存储
实例变量是一个对象一份,一百个对象一百份
给出当程序执行到Student s=new Student();时的内存图:
给出访问实例变量时的内存图:
给出又通过类实例化一个新对象后的内存图:
OOTest02
下面我们创建一个用户类和家庭住址类:
用户类:
//用户类
public class User {
//属性(以下是成员变量之实例变量)
//用户编号
int no;
//int是一种基本数据类型:整数型
//no是一个实例变量
//用户名
String name;
//String是一种引用数据类型:代表字符串
//name是一个实例变量
//name是一个引用
//家庭住址
Address addr;
//Address是一种引用数据类型:代表家庭住址
//addr是一个实例变量
//addr是一个引用
//引用是一个变量,变量里面保存了内存地址,地址指向了一个对象
}
家庭住址类:
//家庭住址类
public class Address {
//属性(成员变量之实例变量)
//城市
//String是一种引用数据类型,city是一个变量名,属于实例变量
//city是一个引用:保存内存地址的一个变量,该变量保存内存地址指向了堆内存当中的对象
//城市
String city;
//街道
String street;
//邮编
String zipcode;
}
OOTest02类:
public class OOTest02 {
public static void main(String[] args) {
//创建user对象
User u=new User();
//u是局部变量,是一个引用
//u保存内存地址指向堆内存的User对象
//输出User对象内部实例变量的值
System.out.println(u.no+" "+u.name+" "+u.addr);
//修改User对象内部实例变量的值
u.no=12;
u.name="jack";//字符串比较特殊,不用new
u.addr=new Address();
//在main方法当中目前只能看到一个引用"u",
//一切都是只能通过u来访问
System.out.println(u.name+"居住在的城市为"+u.addr.city);
u.addr.city="武汉";
System.out.println(u.name+"居住在的城市为"+u.addr.city);
}
}
给出OOTest02的内存图:
OOTest03
public class OOTest03 {
public static void main(String[] args) {
//u是引用
//u是局部变量
User u=new User();
//u.addr=new Address();
//a是引用,是局部变量
Address a=new Address();
u.addr=a;
System.out.println(u.addr.city);//null
a.city="北京";
System.out.println(u.addr.city);//北京
}
}
OOTest04:空指针异常
我们现在再说一下空指针异常这个比较常见的错误
创建一个简单的顾客类:
//顾客类
public class Customer {
//id
int id;
}
OOTest04类:
public class OOTest04 {
public static void main(String[] args) {
Customer c=new Customer();
System.out.println(c.id);//0
c=null;
//以下程序运行出现空指针异常
//空引用访问“实例”相关的数据一定会出现空指针异常
//即java.lang.NUllPointerExcepation错误
//System.out.println(c.id);
}
}
//“实例”相关的数据表示:这个数据访问的时候必须有对象的参与
内存图如下:
java虚拟机内存
最后我们说一下java虚拟机内存是怎么回事
- JVM(java虚拟机)主要包括三块内存空间,分别是:栈内存、堆内存、方法区内存。(上面的内存图都给你画出来了)
- 堆内存和方法区内存各有一个,而一个线程一个栈内存。
- 方法调用的时候,该方法所需要的内存空间在栈内存中分配,称为压栈。方法执行结束之后,该方法所属的内存空间释放,称为出栈。
- 栈中主要存储的是方法体当中的局部变量。
- 方法的代码片段以及整个类的代码片段都被存储到方法区内存当中,在类加载的时候这些代码会载入。
- 在程序执行过程中使用new运算符创建的java对象,存储在堆内存当中,对象内部有实例变量,所以实例变量存储在堆内存当中。
- 变量分类:
局部变量【方法体中声明】
成员变量【方法体外声明】:分为实例变量,静态变量(有无static修饰) - 静态变量存储在方法区内存
- 三块内存当中变化最频繁的是栈内存,最先有数据的是方法区内存,垃圾回收器主要针对的是堆内存。
- 垃圾回收器【自动垃圾回收机制、GC机制】什么时候会考虑将某个java对象得内存回收呢?
答:当堆内存当中的java对象成为垃圾数据的时候,会被垃圾回收器回收。 - 什么时候堆内存中的java对象会变成垃圾呢?
答:没有更多的引用指向它的时候。
这个对象无法被访问,因为访问对象只能通过引用的方式。
结语
结语:感觉这次博客写的有点乱,读者看起来可能会觉得累吧,最后面的关于java虚拟机的东西我觉得值得一看呢,不过我也就一个小白。如果有错误请指出来鸭,加油鸭!