你什么时候用Java调用super()? 我在派生类的一些构造函数中看到它,但不是自动调用的每个父类的构造函数?为什么你需要使用超级?
答案 0 :(得分:44)
如果你提供这样的课程:
public class Foo
{
}
或者这个:
public class Foo()
{
public Foo()
{
}
}
编译器将为此生成代码:
public class Foo()
{
public Foo()
{
super();
}
}
因此,严格来说,对“super()”的调用始终存在。
在实践中,您应该只调用“super(...)”,其中有想要传递给父构造函数的参数。
调用“super()”(没有参数)没有错,但人们会嘲笑你: - )
答案 1 :(得分:23)
在这种情况下,您需要使用super()
:
public class Base {
public Base(int foo) {
}
}
public class Subclass extends Base {
public Subclass() {
super(15);
}
}
这是一个非常人为的例子,但是你需要调用super()
的唯一时间是你是从一个没有提供默认的无参数构造函数的类继承的。在这种情况下,您需要从子类的构造函数中显式调用super()
,传入满足基类构造函数所需的任何参数。此外,对super()
的调用必须是继承类的构造函数的 first 行。
答案 2 :(得分:2)
无需调用super()。
来自Accessing Superclass Members:
使用super(),调用超类无参数构造函数。使用super(参数列表),将调用具有匹配参数列表的超类构造函数。
注意:如果构造函数没有显式调用超类构造函数,Java编译器会自动插入对超类的无参数构造函数的调用。如果超类没有无参数构造函数,则会出现编译时错误。对象确实有这样的构造函数,因此如果Object是唯一的超类,则没有问题。
答案 3 :(得分:2)
如果你没有在构造函数中调用super,那么编译器将添加一个无参数的超级调用作为构造函数体的第一行的父构造函数。
就像之前发布的代码一样
public class Foo
{
}
或
public class Foo
{
public Foo()
{
}
}
编译器将生成符合Java规则的代码。所有对象都是java.lang.Object的子类,因此编译器将编译它,就像编写它一样
// All classes extend Object. This is Java, after all.
public class Foo extends java.lang.Object
{
public Foo()
{
// When constructing Foo, we must call the Object() constructor or risk
// some parts of Foo being undefined, like getClass() or toString().
super()
}
}
但是如果超类没有与参数匹配的构造函数,那么你必须调用适当的非匹配超类构造函数。
public class LightBlue extends java.awt.Color
{
public LightBlue()
{
// There is no Color() constructor, we must specify the suitable super class
// constructor. We chose Color(int red, int green, int blue).
super(172, 216, 230);
}
}
其他时候,也许有一个构造函数匹配子类的构造函数的签名,但无论出于何种原因,你不希望将参数直接传递给超类构造函数。
public class HSVColor extends Color
{
public HSVColor(int hue, int saturation, int value)
{
super(...code converting HSV to Red...,
...code converting HSV to Green...,
...code converting HSV to Blue);
}
}
如果忽略显式指定超类构造函数,则编译器会添加默认的no-arg超类构造函数。但是,如果该构造函数不存在,那么编译器将不会编译该类,因为不清楚哪个暴露的构造函数是正确的构造函数。
这是一种风格考虑因素,但您可能决定始终包含super()调用。如果您选择这样做,那将是因为您希望提醒读者必须将基类对象构建为子类对象的一部分,并且您希望显式创建特定的超类构造函数。传统上,一个总是包含的super()调用很奇怪,因为传统的代码只有在与“默认”行为不同时才输出。
答案 4 :(得分:1)
如前所述,如果构造函数没有显式调用带有或不带某个参数的super(),java将自动调用超类的默认构造函数。
但是,显式调用super()只是 - 显式。如果你知道超类的构造函数做了一些重要的事情,那么对于维护代码的人来说,首先调用super()(并且可能有副作用)是一个有用的提醒。这甚至可能是在调试时放置断点的有用位置。
答案 5 :(得分:1)
如果你有一个扩展另一个类的类而且父类没有默认的构造函数,那么你必须在Son的构造函数中使用super()来调用父类中的构造函数,并使用如下正确的参数:
class A
{
int a;
A(int value)
{
this.a=value;
System.out.println("A Constructor " + a );
}
}
class B extends A
{
int b;
B()
{
super(5);
this.b=10;
System.out.println("B Constructor " + b);
}
}
如果你想使用“this”调用calss中的另一个构造函数,你必须知道哟不能使用“super”和“this”。
答案 6 :(得分:1)
我想提供一些迄今尚未提及的信息。如果您在构造函数中使用this(...)
调用,则无法调用super(...);
这也包括Java自动插入无参数调用super();
以下示例说明了这一点,包括解释性说明:
public class B extends A {
private int x;
public B() {
// Java doesn't call super(); here, because
// of the call to this(...); below.
// You can't call super(...) here either,
// for the same reason.
this(42); // Calls public B(int x) below.
}
public B(int x) {
// Java does call super(); here.
// You can call super(...) here, if you want/need to.
// The net result of calling new B() above is that
// super(...) for class A only gets called once.
this.x = x;
}
}
答案 7 :(得分:0)
super()是隐式的。
答案 8 :(得分:0)
如果要调用超类的非默认构造函数,或者超类没有默认构造函数,可以使用参数调用super()。编译器只能插入默认的,无参数的super()构造函数。
答案 9 :(得分:0)
因为不会自动调用超类的构造函数。 例如,可能有几个构造函数,其中一些构造函数需要额外的参数。所以你并不总是有一个“空”的super()语句,但是这样的话:
public class DerivedClass extends SomeOtherClass
{
private String anotherParameter;
public DerivedClass(int parameterA, String parameterB, String anotherParameter)
{
super(parameterA, parameterB);
this.anotherParameter = anotherParameter;
}
}
编辑:我显然忘了说(或者我选择的单词并不好,但我不是母语,对不起),如果超级班不参加参数,对super()的调用将由java /编译器为您完成。 (现在我重新阅读了我的答案,我可以看到,听起来你总是要调用super()。)
答案 10 :(得分:0)
虽然super()
对编译器没有任何功能(超类默认构造函数是自动调用的),但它确实对我有很大帮助。它对我说:“不要删除空的构造函数。这是有原因的。”
一个完美的例子是你创建Spring托管bean或JPA实体的地方,你已经创建了一个参数化的构造函数。
@Entity
public class Portfolio {
...
public Portfolio() {
super(); // This says to me: DON'T DELETE!
}
/**
* Because there is now a parameterised constructor (me),
* the default constructor no longer exists. This means
* that for this example, you need an empty constructor in place (above)
**/
public Portfolio(String name) {
this.name = name;
}
}
答案 11 :(得分:0)
当我们想要从父类继承一些参数时调用Super。它不是强制性的,因为编译器总是调用默认构造函数。如果你想继承一个有一些参数的构造函数,那么你需要调用super。所以你可以使用它。