![](/img/trans.png)
[英]Why the default constructor is not provided when typing an argument-ed constructor in java?
[英]Why default constructor is required in a parent class if it has an argument-ed constructor?
如果父类具有带参数的构造函数,为什么在父类中需要(显式)默认构造函数
class A {
A(int i){
}
}
class B extends A {
}
class Main {
public static void main(String a[]){
B b_obj = new B();
}
}
这将是一个错误。
这里有两个方面在起作用:
如果您确实明确指定了构造函数(如在A
),则 Java 编译器不会为您创建无参数构造函数。
如果您没有显式指定构造函数(如在B
),Java 编译器将为您创建一个无参数构造函数,如下所示:
B() { super(); }
(可访问性取决于类本身的可访问性。)
那是试图调用超类无参数构造函数 - 所以它必须存在。 您有三个选择:
A
显式提供无参数构造函数B
中显式提供无参数构造函数,该构造函数使用适当的int
参数显式调用基类构造函数。B
提供一个参数化构造函数,它调用基类构造函数如果父类具有带参数的构造函数,为什么在父类中需要(显式)默认构造函数
我会说这种说法并不总是正确的。 理想情况下它不是必需的。
规则是:如果您显式提供了带参数的构造函数,则该类无法使用默认构造函数(无参数)。
For Example :
class A {
A(int i){
}
}
class B extends A {
}
所以当你写
B obj_b = new B();
它实际上调用了java提供的隐式构造函数给B,B又调用了super(),理想情况下应该是A()。 但是由于您为 A 提供了带参数的构造函数,因此默认构造函数 i:e A() 对 B() 不可用。
这就是您需要为 B() 专门声明 A() 以调用 super() 的原因。
如果子类构造函数没有显式调用超类的其他构造函数,则每个子类构造函数都会调用超类的默认构造函数。 因此,如果您的子类构造函数显式调用您提供的超类构造函数(带参数),则超类中不需要无参数构造函数。 因此,将编译以下内容:
class B extends A{
B(int m){
super(m);
}
}
但是以下不会编译,除非您在超类中明确提供没有 args 构造函数:
class B extends A{
int i;
B(int m){
i=m;
}
}
假设您打算编写class B extends A
:
每个构造函数都必须调用超类构造函数; 如果不是,则隐式调用无参数超类构造函数。
如果(且仅当)一个类没有声明构造函数,Java 编译器会给它一个默认构造函数,它不带参数并调用超类的无参数构造函数。 在您的示例中, A
声明了一个构造函数,因此没有这样的默认构造函数。 类B
没有声明构造函数,但无法获得默认构造函数,因为它的超类没有可调用的无参数构造函数。 由于类必须始终具有构造函数,因此这是编译器错误。
Why default constructor is required(explicitly) in a parent class if it
has an argumented constructor
不必要!
现在在你的 B 班
class B extends A {
}
您尚未在 B 类中提供任何构造函数,因此将放置默认构造函数。 现在的规则是每个构造函数都必须调用它的超类构造函数之一。 在您的情况下,B 类中的默认构造函数将尝试调用 A 类(它的父类)中的默认构造函数,但由于您在 A 类中没有默认构造函数(因为您在 A 类中明确提供了一个带参数的构造函数,因此您将在 A 类中没有默认构造函数)你会得到一个错误。
你可能会做的是
在 A 类中不提供 args 构造函数。
A()
{
//no arg default constructor in Class A
}
要么
明确地在 B 中写入 no args 构造函数,并使用一些默认的 int 参数调用您的 super。
B()
{
super(defaultIntValue);
}
底线是,要创建一个对象,必须调用继承层次结构中每个父级的完全构造函数。 调用哪个实际上是您的设计选择。 但是,如果您没有明确提供任何 java 会将默认构造函数 super() 调用作为每个子类构造函数的第一行,现在如果您在超类中没有它,那么您将收到错误。
使用构造函数时需要注意一些事项,以及如何在基类和超类中声明它们。 这可能会变得有些混乱,因为超类或基类中构造函数的可用性或存在性可能有很多。 我将尝试深入研究所有可能性:
如果您在任何类(基类/超类)中显式定义构造函数,Java 编译器将不会在相应的类中为您创建任何其他构造函数。
如果您没有在任何类(基类/超类)中显式定义构造函数,Java 编译器将在相应的类中为您创建一个无参数的构造函数。
如果您的类是从超类继承的基类,并且您没有在该基类中显式定义构造函数,则编译器不仅会为您创建无参数构造函数(如上点),而且还会从超类隐式调用无参数构造函数。
class A { A() { super(); } }
如果 super() 被调用(由编译器显式或隐式调用),编译器将期望您的超类具有不带参数的构造函数。 如果它在你的超类中没有找到任何没有参数的构造函数,它会给你一个编译器错误。
类似地,如果调用 super(parameters) ,编译器将期望您的超类具有带参数的构造函数(参数的数量和类型应匹配)。 如果它在你的超类中找不到这样的构造函数,它会给你一个编译器错误。 ( Super(parameters) 永远不能被编译器隐式调用。如果需要,它必须显式地放入你的代码中。)
我们可以从上面的规则中总结出一些东西
另一件要注意的事情是,如果您的超类有一个私有构造函数,那么在您编译子类时会产生错误。 这是因为如果您不在子类中编写构造函数,它将调用超类构造函数,而隐式 super() 将尝试在超类中查找无参数构造函数但找不到。
说这个编译,你希望它打印什么?
class A{
A(int i){
System.out.println("A.i= "+i);
}
}
class B extends A {
public static void main(String... args) {
new B();
}
}
当 A 被构造为i
,必须传递一个值,但是编译器不知道它应该是什么,因此您必须在构造函数中明确指定它(任何构造函数,它都不必是默认的)
当我们有参数构造函数时。 我们通过设计明确绑定到消费者。 他不能在没有参数的情况下创建该类的对象。 有时我们需要强制用户提供价值。 对象只能通过提供参数(默认值)来创建。
class Asset
{
private int id;
public Asset(int id)
{
this.id = id;
}
}
class Program
{
static void Main(string[] args)
{
/* Gives Error - User can not create object.
* Design bound
*/
Asset asset1 = new Asset();/* Error */
}
}
连子类都不能创建。 因此,这是良好设计的行为。
扩展类时,会自动添加默认的超类构造函数。
public class SuperClass {
}
public class SubClass extends SuperClass {
public SubClass(String s, Product... someProducts) {
//super(); <-- Java automatically adds the default super constructor
}
}
但是,如果您重载了超类构造函数,这将取代默认值,因此调用super()
将导致编译错误,因为它不再可用。 然后,您必须显式添加重载的构造函数或创建一个无参数的构造函数。 请参阅以下示例:
public class SuperClass {
public SuperClass(String s, int x) {
// some code
}
}
public class SubClass extends SuperClass {
public SubClass(String s, Product... someProducts) {
super("some string", 1);
}
}
要么...
public class SuperClass {
public SuperClass() {
// can be left empty.
}
}
public class SubClass extends SuperClass {
public SubClass(String s, Product... someProducts) {
//super(); <-- Java automatically adds the no-parameter super constructor
}
}
因为如果您想阻止创建没有任何数据的对象,这是一种好方法。
当然,如果这样写它是一个错误,它不是JAVA。
如果您将使用 JAVA 语法,则不会出错。
如果在单独的文件/包中,A 类和 B 类对彼此一无所知。
A 类根本不需要默认构造函数,它只使用参数构造函数就可以正常工作。
如果 B 扩展了 A,您只需在 B 的构造函数中调用 super(int a) ,一切都很好。 对于不调用扩展超类的 super(空/或不)的构造函数,编译器将添加对 super() 的调用。
如需进一步阅读,请参阅使用关键字超级
我猜这是因为当您有一个空参数列表时,无法实例化超级变量。 对于空参数列表,我的意思是如果超类具有非参数构造函数,编译器可以添加隐式 super() 。
例如,如果您键入:
int a;
System.out.print(a);
你会得到一个错误,我认为是相同的逻辑错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.