目录
一、引言
引入类与对象(OOP)的目的就是现有的技术不能完美解决新的需求。比如描述一个事物,单独的定义变量和使用数组,都不能很好地解决,不利于数据的管理,效率低。
在Java中最基本的单位是类,事物通过类来体现。
类就是数据类型,有属性(成员变量)和行为(成员方法),即:类就是一组相关的属性和行为的集合。比如Person类。
对象就是一个具体的体现(实例),一个对象可以管理多个属性和行为。以下面的代码为例,不同的对象可以管理他们各自的属性。
1)类是抽象的,概念的,代表一类事物,比如人类、书类...,即它是数据类型。
2)对象是具体的,实际的,代表一个具体事物,即是实例。
3)类是对象的模板,对象是类的一个个体,对应一个实例。
public class TestDemo {
public static void main(String[] args) {
Cat cat1 = new Cat();
cat1.name = "小白";
cat1.age = 12;
cat1.color = "白色";
Cat cat2 = new Cat();
cat2.name = "bb";
cat2.age = 3;
cat2.color = "黑色";
}
}
class Cat {
String name;
int age;
String color;
}
二、对象在内存布局图
这里要注意:String类型的数据是存放在方法区的常量池中的;任何数据都有它独有的地址值。
对象内存图详细介绍:
- 执行main方法之前,先在内存的方法区中加载类,该类是main方法所在的类,方法区中就有一个空间存放TestDemo2.class,main方法的信息,就存放在方法区的TestDemo2.class这个区域中。
- main方法加载完后,要执行main方法,就要参考方法区中的信息,在栈中执行main方法中的代码,栈中是执行所有方法的地方。
- 在栈中开辟一块空间,这块空间叫main,代码开始执行:
- 先执行右边new Car(),这是第一次使用Car这个类,当第一次使用这个Car类时,会将Car类的信息(属性和方法)加载到方法区,即:方法区中会开辟一块空间叫Car.class。
- 接下来才是真正的开始new Car(),即在堆中开辟一块空间创建Car对象,这块空间是参考方法区重的Car信息创建的。
- 在堆中的成员变量是有默认值的,引用数据类型默认为null,基本数据类型遵循基本数据类型的默认规则。成员变量是从方法区中拷贝到堆中的。(注意:String类型的数据真正的内容也是在方法区中的常量池,这里先不画了)
- 在堆中开辟空间后就会产生一个十六进制的地址值,成员方法在方法区中就有地址,所以堆中的成员方法拷贝的是地址,即堆中成员方法的地址指向方法区中,类的成员方法地址。
- 堆中的对象创建并初始化完成后,其地址会赋值给main方法中的局部变量,即Car car;所以car变量指向堆中的对象。
- 对象名.成员变量修改堆中成员变量之前的默认值
- 接下来调用成员方法,参考方法区中的成员方法,在栈中开辟一块新的空间run,run方法执行完毕后,就会出栈,run空间就会立即被销毁掉。
- 调用stop方法也是同样,参考方法区中的信息,在栈中开辟一块新的空间stop,stop方法执行完毕后,就会出栈,stop空间就会立即被销毁掉。
- 此时,main方法也执行完毕了,main方法也会随之出栈。
- 最后这个内存空间全部被回收。
三、属性/成员变量
(一)基本介绍
1.从概念或叫法上看:成员变量=属性=field(字段) (即 成员变量是用来表示属性的)。
2.属性是类的一个组成部分,一般是基本数据类型,也可以是引用数据类型(对象,数组)。比如前面定义的猫类的 int age就是属性。
class Car {
String name;
double price;
String color;
String[] master; // 数组也可以是属性
}
(二)注意事项和细节说明
- 属性的定义语法同变量,实例:访问修饰符 属性类型 属性名;访问修饰符控制属性的访问范围,有4种访问修饰符:public、protected、默认和private。
- 属性的定义类型可以为任意类型,包含基本数据类型或引用数据类型。
- 属性如果不赋值,有默认值,规则和数组一致。具体为:
int short byte long float double char boolean String 0 0 0 0 0 0 \u0000 false null
public class TestDemo1 {
public static void main(String[] args) {
//创建Person 对象
//p1 是对象名(对象引用)
//new Person() 创建的对象空间(数据) 才是真正的对象
Person p1 = new Person();
//对象的属性默认值,遵守数组规则:
System.out.println("当前这个人的信息:");
System.out.println("age=" + p1.age + " name="
+ p1.name + " sal=" + p1.sal + " isPass=" + p1.isPass);
// 当前这个人的信息:
// age=0 name=null sal=0.0 isPass=false 这些都是属性的默认值
}
}
class Person {
int age;
String name;
double sal;
boolean isPass;
}
(三)创建对象的方式
1.先声明,再创建
Cat cat; // 声明对象 cat
cat = new Cat();
2.直接创建
Cat cat = new Cat();
四、对象的分配机制(重要)
(一)Java内存的结构分析
- 栈:一般存放基本数据类型(局部变量)
- 堆:存放对象(Cat cat,数组等)
- 方法区:常量池(常量,比如字符串),类加载信息
(二)Java创建对象的流程简单分析
以下面这段代码为例:
Person p = new Person();
p.name = "jack";
p.age = 10;
- 先加载Person类信息(属性和方法信息,只会加载一次)
- 在堆中分配空间,进行默认初始化
- 把地址赋给p,p就指向对象
- 进行指定初始化,比如p.name = "jack"; p.age = 10;
(三)对象机制练习
五、成员变量和局部变量的区别(重要)
1.初始化值不同
- 成员变量有默认值
- 局部变量没有默认值,不赋值不能使用
2.在类中的位置不同
- 成员变量:在类中方法外
- 局部变量:在方法中或者方法的声明上
3.内存位置不同
- 成员变量:在堆内存
- 局部变量:栈内存
4.生命周期不同
- 成员变量:随着对象的创建而出现,随着对象的消失而消失。
- 局部变量:随着方法调用,在定义的那一行出现,随着方法的调用完毕而消失。