在这种情况下是不是需要实现标准构造函数(Java)?

Posted

技术标签:

【中文标题】在这种情况下是不是需要实现标准构造函数(Java)?【英文标题】:Is implementation of a standard constructor (Java) necessary in this case?在这种情况下是否需要实现标准构造函数(Java)? 【发布时间】:2015-10-19 00:16:43 【问题描述】:

我有三个这样的课程:

public abstract class ClassA extends ClassX 
    protected ClassA() 
        super();
    
    // more code

public class ClassB extends ClassA 
    public ClassB() 
        super();
    
    // more code

public abstract class ClassC extends ClassB 
    public ClassC() 
        super();
    
    // more code

我想说ClassC 的标准构造函数不是必需的,因为Java 会在编译期间插入它,因为此类中没有其他构造函数,对吧? 如果属实,我可以将ClassC 的代码简化为:

public abstract class ClassC extends ClassB 
    // more code

现在我想说我不能对ClassB 做同样的事情,因为构造函数的可访问性从protected 增加到public

我之所以这么问,是因为我对此不是 100% 确定,并认为我可能会遗漏一些东西。特别是关于将插入ClassC 的标准构造函数,如果我自己不实现它。在这种情况下,它将具有可访问性 public,因为它继承自 ClassB。对吗?

所以我的问题是:我可以在不更改代码的情况下删除 ClassC 中的构造函数(尤其是构造函数的可访问性)吗?我不能删除 ClassB 的构造函数是否正确。

【问题讨论】:

您可能应该提出单独的问题 :) 长话短说。你的假设似乎是正确的 你是对的 :-)。所以我的问题主要是:我可以在不更改代码的情况下删除 ClassC 中的构造函数吗(将编辑问题)。 我不确定你的意思是什么: > 现在我想说我不能对 ClassB 做同样的事情,因为构造函数的可访问性从受保护增加到公共。默认构造函数是包私有的。 @RazvanManolescu:如果默认构造函数是包私有的,那意味着,如果我删除 ClassC 的构造函数,java 将不会添加默认构造函数,因为它不能具有较低的可访问性(包私有),或者它将添加一个不是包私有而是公共的构造函数(因为它必须等于或高于它的父级)。你会说Java插入哪一个? 【参考方案1】:

现在我想说我不能对 ClassB 做同样的事情,因为构造函数的可访问性从受保护增加到公共。

这无关紧要,因为它是一个抽象类。不能直接调用构造函数 - 它仅在从子类构造函数链接时使用。

因此,虽然技术上会有所不同,但如果您删除所有构造函数声明,您的代码将实际上相同。

但就默认构造函数的可访问性而言,JLS 8.8.9 是这里的权威:

如果类不包含构造函数声明,则隐式声明默认构造函数。***类、成员类或本地类的默认构造函数形式如下:

默认构造函数具有与类相同的可访问性(第 6.6 节)。 ...

【讨论】:

"默认构造函数与类具有相同的可访问性" --> 很有帮助,非常感谢! 我的困惑是因为我认为默认构造函数继承了其父类的无参数、无抛出语句构造函数的可访问性。由于文档说它继承了类本身的可访问性,现在很清楚了。 关于 ClassA 是抽象的好评论 - 你是对的,那么我也可以删除那里的构造函数。想知道是谁把它放在那里的:-)【参考方案2】:

类的默认构造函数与类本身具有相同的访问修饰符的规则简单直观。但是请注意,这并不意味着只要类可访问,就可以访问构造函数。

    如果你不创建构造函数,default empty constructor is automatically created。 如果任何构造函数没有显式调用 super 或 this 构造函数作为其第一条语句,则为 call to super() is automatically added。

这意味着如果您的构造函数是在子类的范围内定义的,则无需显式调用super()。与您的情况一样,您可以删除所有构造函数。您的程序仍将编译并运行。

希望这会有所帮助。有关更多信息,请查看共享链接,其中有一些更漂亮的示例。

【讨论】:

【参考方案3】:

来自Java specification on default constructor。

如果一个类不包含构造函数声明,则隐式声明一个没有形式参数且没有 throws 子句的默认构造函数。

如果声明的类是原始类 Object,则默认构造函数的主体为空。否则,默认构造函数只会调用不带参数的超类构造函数。

所以你应该很好地不包括任何这些构造函数。

【讨论】:

以上是关于在这种情况下是不是需要实现标准构造函数(Java)?的主要内容,如果未能解决你的问题,请参考以下文章

默认情况下Java构造函数不是公开的吗? [复制]

如何更改 C# Record 构造函数的行为

C++ 与 Java 构造函数

记录文件、类和构造函数的正确方法是啥?

我们是不是需要显式使用指针类型的 CTOR?

在这种情况下,如何传递成员函数而不是函数? [复制]