構造器、this關鍵字、setter和getter
阿新 • • 發佈:2022-05-18
構造器、this關鍵字、setter和getter
構造器
我們一直在學習怎麼封裝class,一個class封裝好之後的目的一般是建立例項物件,我們其實已經做過了。
Dog dog = new Dog();
new 一個物件的時候到底發生了什麼事情呢?
- java在new一個物件的時候,會先檢視物件所屬的類有沒有被載入到記憶體,如果沒有的話,就會先通過類的許可權定名來載入,這個過程我們後邊聊。
- 載入並初始化類完成後,再進行物件的建立工作。
我們先聊聊建立的過程:
- 在堆區分配物件需要的記憶體。
- 對所有例項變數賦預設值。
- 執行構造方法,比如我們可以使用構造方法賦值。(不太準確,以後會慢慢補充)
- 在棧區定義引用變數,然後將堆區物件的地址賦值給它。
構造方法,也叫構造器,會在new物件的時候主動被呼叫。
但是,事實上,我們並沒有看到任何構造方法。
每個java類,會預設送你一個構造方法,這個方法它是這個樣子的:
public Dog(){
}
我們可以寫出來,也可以不寫,這個構造方法什麼都沒做,我們可以想辦法讓它做一些事情,比如:
public Dog(){ name = "teddy"; age = 12; } public static void main(String[] args) { Dog dog = new Dog(); System.out.println(dog.name); System.out.println(dog.age); } 我們並沒有呼叫這個方法啊: 但是,結果卻出來了: teddy 12
當然如果我們想自己按照自己的意願去構造例項,我們還可以定義這樣的構造器:
同時new的時候就要傳遞引數了:
public Dog(String name,int age){ System.out.println("驗證構造方法被呼叫的時機:【"+ name + "】被建立!"); this.name = name; this.age = age; } public static void main(String[] args) { Dog dog = new Dog("jinmao",23); System.out.println(dog.name); System.out.println(dog.age); } 結果: 驗證構造方法被呼叫的時機:【jinmao】被建立! jinmao 23
此時,如果我們把那個沒有引數的構造器刪除,
你會發現已經不能這麼去new物件了。
【注】一旦自己寫了構造器,系統將不再贈送,所以我們一般【會自己補充上】。
#6、this關鍵字
- 記住一點:每一個方法都會預設傳入一個變數叫this,它永遠指向呼叫它的【當前例項】。
#(1)this訪問屬性和方法
寫段程式碼:
//構造方法和其他方法一樣可以過載,可以有引數,名字必須和類名一樣,不能有一點區別
public Dog(String name){
System.out.println("驗證構造方法被呼叫的時機:【"+ name + "】被建立!");
this.name = name;
}
public void eat(){
// this也可以在成員方法中使用
System.out.printf("【%s】再吃骨頭。",this.name);
}
public static void main(String[] args) {
//直接new物件看看new的時候是不是呼叫了構造方法,事實證明是的
new Dog("哈士奇").eat();
}
一個方法只有在呼叫的時候,才能明確方法中的【this】具體指向哪個例項物件。
我們可以使用this訪問當前物件的方法和屬性。
#(2)this訪問構造器
還可以訪問當前類的構造器:
//構造方法和其他方法一樣可以過載,可以有引數,名字必須和類名一樣,不能有一點區別
public Dog(String name){
System.out.println("驗證構造方法被呼叫的時機:【"+ name + "】被建立!");
this.name = name;
}
public Dog(){
this("default");
}
如果我們使用無參構造會傳入一個預設值,這就是典型的案例
this當做構造器只能放在第一行
#7、setter和getter
我們之前呼叫一個例項物件的屬性的時候,都是 dog.name
但事實上,java程式設計師從來不會這麼幹。
我們有這樣的規定,所有的屬性必須私有化,使用setter和getter賦值或者取值,
public class Dog {
//有哪些特點
//定義狗有顏色這個屬性
private String color;
//定義狗有種類這個屬性
private String type;
//定義狗有年齡這個屬性
private int age;
//java約定使用setter和getter方法進行屬性的取值和賦值
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//..狗還有很多屬性和方法,我們無法一一列舉
}
為什麼呢?
- getter方法能夠按照客戶的期望返回格式化資料。
- setter方法可以限制和檢驗setter方法傳入的引數,隱藏物件內部資料結構。
- 屬性不具備多型性。
舉個例子:
public class Girl {
private int age;
public int getAge() {
// 你問我多大了,真實年齡大於18歲,都是18歲
if(this.age > 18){
return 18;
}
return age;
}
public void setAge(int age) {
// 每過一年,如果我超過了18歲,我永遠是18歲。
if(age > 18){
this.age = 18;
}
this.age = age;
}
}
所以,正確的定義一個類,一定是
- 所有的屬性私有化。
- 每個屬性都有對應的getter和setter放。
這是規矩,你得遵守。
package com.ydlclass;
public class Girl {
//第一塊成員變數
private String name;
private int age;
private int weight;
//第二塊構造器
public Girl(){
}
public Girl(String name){
this.name = name;
}
public Girl(int age,int weight){
this.age = age;
this.weight = weight;
}
//第三塊成員方法
int feeling = 0;
public void happy(int feeling){
if (feeling >= 60){
System.out.println(name+"很開心!");
}else if (feeling >= 0 & feeling < 60){
System.out.println(name+"很平靜!");
}else {
System.out.println(name+"很傷心!");
}
}
//第四塊get和set
public void setName(String name){
this.name = name;
}
public String getName() {
return this.name;
}
public void setAge(int age){
this.age = age;
}
public int getAge() {
return this.age;
}
public void setWeight(int weight){
this.weight = weight;
}
public int getWeight(){
return this.weight;
}
}
package com.ydlclass;
public class Test {
public static void main(String[] args) {
Girl girl = new Girl();
girl.setName("安妮");
girl.setAge(19);
girl.setWeight(50);
System.out.println("女孩的名字叫:"+girl.getName());
System.out.println("她的年齡:"+girl.getAge()+"歲");
System.out.println("她的體重:"+girl.getWeight()+"kg");
girl.happy(60);
}
}
女孩的名字叫:安妮
她的年齡:19歲
她的體重:50kg
安妮很開心!
Process finished with exit code 0