Java中super() 和 this() 的区别
super()
和 this()
都用于进行构造函数调用。 super()
用于调用基类的构造函数(即父类),而 this()
用于调用当前类的构造函数。
下面来详细看看它们:
super()
1、 super()
用于调用基类(父类)的构造函数。
// Java code to illustrate usage of super()
class Parent {
Parent()
{
System.out.println("Parent class's No " +
" arg constructor");
}
}
class Child extends Parent {
Child()
{
super();
System.out.println("Flow comes back from " +
"Parent class no arg const");
}
public static void main(String[] args)
{
new Child();
System.out.println("Inside Main");
}
}
运行输出结果如下:
Parent class's No arg constructor
Flow comes back from Parent class no arg const
Inside Main
程序执行流程:
- 在 main 中,我们做了一个
new Child()
语句,所以它调用了Child
类的无参数构造函数。 - 在里面有
super()
调用 Parent 类的无参数,因为编写了super()
并且没有参数,这就是它调用Parent
类的无参数构造函数的原因,因为有一个SOP
语句,因此它打印Parent
类的No arg
构造函数。 - 现在,随着 Parent 类的
No argument const
完成,flow 回到 Child 类的no argument
并且有一个SOP
语句,因此它打印Flow
从Parent class no arg const
返回。 - 在完成子类流的无参数构造函数之后,现在再次回到
main
并执行剩余的语句并在Main
中打印。
2、只能在构造函数内部使用 super()
,在其他任何地方都不能使用,即使在静态上下文中也不能在方法内部使用,并且 super()
应该是构造函数内部的第一个语句。
// Java program to illustrate usage of
// super() as first statement
class Parent {
Parent()
{
System.out.println("Parent class's No " +
"arg constructor");
}
}
class Child extends Parent {
Child()
{
// Uncommenting below line causes compilation
// error because super() should be first statement
// System.out.println("Compile Time Error");
super();
System.out.println("Flow comes back from " +
"Parent class no arg const");
}
public static void main(String[] args)
{
new Child();
System.out.println("Inside main");
}
}
运行输出结果:
Parent class's No arg constructor
Flow comes back from Parent class no arg const
Inside main
注意:
super()
应该是任何构造函数中的第一个语句。 它只能在构造函数内部使用,不能在其他任何地方使用。super()
仅用于引用父类(超类)的构造函数。
this()
this()
用于调用当前类的构造函数。
// Java code to illustrate usage of this()
class RR {
RR()
{
this(10);
System.out.println("Flow comes back from " +
"RR class's 1 arg const");
}
RR(int a)
{
System.out.println("RR class's 1 arg const");
}
public static void main(String[] args)
{
new RR();
System.out.println("Inside Main");
}
}
运行结果:
RR class's 1 arg const
Flow comes back from RR class's 1 arg const
Inside Main
程序执行流程:
- 首先从
main
开始,然后有一个语句new Child()
因此它调用Child
类的无参数构造函数,在里面有this(10)
它调用当前类的第一个参数(即 RR 类) - 由于编写了
this(10)
和 1 个参数,它调用 RR 类的 1 个参数构造函数。 因为有一个 SOP 语句,因此它打印 RR 类的1 arg const
。 - 随着 RR 类的 1 参数 const 完成,flow 回到 RR 类的无参数,因为有一个 SOP 语句,因此它打印 Flow 从 RR 类的
1 arg const
回来。 - 在完成 RR 类流的无参数构造函数之后,现在再次回到 main 并执行剩余的语句并打印
Inside Main
。
只能在构造函数中使用 this()
而不能在其他任何地方使用,即使在静态上下文中也不能在方法内部使用,并且 this()
应该是构造函数中的第一个语句。
// Java program to illustrate usage of
// this() as first statement
class RR {
RR()
{
// Uncommenting below line causes compilation
// error because this() should be first statement
// System.out.println("Compile Time Error");
this(51);
System.out.println("Flow comes back from RR " +
"class 1 arg const");
}
RR(int k)
{
System.out.println("RR class's 1 arg const");
}
public static void main(String[] args)
{
new RR();
System.out.println("Inside main");
}
}
运行结果如下:
RR class's 1 arg constructor
Flow comes back from RR class 1 arg const
Inside main
注意:
this()
应该是任何构造函数中的第一条语句。 它只能在构造函数内部使用,不能在其他任何地方使用。this()
仅用于引用当前类的构造函数。
关于 this() 和 super() 的要点
- 我们只能在构造函数中使用
super()
以及this()
一次。 如果使用super()
两次或this()
两次,或super()
后跟this()
, 或this()
后跟super()
,那么会立即得到编译时错误,即可以使用super()
或this()
作为构造函数中的第一个语句,但不是同时使用两个。 - 是否使用
super()
或this()
取决于您,因为如果不使用this()
或super()
,则默认情况下编译器会将super()
作为构造函数中的第一条语句。
// Java program to illustrate super() by default
// executed by compiler if not provided explicitly
class Parent {
Parent()
{
System.out.println("Parent class's No " +
"argument constructor");
}
Parent(int a)
{
System.out.println("Parent class's 1 argument" +
" constructor");
}
}
class Base extends Parent {
Base()
{
// By default compiler put super()
// here and not super(int)
System.out.println("Base class's No " +
"argument constructor");
}
public static void main(String[] args)
{
new Base();
System.out.println("Inside Main");
}
}
运行结果:
Parent class's No argument constructor
Base class's No argument constructor
Inside Main
程序执行流程:
- 在 main 有
new Base()
然后流程转到基类的无参数构造函数。 - 之后,如果不放
super()
或this()
代码,那么编译器默认放super()
。 - 所以流程转到
"Parent class’s No arg constructor"
而不是" 1 argument constructor"
。 - 之后它会打印 Parent 类的无参数构造函数。
- 之后,当 Parent() 构造函数完成时,流程再次回到基类的无参数构造函数并执行下一个 SOP 语句,即基类的无参数构造函数。
- 完成无参数构造函数流程后,再次返回
main()
并打印main()
内的剩余语句,即Inside main
。
但是,如果明确指定,可以在 super()
之前使用 this()
。
// Java program to illustrate recursive
// constructor call not allowed
class RR {
RR()
{
this(30);
}
RR(int a)
{
this();
}
public static void main(String[] args)
{
new RR();
}
}
运行结果:
Compile time error saying recursive constructor invocation
程序流程: 这里,上面从 main() 开始,然后流程转到 RR 类的 No arg 构造函数。 之后,有 this(30)
并且流转到 RR 的 1 arg 构造函数,因为有 this()
所以再次流转到基类的 No arg 构造函数,然后再次有了 this(30)
并再次流 到 Base 类的 1 个 arg 构造函数,它继续……就像一个递归。 所以它是无效的,这就是为什么得到编译时错误:递归构造函数调用。 所以java中不允许递归构造函数调用。