【问题标题】:Why does a Java constructor have to be public or protected for a class to be extended outside its package?为什么 Java 构造函数必须是公共的或受保护的才能将类扩展到其包之​​外?
【发布时间】:2012-01-19 05:34:20
【问题描述】:

以下是我的ProtectedConstructor.java源代码:

package protectCon;

public class ProtectedConstructor{
    public int nothing;
    ProtectedConstructor(){
        nothing = 0;
    }
}

以下是UsingProtectedCon.java 来源:

package other;

import protectcon.ProtectedConstructor;

public class UsingProtectedCon extends ProtectedConstructor{   //**Line 4**
    public static void main(String... a) {  
    }
}

当我编译 UsingProtectedCon.java 时,我在上面显示的第 4 行出现错误。它说 ProtectedConstructor() 不是 public ;所以不能在包外访问。

但是,由于我的课程是公开的,我不应该能够将它扩展到包之外。反正我没有创建它的任何实例。

现在,如果我将ProtectedConstructor 类的构造函数设置为publicprotected,那么代码可以正常编译,没有错误。

那么,为什么构造函数必须是publicprotected,而不仅仅是具有默认访问权限?

【问题讨论】:

    标签: java inheritance constructor default access-modifiers


    【解决方案1】:

    如果你想在它的包之外扩展一个类,它必须有一个publicprotected的构造函数,因为在Java中每个构造函数都必须从它的超类中调用一个构造函数。

    因此,在每个没有this() 或显式调用super() 作为其第一条语句的构造函数中都有一个隐含的super() 调用。如果你根本不指定构造函数,Java 将添加一个默认的无参数构造函数,所以实际上你的代码如下所示:

    public class UsingProtectedCon extends ProtectedConstructor {
        public UsingProtectedCon() {
            super();
        }
    
        public static void main(String... a) {   
        }
    }
    

    换句话说,您的代码无法编译,因为无法解析默认构造函数中对super() 的调用。

    【讨论】:

      【解决方案2】:

      constructorfieldmethod 等类的成员,因此访问修饰符适用于 in the same manner it apples to all the member of class

      当你在 B 中扩展类 A 时,A 的默认构造函数将被 B 的构造函数隐式调用(如果你不调用任何重载的构造函数)

      【讨论】:

      • 吹毛求疵:Java 中没有重写的构造函数。
      【解决方案3】:

      在您的类 ProtectedConstructor 中定义为包私有访问 这意味着即使从 ProtectedConstructor 类扩展的类也看不到包外部

      用'protected'访问修饰符定义你的构造函数,你就完成了:

       package protectCon;
      
      public class ProtectedConstructor{
          public int nothing;
          protected ProtectedConstructor(){
              nothing = 0;
          }
      }
      

      【讨论】:

        【解决方案4】:

        您的构造函数不是公开的。默认范围是包私有。

        【讨论】:

          【解决方案5】:

          JLS 6.6.7 回答您的问题。如果子类涉及其父类的实现,则子类只能访问其父类的受保护成员。因此,不能在子类中实例化父对象,如果父构造函数被保护并且它在不同的包中。由于子类的默认构造函数会尝试调用父类构造函数,所以会出现此错误。

          查看此SO Post f或详细信息

          【讨论】:

            【解决方案6】:

            为了避免所有混乱,请这样做。 包protectCon;

            public class ProtectedConstructor{
                public int nothing;
                public ProtectedConstructor(){
                    nothing = 0;
                }
            }
            
            
            package other;
            
            import protectCon.ProtectedConstructor;
            public class UsingProtectedCon extends ProtectedConstructor{   //**Line 4**
            
                public UsingProtectedCon(){
                  super();
                  }
            
            
              public static void main(String... a){   
                }
            }
            

            【讨论】:

              【解决方案7】:

              您可以拥有公共的、受保护的(供内部使用的)甚至私有的构造函数。

              一个简单的例子是 String,它有一般使用的 public 构造函数和内部使用的包本地构造函数。

              ObjectOutputStream 类有一个公共构造函数,它接受一个 OutputStream 和一个只能由子类使用的 protected 构造函数。

              顺便说一句:如果你有一个abstract 类,那么让构造函数public 就像经常发生的情况一样有意义吗? ;) 提示:与protected 相同。

              【讨论】:

                【解决方案8】:

                如果子级将有父级私有的构造函数,我们可以使用该构造函数创建子级的实例并将其转换为父级的类型。 因此,为了防止这个 java 编译器不允许构造函数具有父级私有的构造函数。

                【讨论】:

                  猜你喜欢
                  • 2011-04-09
                  • 2020-09-17
                  • 2014-12-23
                  • 2013-01-27
                  • 2010-10-20
                  • 2015-06-14
                  • 2017-12-30
                  • 2013-08-04
                  • 1970-01-01
                  相关资源
                  最近更新 更多