Java类的默认构造函数

什么情况下存在默认构造函数

说明

如果一个Java类没有显式包含构造函数的声明,那么隐含着有一个默认构造函数。

示例

定义一个类B,没有显式声明构造函数,所以存在一个默认构造函数:

package com.thb;

public class B {

	public void method() {}
}

定义一个类C,显式声明了一个带参数的构造函数,所以就不存在默认构造函数:

package com.thb;

public class C {
	private String msg;

	public C(String msg) {
		this.msg = msg;
	}
	
	public void method() {}
}

定义一个类Test1 ,调用类B和类C:

package com.thb;

public class Test1 {
		
	public static void main(String[] args) {
		// 类B没有声明构造函数,所以会隐含着有一个默认构造函数
		B b = new B();
		b.method();
		
		// 如果去掉下面代码前面的注释就会编译出错,因为类C中已经明确声明了一个带参数的构造
		// 函数,就不会有默认构造函数了
		// C c = new C();  
		C c = new C("hello");  // 调用类C声明的构造函数
		c.method();		
	}

默认构造函数的形式

一个顶层类、成员类、局部类的默认构造函数形式如下:

默认构造函数的访问修饰符

说明

默认构造函数的访问修饰符和类的访问修饰符相同;如果类没有显式声明访问修饰符,那么默认构造函数是包的访问修饰符。

示例—类用public修饰

定一个类B,用public修饰,没有声明构造函数,所以存在一个默认构造函数:

package com.thb;

public class B {

	public void method() {}
}

打开类B编译后的class文件,可以发现,因为类B的访问控制修饰符是public,所以默认构造函数的访问控制修饰符也是public:

// Compiled from B.java (version 18 : 62.0, super bit)
public class com.thb.B {
  
  // Method descriptor #6 ()V
  // Stack: 1, Locals: 1
  public B();
    0  aload_0 [this]
    1  invokespecial java.lang.Object() [8]
    4  return
      Line numbers:
        [pc: 0, line: 3]
      Local variable table:
        [pc: 0, pc: 5] local: this index: 0 type: com.thb.B
  
  // Method descriptor #6 ()V
  // Stack: 0, Locals: 1
  public void method();
    0  return
      Line numbers:
        [pc: 0, line: 5]
      Local variable table:
        [pc: 0, pc: 1] local: this index: 0 type: com.thb.B
}

示例—类没有显式声明访问控制修饰符

定义类D,没有显式声明访问控制修饰符,即表示是包访问控制:

package com.thb;

class D {

}

打开类D编译后的class文件,可以发现,默认构造函数也没有注明访问控制修饰符,即是包访问控制:

// Compiled from D.java (version 18 : 62.0, super bit)
class com.thb.D {
  
  // Method descriptor #6 ()V
  // Stack: 1, Locals: 1
  D();
    0  aload_0 [this]
    1  invokespecial java.lang.Object() [8]
    4  return
      Line numbers:
        [pc: 0, line: 3]
      Local variable table:
        [pc: 0, pc: 5] local: this index: 0 type: com.thb.D
}

默认构造函数没有形式参数(非private的内部成员类除外)

说明

默认构造函数没有形式参数,非private的内部成员类除外。
非private的内部成员类的默认构造函数有一个形式参数,这个形式参数类型是包裹内部成员类的外部类。

示例:非private的内部成员类的默认构造函数

定义一个类E,在其内部定义一个非private的成员类AnotherInE :

package com.thb;

public class E {

	class AnotherInE {
		
	}
}

打开类E 编译后的class文件,可以发现它有一个没有形式参数的默认构造函数:

// Compiled from E.java (version 18 : 62.0, super bit)
public class com.thb.E {
  
  // Method descriptor #6 ()V
  // Stack: 1, Locals: 1
  public E();
    0  aload_0 [this]
    1  invokespecial java.lang.Object() [8]
    4  return
      Line numbers:
        [pc: 0, line: 3]
      Local variable table:
        [pc: 0, pc: 5] local: this index: 0 type: com.thb.E

  Inner classes:
    [inner class info: #17 com/thb/E$AnotherInE, outer class info: #1 com/thb/E
     inner name: #19 AnotherInE, accessflags: 0 default]

Nest Members:
   #17 com/thb/E$AnotherInE
}

打开内部类AnotherInE 编译后的class文件,可以发现内部成员类的默认构造函数有一个形式参数,类型是包裹它的类E:

// Compiled from E.java (version 18 : 62.0, super bit)
class com.thb.E$AnotherInE {
  
  // Field descriptor #6 Lcom/thb/E;
  final synthetic com.thb.E this$0;
  
  // Method descriptor #8 (Lcom/thb/E;)V
  // Stack: 2, Locals: 2
  E$AnotherInE(com.thb.E arg0);
     0  aload_0 [this]
     1  aload_1 [arg0]
     2  putfield com.thb.E$AnotherInE.this$0 : com.thb.E [10]
     5  aload_0 [this]
     6  invokespecial java.lang.Object() [12]
     9  return
      Line numbers:
        [pc: 0, line: 5]
      Local variable table:
        [pc: 0, pc: 10] local: this index: 0 type: com.thb.E.AnotherInE

  Inner classes:
    [inner class info: #1 com/thb/E$AnotherInE, outer class info: #22 com/thb/E
     inner name: #24 AnotherInE, accessflags: 0 default]

Nest Host: #22 com/thb/E
}

默认构造函数没有throws 子句

默认构造函数体的内容

说明

如果声明的是基本类Object,那么默认构造函数体是空的。如果声明的是其它的类,在默认构造函数体内调用父类的没有形式参数的构造函数。

示例----在子类的默认构造函数体内调用父类的没有形式参数的构造函数

定义类B:

package com.thb;

public class B {

	public void method() {}
}

定义B的子类BB:

package com.thb;

public class BB extends B {

}

打开类BB编译后的class文件,可以发现它的默认构造函数体内调用父类B的没有形式参数的构造函数:

// Compiled from BB.java (version 18 : 62.0, super bit)
public class com.thb.BB extends com.thb.B {
  
  // Method descriptor #6 ()V
  // Stack: 1, Locals: 1
  public BB();
    0  aload_0 [this]
    1  invokespecial com.thb.B() [8]
    4  return
      Line numbers:
        [pc: 0, line: 3]
      Local variable table:
        [pc: 0, pc: 5] local: this index: 0 type: com.thb.BB
}

编译出错示例—子类没有显式定义造函数,但父类没有这样一个构造函数:无形式参数并且无throws 子句

定义一个类B,显式定义了一个带形式参数的构造函数,但没有定义无形式参数且没有throws 子句的构造函数:

package com.thb;

public class B {
	private String name;
	
	public B(String name) {
		this.name = name;
	}

	public void method() {}
}

定义类B的子类BB,BB中没有显式定义构造函数,编译出错:
Java类的默认构造函数_第1张图片
Java类的默认构造函数_第2张图片

你可能感兴趣的:(java,开发语言)