摘要:Java 也采用了構造器,并且還提供了一個垃圾收集器(garbage collector),當不再使用記憶體資源的時候,垃圾收集器會自動將其釋放,
本文分享自華為云社區《一文帶你了解 Java 中的構造器》,作者: 宇宙之一粟 ,
C ++ 引入了構造器(constructor,也叫建構式)的概念,它是在創建物件時被自動呼叫的特殊方法,
Java 也采用了構造器,并且還提供了一個垃圾收集器(garbage collector),當不再使用記憶體資源的時候,垃圾收集器會自動將其釋放,
構造器定義
在 Java 中,可以通過撰寫構造器來確保每個物件的初始化,但是這里有兩個問題:
- 這個構造器使用的任何名字都有可能與類里某個成員相沖突;
- 編譯器負責呼叫構造器,所以它必須始終知道應該呼叫哪個方法,
C++ 語言采用的方案就是將構造器和類的名字定義相同,Java 也采用了這個方案,
構造器的作用是用來建立一個新的類的實體,當一個物件被創建時,JVM 使用一個建構式,并為其分配記憶體空間,
語法結構
class ClassName { ClassName() { } }
例如,在下面的示例中,我們創建了一個名為 ReLearnConstructor 的建構式,在建構式內部,我們正在初始化 hello 變數的值,:
public class ReLearnConstructor { String hello; // 屬性 // 構造器 public ReLearnConstructor() { hello = "Hello, Constructor!"; } public static void main(String[] args) { ReLearnConstructor rc = new ReLearnConstructor(); System.out.println(rc.hello); } }
注意創建 ReLearnConstructor 類的物件的陳述句:ReLearnConstructor rc = new ReLearnConstructor();
在這里,當創建物件時,呼叫 ReLearnConstructor 建構式,并且,hello 變數的值被初始化,
因此列印的 hello 的值為:
構造器目的
建構式的目的是初始化物件的狀態,為所有宣告的屬性賦值,如果我們沒有自定義建構式,JVM 就會為這些屬性分配默認值,
原始型別的默認值:
- 整數型別是 0
- 浮點型別是 0.0
- 布爾型別是 false
對于其他 Java 參考型別,默認值是null,這意味著參考型別的屬性沒有被分配任何值,
后面可以用代碼查看這些默認值,
構造器分類
在 Java 中,有三種型別的構造器:
- 無參構造器
- 有參構造器
- 默認構造器
無參構造器
與方法類似,Java 建構式可能有引數,也可能沒有任何引數,如果建構式不接受任何引數,則稱為無引數構造器,例如上述代碼中 ReLearnConstructor 構造器就是:
// 無參構造器 public ReLearnConstructor() { hello = "Hello, Constructor!"; }
有參構造器
字面理解,具有引數的建構式稱為有引數構造器,那為什么需要使用有參構造器?
有參構造器可用于為不同物件提供不同初始化的值, 例如:
public class ReLearnConstructor { String languages; // 接受單個引數的構造器 public ReLearnConstructor(String lang) { languages = lang; System.out.println("我在學習 " + languages + " 語言!"); } public static void main(String[] args) { // 向構造器中傳入不同的值 ReLearnConstructor rc1 = new ReLearnConstructor("Java"); ReLearnConstructor rc2 = new ReLearnConstructor("Go"); ReLearnConstructor rc3 = new ReLearnConstructor("Python"); } }
運行結果:
默認構造器
如果我們不創建任何建構式,Java 編譯器會在程式執行期間自動創建一個無引數建構式,這個建構式稱為默認建構式,來看一個例子;
public class ReLearnConstructor { String languages; int a; boolean b; float c; public static void main(String[] args) { ReLearnConstructor rc = new ReLearnConstructor(); System.out.println("默認值:"); System.out.println("languages:" + rc.languages); System.out.println("a:" + rc.a); System.out.println("b:" + rc.b); System.out.println("c:" + rc.c); } }
運行結果:
默認值: languages:null a:0 b:false c:0.0
可以看到,我們還沒有創建任何建構式,因此,Java 編譯器會自動創建默認建構式,上述表格得以印證,
原生方法和構造器的區別
- 建構式必須與在 Java 中定義的類具有相同的名稱
- 當方法沒有回傳任何值時,建構式不會回傳任何型別,而方法則具有回傳型別或 void
- 在物件創建時,僅呼叫建構式一次,而方法可以被呼叫任何次數
如果我們不用構造器來給屬性賦值的話,可以先使用 new 運算子獲取類的實體,并使用類的 setter 方法設定值,如下:
import java.util.Arrays; class Person { private String name; private int age; @Override public String toString() { return Arrays.asList(name, String.valueOf(age)).toString(); } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } // getters } // Initialize an object in Java class Main { public static void main(String[] args) { Person person = new Person(); person.setName("Yuzhou1su"); person.setAge(22); System.out.println(person); } }
通過構造器進行初始化就可以省去我們的 setter 方法,
如下的例子:
import java.util.Arrays; class Person { private String name; private int age; // 構造器 public Person(String name, int age) { this.name = name; this.age = age; } public String toString() { return Arrays.asList(name, String.valueOf(age)).toString(); } } class SimpleConstructor { public static void main(String[] args) { Person person = new Person("Yuzhou1su", 22); System.out.println(person); } }
運行結果:
[Yuzhou1su, 22]
構造器多載
與 Java 方法多載類似,我們也可以創建兩個或多個具有不同引數的建構式,這稱為建構式多載,
public class ReLearnConstructor { String language; public ReLearnConstructor() { this.language = "Java"; } // 構造器 public ReLearnConstructor(String language) { this.language = language; } public void getName() { System.out.println("編程語言:" + this.language); } public static void main(String[] args) { ReLearnConstructor rc1 = new ReLearnConstructor(); ReLearnConstructor rc2 = new ReLearnConstructor("Python"); rc1.getName(); rc2.getName(); } }
在上面的例子中,我們有兩個建構式:ReLearnConstructor() 和 ReLearnConstructor(String language),在這里,兩個建構式都用不同的值初始化變數語言的值,根據創建物件時傳遞的引數,呼叫不同的建構式,分配不同的值,
運行結果:
編程語言:Java
編程語言:Python
拷貝構造器
Java 中的拷貝構造方法是一種使用該類的一個物件構造另外一個物件的構造方法,
復制建構式是一種特殊建構式,用于將新物件創建為現有物件的副本,它只需要一個引數,它將是同一類的另一個實體,我們可以使用 this() 陳述句從復制建構式中顯式呼叫另一個建構式:
public class ReLearnConstructor { private String language; // 構造器 public ReLearnConstructor(String language) { this.language = language; } // 拷貝構造器 public ReLearnConstructor(ReLearnConstructor rc) { this.language = rc.language; } public void getName() { System.out.println("編程語言:" + this.language); } public static void main(String[] args) { ReLearnConstructor rc = new ReLearnConstructor("Python"); ReLearnConstructor copyOfrc = new ReLearnConstructor(rc); rc.getName(); copyOfrc.getName(); } }
運行結果:
編程語言:Python
編程語言:Python
當需要拷貝一個帶有多個成員變數的復雜物件或者想構造已存在物件的深拷貝物件時非常有用,
匿名內部類
除了上文介紹的使用構造器的方法,另一種初始化物件的方法是使用“雙大括號初始化”,這將創建一個匿名內部類,其中只有一個實體初始化程式,建議不要使用這種方法,
import java.util.Arrays; class Person { private String name; private int age; @Override public String toString() { return Arrays.asList(name, String.valueOf(age)).toString(); } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } // getters } // Initialize an object in Java class Main { public static void main(String[] args) { // Anonymous class Person person = new Person() {{ // Initializer block setName("Yuzhou1su"); setAge(22); }}; System.out.println(person); } }
總結
- 實體化物件時會隱式呼叫建構式,
- 創建建構式的兩條規則是:建構式的名稱應與類相同,Java 建構式不能有回傳型別,
- 如果一個類沒有建構式,Java 編譯器會在運行時自動創建一個默認建構式,默認建構式使用默認值初始化實體變數,例如 int 變數將被初始化為 0
- 建構式型別:
- 無參構造器 - 不接受任何引數的建構式引數化建構式
- 接受引數的構造器 - 接受引數的建構式
- 默認構造器 - 如果沒有明確定義,Java 編譯器會自動創建一個建構式,
- 建構式不能被 abstract、static 或 final 修飾
編譯器會報如下錯誤:
Illegal modifier for the constructor in type ReLearnConstructor; only public, protected & private are permitted
- 建構式可以多載但不能被覆寫
點擊關注,第一時間了解華為云新鮮技術~
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/508053.html
標籤:Java
