面向對象
類
package com.mm;public class Person {/*** 名詞-屬性*/String name;int age;double height;/*** 動詞-方法*/public void sleep(String add) {System.out.println("我在" + add + "睡覺");}public String introduce() {return "我的名字是" + name + "我的年齡是" + age;}
}
調用Person類
package com.mm;/*** 測試類:一般在測試類中編寫業務邏輯代碼*/
public class test {/*** main程序的入口*/public static void main(String[] args) {//創建一個Person類的對象Person p1 = new Person();//參照類的模板,給對象賦值p1.name = "麗麗";p1.age = 19;p1.height = 164.7;p1.sleep("賓館");//接收對象返回值String s = p1.introduce();System.out.println(s);//創建新對象,對象不能重復命名Person p2 = new Person();p2.age = 30;//匿名對象new Person().age = 10;//可以對對象的屬性進行賦值//注意,重復調用匿名對象產生的是不同對象,這是一個新的對象new Person().name = "菲菲";//用于僅一次調用,支持鏈式調用。表示返回下標為1的字符new Person().introduce().charAt(1);System.out.println(new Person().introduce().charAt(1));}
}
構造器
package com.mm;public class Person {/*** 名詞-屬性*/String name;int age;double height;/*** 顯式的將構造器編寫出來*/public Person(){System.out.println("這是無參構造器");}/*** 動詞-方法*/public void sleep(String add) {System.out.println("我在" + add + "睡覺");}public String introduce() {return "我的名字是" + name + "我的年齡是" + age;}
}
調用Person類
package com.mm;/*** 測試類:一般在測試類中編寫業務邏輯代碼*/
public class test {/*** main程序的入口*/public static void main(String[] args) {Person p = new Person();}
}
有參構造器——構造器的重載
package com.mm;public class Person {int age;String name;double height;public Person(){//空參構造器,盡量保證存在}//構造器的重載public Person(int age, String name, double height) {//形參名可以跟屬性一樣,//默認就近原則:下面兩個age都默認是形參age,相當于沒有賦值給屬性this.age = age;//使用this關鍵字,修飾要表示的屬性this.name = name;this.height = height;}
}
調用Person類
package com.mm;public class test {public static void main(String[] args) {Person p = new Person(1, "菲菲", 110.1);System.out.println(p.age);System.out.println(p.name);}public static void main(String[] args) {Person p = new Person(2, "琳琳", 120.1);System.out.println(p.age);System.out.println(p.name);
}
步驟1
在棧中為main方法開辟棧幀。把Person類對應的字節碼信息加載到方法區。等號右側:new操作在堆空間開辟空間創建對象,此時屬性為初始值。
步驟2
調用有參構造器(在構造方法棧中產生有參構造方法的棧幀,含參數a、b、c)。JVM(從棧內存?)把基本數據類型通過值傳遞傳給a、b,從字符串常量池把字符串(地址)傳給參數c。
步驟3
構造方法棧幀中的a、b、c把對應值傳給堆中的對象屬性。構造方法棧幀消失。
步驟4
堆空間中生成一個對應的地址0x88。等號左側:把地址賦給棧空間中main棧幀的對象p
內存分析
方法形參為自定義引用數據類型。對象和對象之間的數據本身是不會相互影響的,但多個變量指向同一個對象時就會相互影響
package com.mm;public class Person {int id;int age;Person(int a, int b) {id = a;age = b;}class Test {public void change(Person p) {//傳遞對象p(不是傳遞對象的數據)p.id = 2;p.age = 18;}public static void main(String[] args) {//主方法Person p = new Person(1, 20);//創建對象p(0x88地址指向堆內存中的對象)Test t = new Test();//創建對象t(0x72地址指向堆內存中的對象)t.change(p);//t調用change方法。為change方法創建對應棧幀,把main方法里的對象p傳到chage方法里(雖然是通過值傳遞方式,但傳過去的也是0x88地址指向堆內存中的對象)System.out.println(p.id);//2System.out.println(p.age);//18}}
}
步驟1
在棧中為main方法開辟棧幀。
把Person類對應的字節碼信息加載到方法區。等號右側:new操作在堆空間開辟空間創建對象,此時屬性為初始值。堆空間中生成一個對應的地址0x88。等號左側:把地址賦給棧空間中main棧幀的對象p
把Test類對應的字節碼信息加載到方法區。等號右側:new操作在堆空間開辟空間創建對象,此時屬性為初始值。堆空間中生成一個對應的地址0x72。等號左側:把地址賦給棧空間中main棧幀的對象t
步驟2
在棧幀中開辟change方法棧幀,并將p對象的地址提供‘值傳遞’方式傳到change方法棧幀。
步驟3
change棧幀中的p依舊是0x88,指向堆空間里的對象
方法形參為自定義引用數據類型。對象和對象之間的數據本身是不會相互影響的,但多個變量指向同一個對象時就會相互影響
步驟4
方法change對p.id和p.age重新賦值,改變堆空間0x88對應的對象p的屬性
打印時main棧幀里的p對象通過0x88找到堆空間的p對象并返回屬性值(被改變)
this關鍵字
package com.mm;public class Person {int age;String name;public Person(int age, String name){//屬性名字和形參重名//this修飾構造器必須放在第一行this(age);//等于this.age = age。相當于調用本類的構造器(下面第一個)System.out.println(this); // 指代的就是當前正在構建的對象//this.age = age; // 如果屬性名字和形參重名,那么要表示的屬性前面必須加上thisthis.name = name;}public Person(int age){//被this隱式修飾的構造器,被上面調用this.age = age;}public Person(String name){//參數類型不同,不會被調用this.name = name;}public void sleep(){System.out.println(/*this.*/age); // 10,此處沒有重名問題,那么可以省略this.int age = 66;System.out.println(age);//66 如果局部變量和屬性重名,也會發生就近原則System.out.println(this.age); // 10}public void eat(){System.out.println(this); // 指代的就是正在調用當前方法的對象System.out.println("我可以吃飯");play();//如果在同一個類中調用本類的方法,可以不用寫this}public void play(){System.out.println("我可以玩");}
}
調用Person類sleep方法
package com.mm;public class Test {public static void main(String[] args) {// 創建Person類的具體的對象:Person p = new Person(10, "麗麗");System.out.println(p);p.sleep();p.eat();}
}
封裝
package com.mm;public class Person {private int age;/*** 定義一個方法,用來設置age,提供合理的暴露*/public void setAge(int age) {if (age >= 18) {//只暴露小于18的,大于等于18的都是18this.age = 18;} else {this.age = age;}}/*** 用來讀取age*/public int getAge() {return this.age;}
}
調用Person
package com.mm;public class test {public static void main(String[] args) {Person p = new Person();p.setAge(19);System.out.println(p.getAge());}
}
封裝實操
package com.mm;public class Person {private String name;private String sex;private int age;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getSex() {return sex;}public void setSex(String sex) {if (sex.equals("男") || sex.equals("女")) {//使用equals更規范this.sex = sex;} else {this.sex = "男";}}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public Person() {}public Person(String name, String sex, int age) {this.name = name;//相當于this.sex = sex;setSex(sex);//使用上面的方法setSexthis.age = age;}
}
調用Person類
package com.mm;public class test {public static void main(String[] args) {Person p = new Person();p.setAge(19);p.setName("麗麗");p.setSex("女");System.out.println(p.getAge());System.out.println(p.getName());System.out.println(p.getSex());Person p2 = new Person("菲菲", "sdfa", 19);System.out.println(p2.getAge());System.out.println(p2.getName());System.out.println(p2.getSex());}
}