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中不允许递归构造函数调用。
极客教程