Java基礎(005):Java為什么需要默認的無參構造函數


  本篇主要談談為何需要默認的無參構造函數,目錄結構如下:

 

1、Java為什么需要默認的無參構造函數?

  根據Oracle官網[1]Using the Keyword super https://docs.oracle.com/javase/tutorial/java/IandI/super.html


If a constructor does not explicitly invoke a superclass constructor, the Java compiler automatically inserts a call to the no-argument constructor of the superclass. If the super class does not have a no-argument constructor, you will get a compile-time error. Object does have such a constructor, so if Object is the only superclass, there is no problem.

If a subclass constructor invokes a constructor of its superclass, either explicitly or implicitly, you might think that there will be a whole chain of constructors called, all the way back to the constructor of Object. In fact, this is the case. It is called constructor chaining, and you need to be aware of it when there is a long line of class descent.


  還有Java語言規范中的說明[2]8.8.9. Default Constructor https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.8.9


If a class contains no constructor declarations, then a default constructor with no formal parameters and no throws clause is implicitly declared.

If the class being declared is the primordial class Object, then the default constructor has an empty body. Otherwise, the default constructor simply invokes the superclass constructor with no arguments.

It is a compile-time error if a default constructor is implicitly declared but the superclass does not have an accessible constructor (§6.6) that takes no arguments and has no throws clause.


   總結下大概是這幾個原因:

  1. 類本身默認的實例化、初始化:對象的實例化一般都是通過 new 構造器的方式來進行的,如果自定義的類中沒有顯式提供構造器,則肯定需要一個默認的無參的空構造器用於 new 實例化、初始化(Java編譯器插入的),不然就無法用正常的方式實例化了,例如私有的構造器。換個角度看,默認的無參空構造器使得類可以直接 new 實例化。
  2. 父類的實例化、初始化:Super must be instantiated before sub like parent must exists before child.[5] 子類的實例化必然是伴隨着父類的先一步實例化。子類如果沒有通過 super 來顯式調用父類的構造器,則都會默認調用父類的無參構造器來進行父類的初始化。如果此時父類沒有無參構造器,則會出現編譯錯誤。除了基類 Object 的無參構造函數是空實現外,所有子類的默認的無參構造器都會通過 super() 先調用父類的無參構造器。另外,構造器調用是一個構造器調用鏈,只要沒有指明需要調用的父類構造器,則默認都是調用父類的無參構造器。
  3. 反射的實例化:很多框架都使用了反射 Class.newInstance() 來進行實例化,使用的也是無參的構造器,然后通過setter設置內部屬性,如果通過構造器,只能通過類型匹配來調用。
  4. 當然,並不是所有類都需要無參構造器,像有些類就必須指定初始化參數和有參構造器的,例如:
FileInputStream fileInputStream=new FileInputStream(); // 到底是誰的輸入流??

  

2、在Java中定義一個不做事且沒有參數的構造方法的作用(來自網絡)

  或者說:自定義無參空構造器的作用

  • 前面第一段英文提到了:如果類中沒有顯式調用父類的構造器,則默認是執行父類的無參構造器,如果此時父類沒有無參構造器,則會編譯錯誤。
  • 如果類中沒有自定義構造器,則編譯器會插入默認構造器;當類中有自定義構造器時,編譯器只會在沒有顯式調用父類構造器的構造器的最開始處加入對父類構造器的調用 super() 。因此一般會額外定義一個不做事且沒有參數的構造方法。
  • 可以說無參構造器(不管有沒有做事)是用於默認的實例化調用的。
  • 其他見 擴展2:無參構造器和默認構造器的區別

 

3、無參構造器和默認構造器的區別

  • 無參構造器
    • 自定義的空參構造器(沒有參數列表),可以執行自定義的初始化,甚至什么都不做;
    • 自定義構造器沒有顯式調用父類構造器的,編譯器默認都會在自定義的構造器內部最前面添加 super() ;
    • 當顯式自定義了構造器之后(無論是有參還是空參,抑或都有),編譯器便不再隱式插入默認構造器。
  • 默認構造器
    • 當類中沒有顯式定義任何構造器時,由Java編譯器默認提供的無參構造器;
    • 除了基類 Object 外,其他類內部的默認構造器都只有直接調用父類的空參構造器,即函數體是 super() ;
    • 當顯式自定義了構造器之后(無論是有參還是空參,抑或都有),編譯器便不再隱式插入默認構造器。
    • Oracle官網[4]:All classes have at least one constructor. If a class does not explicitly declare any, the Java compiler automatically provides a no-argument constructor, called the default constructor. This default constructor calls the class parent's no-argument constructor, or the Object constructor if the class has no other parent. If the parent has no constructor (Object does have one), the compiler will reject the program.

 

4、構造方法的作用是什么?若一個類沒有聲明構造方法,該程序能正確執行嗎?為什么?

  • 構造方法的作用主要就是實例化和初始化(默認初始化或者指定初始化)。
  • 如果沒有聲明構造器,則Java編譯器會自動添加默認構造器用於默認的初始化和實例化,同樣也可以正確執行,只需要保證所有父類都有無參構造器即可。

 

5、參考

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM