構造方法、 This關鍵字 、static、封裝
1.1 構造方法
構造方法是一種特殊的方法,專門用於構造/實例化對象,形式:
[修飾符] 類名(){
}
構造方法根據是否有參數分為無參構造和有參構。
1.1.1 無參構造
無參構造方法就是構造方法沒有任何參數。構造方法在創建對象(new Dog())調用,無參構造方法中一般用於給屬性賦值默認值。
public class Dog{
String name;
int health;
int love;
String strain;
public Dog(){
System.out.println("構造方法");
health = 100;
love = 0;
}
…
}
如果開發中沒有定義無參構造方法,jvm默認給類分配一個無參構造,形如:
public Dog(){
}
1.1.2 有參構造
當構造/實例化一個對象時,可以向構造方法中傳遞參數,這樣的構造方法稱為有參構造。形如:
[修飾符] 類名(Type arg1,Type arg2,…){
// 初始化代碼
}
1.1.2.1 局部變量和成員變量優先級
如果在一個作用域中,局部變量和成員變量同名,局部變量的優先級更
public class Dog{
String name; int health; int love; String strain;
public Dog(String name,int health,int love,String strain){ name = name; health = health; love = love; strain = strain; } } |
優化後
public class Dog{
String name; int health; int love; String strain;
/* public Dog(){ System.out.println("構造方法"); health = 100; love = 0; } */
public Dog(String _name,int _health,int _love,String _strain){ name = _name; health = _health; love = _love; strain = _strain; }
public void showInfo(){ System.out.print("我的名字叫"+name); System.out.print(",健康值"+health); System.out.print(",親密度"+love); System.out.println(",我是一只"+strain); } } |
有參構造和無參構造是方法重載關系。
方法重載:方法重載是指在一個類中定義多個同名的方法,但要求每個方法具有不同的參數的類型或參數的個數。調用重載方法時,Java編譯器能通過檢查調用的方法的參數類型和個數選擇一個恰當的方法。
1.1.2.2 有參構造常見問題
如果一個類提供了有參構造方法,jvm不在給類默認分配無參構造。
public class Dog{
String name; int health; int love; String strain;
/* public Dog(){ System.out.println("構造方法"); health = 100; love = 0; } */
public Dog(String _name,int _health,int _love,String _strain){ name = _name; health = _health; love = _love; strain = _strain; }
public void showInfo(){ System.out.print("我的名字叫"+name); System.out.print(",健康值"+health); System.out.print(",親密度"+love); System.out.println(",我是一只"+strain); } } |
Dog dog = new Dog(); dog.name = name; dog.health = 100; dog.love = 0; dog.strain = strain; |
|
總結:
在開發過程中,如果開發者提供了有參構造方法,一定要習慣性的提供無參構造。
1.2This關鍵字(上)
1.1.1 對象初始化內存圖
|
this 是一個關鍵字,表示對象本身,本質上this中存有一個引用,引用對象本身。
this用於訪問本對象屬性,同時解決局部變量和成員變量同名的問題。
public Dog2(String name,int health,int love,String strain){ System.out.println("this:"+this); this.name = name; this.health = health; this.love = love; this.strain = strain; } |
public class Test04{ public static void main(String[] args){
Dog2 dog = new Dog2("二狗",100,0,"土狗"); System.out.println("dog:"+dog); dog.showInfo(); } } |
通過打印this中的引用,可以看出對象dog和this指向同一內存。
一般而言,dog用於類的外部,this用於類的內部。因為類的內部根本不知道dog變量名的存在。
1.2.2 方法的調用內存圖
|
優化方法代碼
public void showInfo(){ System.out.print("我的名字叫"+this.name); System.out.print(",健康值"+this.health); System.out.print(",親密度"+this.love); System.out.println(",我是一只"+this.strain); } |
1.3 static
需求:統計汽車工廠生成了多少量車?
ð 統計工廠生成了多少量汽車的功能應該放到類功能上,不應該屬於某個對象。
ð 聲明一個變量用於統計個數,這個變量應該被類的實例共享。
ð 被類的實例共享的區域在方法區(Car.class)
ð 用static關鍵字聲明這樣的變量
static 關鍵字表示靜態,可以修改變量,也可以修飾方法。
1.3.1 靜態變量
static 修飾的變量稱為靜態變量/靜態屬性,形式
static 類型 變量名稱 [= 初始值] |
被static修飾的變量稱為靜態變量,歸類所有,分配在方法區(共享區)中的靜態區,可以被類的實例共享訪問。
|
靜態變量歸類所有,也叫類變量,訪問方式:
[1] 類名.靜態變量(推薦)
[2] 對象.靜態變量
public class Car{ String brand; String type; float price;
static int count = 0;
public Car(){ Car.count++; }
public Car(String brand,String type,float price){ this.brand = brand; this.type = type; this.price = price; Car.count++; }
public void showInfo(){ System.out.println("車輛信息:"); System.out.println("品牌:"+this.brand); System.out.println("型號:"+this.type); System.out.println("價格:"+this.price); System.out.println("我是第"+Car.count+"輛車"); }
} |
public class Test01{ public static void main(String[] args){ Car car1 = new Car("奔馳","漏油GL300",66); car1.showInfo();
Car car2 = new Car("奔馳","漏油GL400",66); car2.showInfo();
System.out.println(Car.count); System.out.println(car1.count); System.out.println(car2.count);
} } |
類中包含靜態成員(靜態變量和靜態方法)和實例成員(實例變量和實例方法)
1.3.2 靜態方法
static 修飾的方法稱為靜態方法,形式
[修飾符] static 返回值類型 方法名(arg…){ |
靜態方法歸類所有,調用形式
[1] 類名.方法名() (推薦)
[2] 對象.方法名()
1.3.3 靜態方法訪問非靜態成員
public class Car{ String brand; String type; float price;
static int count = 0;
public Car(){ Car.count++; }
public Car(String brand,String type,float price){ this.brand = brand; this.type = type; this.price = price; Car.count++; }
public void showInfo(){ System.out.println("車輛信息:"); System.out.println("品牌:"+this.brand); System.out.println("型號:"+this.type); System.out.println("價格:"+this.price); System.out.println("我是第"+Car.count+"輛車"); }
public static int getCarCount(){ // 在靜態方法中訪問實例變量 // System.out.println("品牌:"+brand);
//showInfo(); //this.showInfo();
return Car.count; } } |
總結
[1]實例方法可以訪問靜態成員。
[2]靜態方法不能訪問非靜態成員。
1.3.4 類加載機制
Car car = new Car(…);
當實例化一個對象時,jvm首先把Car.class加載到方法區
[1]讀取Car.class 根據聲明的成員變量計算申請內存需要的字節數
[2]讀取Car.class 中的靜態成員,給靜態變量分配空間並初始化。
new Car 申請內存得到一個car對象,此時才有對象的空間。showInfo才可以通過car對象調用。
1.3.5 小結
|
1.4 代碼塊(B)
代碼塊通過{}聲明,根據其位置可以分為普通代碼塊、靜態代碼塊、構造代碼塊、同步代碼塊(多線程講解)
1.4.1 普通代碼塊
普通代碼塊一般存在於方法或者類、方法等的定義中,普通代碼塊形成一個作用域。
public class Test03{
public static void main(String[] args){
int count_1 = 10;
// 普通代碼塊 { int count_2 = 20; //System.out.println("count_1:"+count_1); //System.out.println("count_2:"+count_2); }
// error System.out.println("count_2:"+count_2);
} } |
1.4.2 構造代碼塊
構造代碼塊位於類中。構造代碼塊在構造方法前執行。構造一個對象執行一次。
public class Person{ String name; int age;
// 構造代碼塊 { System.out.println("構造代碼塊"); }
public Person(){ System.out.println("構造方法"); } public Person(String name,int age){ this.name = name; this.age = age; } } |
1.4.3 靜態代碼塊
靜態代碼塊位於類中,歸類所有,用static修飾。在類加載時執行,在構建多個對象時只執行一次。
public class Person{ String name; int age;
static{ System.out.println("靜態代碼塊"); }
public Person(){ System.out.println("構造方法"); } public Person(String name,int age){ this.name = name; this.age = age; } } |
總結
靜態代碼塊一般用於初始化靜態資源,構造代碼塊一般用於初始化實例成員。
1.5 封裝
封裝:將類的某些信息隱藏在類內部,不允許外部程序直接訪問,而是通過該類提供的方法來實現對隱藏信息的操作和訪問。
封裝的步驟
[1]屬性私有化
[2]提供公共的設置器和訪問器
[3]在設置器和訪問器中添加業務校驗邏輯
public class Dog{
// 【1】private 私有的,對外不可見 private String name; private int health; private int love; private String strain;
// 【2】提供公共的設置器(setter)和訪問器(getter) public void setName(String name){ // 【3】邏輯校驗 if(name.equals("")){ System.out.println("姓名不能為空."); }else{ this.name = name; } } public String getName(){ return this.name; }
public void setHealth(int health){ if(health < 0){ System.out.println("健康值不合法."); this.health = 0; }else{ this.health = health; } } public int getHealth(){ return this.health; }
public void setLove(int love){ if(love < 0){ System.out.println("親密度不合法."); this.love = 0; }else{ this.love = love; } } public int getLove(){ return this.love; }
public void setStrain(String strain){ if(strain.equals("")){ System.out.println("品種不能為空."); }else{ this.strain = strain; } } public String getStrain(){ return this.strain; }
public Dog(){
}
public Dog(String name,int health,int love,String strain){ this.setName(name); this.setHealth(health); this.setLove(love); this.setStrain(strain); }
public void showInfo(){ System.out.print("我的名字叫"+this.name); System.out.print(",健康值"+this.health); System.out.print(",親密度"+this.love); System.out.println(",我是一只"+this.strain); } } |
1.6 This關鍵字(下)
this表示對象本身。
[1] this調用屬性
[2] this調用方法
public Dog(String name,int health,int love,String strain){ this.setName(name); this.setHealth(health); this.setLove(love); this.setStrain(strain);
// showInfo(); this.showInfo(); } |
[3] this調用本類的構造方法,形式
this(arg1,arg2,…) |
public Dog(){
}
public Dog(String name,int health,int love){ this.setName(name); this.setHealth(health); this.setLove(love); }
public Dog(String name,int health,int love,String strain){ //this.setName(name); //this.setHealth(health); //this.setLove(love);
// this調用本類的其他構造方法 // System.out.println("test"); this(name,health,love); this.setStrain(strain);
// showInfo(); //this.showInfo(); } |
|
註意:this調用其他構造方法必須寫到構造方法的第一句。
1.7 靜態常量
在程序運行過程中,如果一個量的值不會發生改變,可以把該量聲明為靜態常量,用static final修飾。
public class Penguin{
private String name; private int health; private int love; private String gender;
static final String SEX_MALE = "雄"; static final String SEX_FEMALE = "雌";
public void setName(String name){ this.name = name; } public String getName(){ return this.name; }
public void setHealth(int health){ if(health>100 && health<1){ this.health = 60; System.out.println("健康值必須在1-100之間,默認為60"); }else{ this.health = health; } } public int getHealth(){ return this.health; }
public void setLove(String love){ this.love = love; } public int getLove(){ return this.love; }
public void setGender(String gender){ this.gender = gender; } public String getGender(){ return this.gender; }
public Penguin(){
} public Penguin(String name,String gender){ this.setName(name); this.setGender(gender); }
public Penguin(String name,int health,int love,String gender){ this(name,gender); this.setHealth(health); this.setLove(love); }
public void showInfo(){ System.out.print("我的名字叫"+name); System.out.print(",健康值"+health); System.out.print(",親密度"+love); System.out.println(",性別"+gender); }
} |
public class Test02{ public static void main(String[] args){
Penguin penguin = new Penguin("大腳",100,0,Penguin.SEX_MALE); } } |
構造方法、 This關鍵字 、static、封裝