为什么Java类构造函数必须是公共的或受保护的,以便将类扩展到其包之​​外?

时间:2011-12-13 10:29:14

标签: java inheritance constructor default access-modifiers

以下是我的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()不公开;所以不能在包外访问。

但是,由于我的班级是公开的,我不应该将其扩展到包外。无论如何,我没有创建它的任何实例。

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

那么,为什么构造函数必须是publicprotected,而不只是默认访问?

8 个答案:

答案 0 :(得分:13)

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

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

public class UsingProtectedCon extends ProtectedConstructor {
    public UsingProtectedCon() {
        super();
    }

    public static void main(String... a) {   
    }
}

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

答案 1 :(得分:3)

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

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

答案 2 :(得分:1)

您的类中的

使用Package-Private访问权限定义ProtectedConstructor 这意味着在包外部甚至没有看到从ProtectedConstructor类扩展的类

使用“protected”访问修饰符定义构造函数,然后就可以完成了:

 package protectCon;

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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

请参阅此SO Post f或详细信息

答案 5 :(得分:0)

避免一切混乱这样做。    package 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){   
    }
}

答案 6 :(得分:0)

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

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

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

顺便说一句:如果你有一个abstract类,那么构造函数public就好像经常一样。 ;)提示:它与protected相同。

答案 7 :(得分:0)

如果child将拥有在parent中私有的构造函数,我们可以使用该构造函数创建child的实例并将其强制转换为父类型。 因此,为了防止这种java编译器不允许构造函数具有父项中私有的构造函数。