P245对象创建流程分析
- //1.先在方法区加载方法类
- //2.在堆里开空间一个存放age,一个存放name
- //3.(先默认初始化有默认值age=0,name=null,再显示初始化age=90,name=null)
- //4.这个时候调用构造器(name=小钱,注意String指向方法区的常量池,堆的name空间是地址,age=20)
- //5.将堆的开辟的空间地址传给P,P本质是对象的引用
- 代码如下
public class Test245 { public static void main (String[] args) { Person p = new Person("小钱",20); //1.先在方法区加载方法类 //2.在堆里开空间一个存放age,一个存放name //3.(先默认初始化有默认值age=0,name=null,再显示初始化age=90,name=null) //4.这个时候调用构造器(name=小钱,注意String指向方法区的常量池,堆的name空间是地址,age=20) //5.将堆的开辟的空间地址传给P,P本质是对象的引用 } } class Person{//类 int age=90; String name; Person(String n,int a){ name=n; age=a; } }
总结:
- 1.加载Person类信息(Person.class),只会加载一次
- 2.在堆里分配空间(地址)
- 3.在堆里完成对象吃时候[3.1默认初始化age=0,name=null,3.2显示初始化 age =90,
- name=null,3.3构造器初始化 age=20,name=“小钱"]
- 4.在对象在堆中的地址返回给p,(p是对象名,也可以理解成对象的引用总结:
P246this关键字
- //如果我们构造器的形参直接写成属性名更好了
- //但是出现一个问题,根据变量的作用域规则
- //构造器name是局部变量,而不是属性
- //构造器age是局部变量,而不是属性
- //=>1引出this关键字
public class Test246this01 { public static void main (String[] args) { Dog dog1 = new Dog("keai",3); dog1.info();//输出的是属性,所以结果就是null和0 } } class Dog{//类 public int age; public String name; public Dog(String name,int age){//构造器 //如果我们构造器的形参直接写成属性名更好了 //但是出现一个问题,根据变量的作用域规则 //构造器name是局部变量,而不是属性 //构造器age是局部变量,而不是属性 //=>1引出this关键字 age=age; name=name; } public void info(){//成员方法 System.out.println(name+"\t"+age+"\t"); } }
this关键字P247
this java虚拟机会给每个对象分配this,代表当前对象,用this解决前面的问题
public Dog(String name,int age){//构造器 //=>1引出this关键字 this.age=age;//this,name就是当前对象的属性name, this.name=name;//当前对象就是指new出来的当前对象,谁调用就是谁
- //this,name就是当前对象的属性name,
- //当前对象就是指new出来的当前对象,谁调用就是谁
- 此时输出keai
- 内存分析法理解thisP248
- Dog dog1 = new Dog("keai",3);
dog1.info();- main栈中dog1[地址1] 堆里对象dog1地址1[age:3,name:指向方法区常量池地址2,隐藏属性this地址1(可以看成指向对象dog1) 方法区常量池[name:keai 地址2]
- 实际上因为地址存在是java虚拟机,我们可以用hashCode来演示(把对象地址转换成整数)
public class Test246this01 { public static void main (String[] args) { Dog dog1 = new Dog("keai",3); System.out.println("dog1的hashCode"+dog1.hashCode()); dog1.info(); Dog dog2 = new Dog("ki",2); dog2.info(); System.out.println("dog2的hashCode"+dog2.hashCode()); } } class Dog{//类 public int age; public String name; public Dog(String name,int age){//构造器 this.age=age;//this,name就是当前对象的属性name, this.name=name;//当前对象就是指new出来的当前对象,谁调用就是谁 System.out.println("this.hashCode="+this.hashCode()); } public void info(){//成员方法 } }
输出结果如下
this.hashCode=2104457164
dog1的hashCode2104457164
this.hashCode=1500056228
dog2的hashCode1500056228P250this关键字细节
1.//this关键字可以用来访问本类的属性、方法、构造器
2.//this可以用于区分当前类的属性和局部变量
3.//访问成员方法的语法:this.方法名(参数列表);
4.//访问构造器语法:this(参数列表);注意只能在构造器中使用 访问构造器的语法,this()必须放置再第一条语句
5.//this不能再类定义的外部使用,只能再类定义的方法中使用
具体代码.//访问本来属性的语法:this.属性名;P250
public class Test250ThisDetial { public static void main (String[] args) { T t2=new T(); t2.f(); } } //访问成员方法的语法:this.方法名(参数列表; class T{ String name ="smith"; int age=99; public void f(){ //this关键字访问本类的属性 String name="jiujin"; //传统方法(就近原则) System.out.println("name"+name+"age="+age);//输出就近name //也可以使用this方法 System.out.println("name"+this.name+"age="+this.age);//输出simith } }
输出 namejiujinage=99 namesmithage=99
3.//访问成员方法的语法:this.方法名(参数列表);
public class Test250ThisDetial { public static void main (String[] args) { T t1=new T(); t1.f2(); } } //访问成员方法的语法:this.方法名(参数列表; class T{ String name ="smith"; int age=99; public void f1(){ System.out.println("f1()方法..."); } public void f2(){ System.out.println("f2()方法..."); //调用本类的f1方法 //第一种方式 f1(); //第二种方式 this.f1();//访问成员方法的语法:this.方法名(参数列表); } }
输出:f2()方法...
f1()方法...
f1()方法...4.//访问构造器语法:this(参数列表);注意只能在构造器中使用 访问构造器的语法,this()必须放置再第一条语句
public class Test250ThisDetial { public static void main (String[] args) { T t2=new T(); } } //访问构造器语法:this(参数列表);注意只能在构造器中使用 访问构造器的语法,this()必须放置再第一条语句 //this不能再类定义的外部使用,只能再类定义的方法中使用 class T{ String name ="smith"; int age=99; public T(){//构造器 this("jack",100);//第一条 System.out.println("T()构造器被调用..."); } public T(String name,int age){//构造器 System.out.println("T(String name,int age)构造器被调用..."); } }
输出
T(String name,int age)构造器被调用...
T()构造器被调用..