Java Can';t直接调用超类型构造函数-为什么不?
我有以下Java示例类:Java Can';t直接调用超类型构造函数-为什么不?,java,constructor,Java,Constructor,我有以下Java示例类: public class A { } public class Super { protected Super() { } public Super(A a) { } } public class Sub extends Super { } public class Consumer { public Consumer() { Sub sub = new Sub(new A()); //compiler error
public class A { }
public class Super {
protected Super() { }
public Super(A a) { }
}
public class Sub extends Super { }
public class Consumer {
public Consumer() {
Sub sub = new Sub(new A()); //compiler error
}
}
编译器错误声明参数不能应用于Sub中的默认构造函数,这是完全可以理解的
我好奇的是这个决定背后的理由。Java在Sub
中生成默认的空构造函数;在这种情况下,为什么不能称之为幕后呢?这主要是一种理智的手牵手,还是有技术上的原因
编辑
我知道这是一种语言限制。我很好奇为什么这是一种语言限制
编辑2
看起来,就像通常的情况一样,我离实际使用的代码太近了,看不到全局。我在下面的答案中贴了一个反例,说明了为什么这是一件坏事
public class Sub extends Super { }
没有构造函数子(A),它只有默认构造函数子()
构造函数不是继承的。您已经覆盖了默认的公共构造函数,因此没有任何可调用的内容 所以Sub类等价于
public class Sub extends Super
{
protected Sub(){}
public Sub(A a) { }
}
那是因为
- Sane行为-按照程序员指定的行为,它还遵循OOP语言中的继承概念
- 基类需要调用超级构造函数,以确保正确实例化对象。例如,考虑:
class Super {
final String field1;
public Super(String field1) {
this.field1 = field1;
}
...
}
class Base extends Super {
final String field2;
public Base(String field2) {
this.field2 = field2;
}
...
}
Base
的构造函数是否覆盖了Super
构造函数?如果是这样,那么field1就不再保证被初始化,这使得继承的方法表现出意外的行为
当您向子类添加非默认构造函数时,继承的构造函数就会停止工作。我认为,如果将它添加到语言中,这将是一个令人困惑且几乎没有用处的功能,尽管从技术上讲,我看不出为什么它不可能实现。我认为这是一个易读性和不假设意图的问题。你说 Java生成默认的空构造函数;在这种情况下,为什么不能称之为幕后呢 然而,对我来说,Java隐式调用
Super(A)
构造函数“幕后”比调用Super()
构造函数更有意义,忽略A
就在这里。对于这种情况下应该(或可能)发生什么,我们已经有了两种截然不同的假设
Java语言的核心原则之一是透明性。程序员应该尽可能通过查看代码来了解将要发生的事情,有时会以牺牲语法层面的便利性或魔力为代价
与此类似的一个原则是不假设意图:在程序员的意图看起来模棱两可的情况下,Java语言有时会倾向于编译错误,而不是通过某种(任意或其他)选择算法自动选择默认值;我同意其他几个答案,这可能在语义上令人困惑 考虑以下示例:
public class A { }
public abstract class Super {
protected Super() {
// perform time consuming, destructive, or
// otherwise one-time operations
}
public Super(A a) {
this();
// perform A-related construction operations
}
}
public class Sub extends Super { }
public class Consumer {
public Consumer() {
Sub sub = new Sub(new A());
}
}
当构造Sub
时,在这种情况下将调用Sub
上的默认构造函数,它将链接到Super
上的默认构造函数(因为这是语言定义的魔力)。然后,对Super(A)
的调用将调用设计为在构造时运行一次的逻辑。这显然不是开发者的意图
即使没有
Super(A)
构造函数中的this()
调用,也无法确定开发人员的意图;由于某些原因,构造器可能相互排斥。这是好的观点,但您似乎误解了我的说法。我会更新它,让它更清楚。这可能不会改变你的论点…这是Jon Skeet的观点我对你的编辑感到困惑。你想知道为什么当你用一个参数调用一个构造函数时,一个没有参数的默认构造函数不能在它的位置被调用?显然,程序员并没有试图调用完全忽略其参数的构造函数,否则他就不会指定参数!“创建默认无参数构造函数”和“为父级中的每个构造函数创建阴影构造函数”类型之间存在差异。并没有太大的魔力,因为Java并没有做到这一点。除了Java冗长语法的另一个方面(让人恼火的是),没有关于“手持”的内容;-)(构造函数从来都不是虚拟的/重写的。)我想知道为什么不能为Sub
调用默认构造函数,并将参数传递给Super
。当我这样想的时候,我认为这实际上是一种情况,如果我不必一直指定默认构造函数来将这些类与GSON一起使用,我就不会遇到这种情况。但是,考虑到这一点,我想我已经回答了自己的问题——当Java在Sub
中构建默认构造函数时,它会自动在Super
中包含对默认构造函数的调用。因此,如果调用Super(A)
构造将发生两次。@JonathanSpooner-感谢链接到Jon的答案,但这不是完全相同的问题。这个反例的问题是它不涉及默认的构造函数。您认为此代码有问题是正确的;它甚至不会编译。但是,我的问题是关于默认构造函数的。您的示例之所以有效,是因为Sub没有构造函数,如果构造函数仅在这些情况下继承,这将是一个令人困惑的特性。我的示例之所以有问题,只是因为Sub
没有构造函数。我同意你的说法,这会让人困惑,但这个问题是想找出为什么会让人困惑。@mikek3332002:我想我们只能调用超类构造函数