本篇主要谈谈为何需要默认的无参构造函数,目录结构如下:
- 1、Java为什么需要默认的无参构造函数?
- 2、在Java中定义一个不做事且没有参数的构造方法的作用
- 3、无参构造器和默认构造器的区别
- 4、构造方法的作用是什么?若一个类没有声明构造方法,该程序能正确执行吗?为什么?
- 5、参考
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.
总结下大概是这几个原因:
- 类本身默认的实例化、初始化:对象的实例化一般都是通过 new 构造器的方式来进行的,如果自定义的类中没有显式提供构造器,则肯定需要一个默认的无参的空构造器用于 new 实例化、初始化(Java编译器插入的),不然就无法用正常的方式实例化了,例如私有的构造器。换个角度看,默认的无参空构造器使得类可以直接 new 实例化。
- 父类的实例化、初始化:Super must be instantiated before sub like parent must exists before child.[5] 子类的实例化必然是伴随着父类的先一步实例化。子类如果没有通过 super 来显式调用父类的构造器,则都会默认调用父类的无参构造器来进行父类的初始化。如果此时父类没有无参构造器,则会出现编译错误。除了基类 Object 的无参构造函数是空实现外,所有子类的默认的无参构造器都会通过 super() 先调用父类的无参构造器。另外,构造器调用是一个构造器调用链,只要没有指明需要调用的父类构造器,则默认都是调用父类的无参构造器。
- 反射的实例化:很多框架都使用了反射 Class.newInstance() 来进行实例化,使用的也是无参的构造器,然后通过setter设置内部属性,如果通过构造器,只能通过类型匹配来调用。
- 当然,并不是所有类都需要无参构造器,像有些类就必须指定初始化参数和有参构造器的,例如:
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、参考
- [1]Using the Keyword super https://docs.oracle.com/javase/tutorial/java/IandI/super.html
- [2]8.8.9. Default Constructor https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.8.9
- [3]Using the this Keyword https://docs.oracle.com/javase/tutorial/java/javaOO/thiskey.html
- [4]Creating Objects https://docs.oracle.com/javase/tutorial/java/javaOO/objectcreation.html
- [5]why does the subclass have to invoke the no args constructor in the super class? https://stackoverflow.com/questions/14251271/why-does-the-subclass-have-to-invoke-the-no-args-constructor-in-the-super-class
- [6]Difference between a no-arg constructor and a default constructor in Java https://stackoverflow.com/questions/27654167/difference-between-a-no-arg-constructor-and-a-default-constructor-in-java
- [7]Java default constructor https://stackoverflow.com/questions/4488716/java-default-constructor
- [8]Why do we need a default no argument constructor in Java? https://stackoverflow.com/questions/3078389/why-do-we-need-a-default-no-argument-constructor-in-java
- [9]How can a Java class have no no-arg constructor? https://stackoverflow.com/questions/5286348/how-can-a-java-class-have-no-no-arg-constructor