【问题标题】:Why does a private base class constructor result in "Implicit super constructor is not visible"为什么私有基类构造函数会导致“隐式超级构造函数不可见”
【发布时间】:2015-09-21 06:09:18
【问题描述】:

如果构造函数在 Java 中不继承,为什么会出现编译错误(隐式超级构造函数 A() 对于默认构造函数不可见。必须定义显式构造函数)?

class A {
    private A() {
    }
}

public class B extends A {

}

UPD。我知道 super() 在隐式 B 构造函数中被调用。但我不明白为什么它不能使用super() 访问私有构造函数。所以,如果我们只有私有构造函数,那么类事实上是final?

【问题讨论】:

标签: java inheritance constructor private


【解决方案1】:

如果B extends AB 必须有权访问A 构造函数。

请记住,构造函数总是调用super()。 所以这里B的隐式无参构造函数不能调用A构造函数。

【讨论】:

  • 我知道 super() 在隐式 B 构造函数中被调用。但我不明白为什么它不能使用 super() 访问私有构造函数。那么,如果我们只有私有构造函数类事实上是最终的?
  • @OlegKuts 你在这里混淆了一些东西!构造函数不能是final,实际上JLS指定的构造函数不能被覆盖。所以,B 构造函数并没有覆盖A 构造函数,而只是调用它。设置你的A构造函数private意味着它不能在A类之外使用,所以不能在B类中使用,但是B构造函数需要A构造函数,这就是为什么您收到错误super constructor A() is not visible for default constructor :) 希望对您有所帮助!
  • 也许我应该使用逗号...)我的意思是当所有构造函数都设置为私有时,该类成为最终的。
  • @OlegKuts 哦,对不起,我的英语不好了 :P 这是一个很好的问题,已经回答了here ;)
【解决方案2】:

在 Java 中,如果您创建 Child Class 的实例,Parent Class 实例将被隐式创建。 所以子类构造函数应该对Child Class 可见,因为它在第一条语句本身中使用super() 调用Parent Class 构造函数的构造函数。

因此,如果您将Parent Class 的构造函数更改为privateChild Class 将无法访问它并且无法创建自己的任何实例,因此编译器一开始就不允许这样做。

但是如果你想在Parent Class中使用private默认构造函数,那么你需要在Parent Class中显式创建一个重载的public构造函数&然后在Child class构造函数中你需要使用super(param)调用Parent Class 的公共重载构造函数。

此外,你可能会想private 构造函数有什么用。 private 构造函数主要用于当您不希望任何外部类的其他人在您的类上调用 new() 时。所以在这种情况下,我们提供了一些getter() 方法来提供类的object。在该方法中,您可以创建/使用您的类的现有对象并从该方法返回它。

例如。 Calendar cal = Calendar.getInstance();。这实际上构成了Singleton 设计模式的基础。

【讨论】:

  • 谢谢,我知道。我的问题是为什么 super() 不能调用私有构造函数?私有方法不能被覆盖是不是同一个原因?
  • super() 不能调用 Parentprivate 构造函数,因为 private 成员只能在同一个类中访问,所以 Child 类是一个不同的类,你只是不能访问它。
  • @OlegKuts 如果这对您有用,您可以将其设置为正确答案
【解决方案3】:

重要的是要理解任何构造函数的第一行都是调用超级构造函数。如果您自己不调用超级构造函数,编译器会通过在幕后插入 super() 来缩短代码。

现在,如果您将超类中的构造函数设为私有,上述概念将失败。

【讨论】:

    【解决方案4】:

    可以工作

    class A {
        private A() {
        }
        public A(int i){
        }
    }
    
    public class B extends A {
        private A(){
            super(10);
        }
    }
    

    或者去掉private A(),默认为public A(), 除非你有另一个构造函数

    class A {
    
    }
    
    public class B extends A {
        private A(){
            super();
        }
    }
    

    【讨论】:

      【解决方案5】:

      B 类的实例会创建A 类的实例,因此如果A 实现了非默认构造函数,B 必须调用super(...)。所以构造函数应该是protected,因为B能够调用super(...)

      【讨论】:

        【解决方案6】:
        public class B extends A {
        
        /*
        * The default constructor B means
        * public () B {super();}
        */
           public B() {
           }
        }
        

        所以你应该定义一个类B可以访问的构造函数

        1. 您可以更改父构造函数的访问修饰符
        2. 或者,您可以在父类中定义其他构造函数,该构造函数可由类 B 访问并调用该构造函数。

        【讨论】:

          【解决方案7】:

          您的 B 类有一个默认构造函数 B() - 因为您没有明确定义任何其他构造函数。 该构造函数隐式调用其超级构造函数 A()。 但是您已明确将其设为 A 类私有,因此您已明确声明任何其他类(包括 B)都无法访问它。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-10-16
            • 2016-02-21
            • 1970-01-01
            • 2011-05-30
            相关资源
            最近更新 更多