以下是我的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
类的构造函数设为public
或protected
,则代码编译正常,没有错误。
那么,为什么构造函数必须是public
或protected
,而不只是默认访问?
答案 0 :(得分:13)
如果要扩展其包外的类,它必须具有public
或protected
的构造函数,因为在Java中,每个构造函数都必须从其超类中调用构造函数。
因此,在每个构造函数中都有一个隐含的super()
调用,它没有this()
或显式调用super()
作为其第一个语句。如果你没有指定一个构造函数,Java将添加一个默认的无参数构造函数,所以实际上你的代码看起来像这样:
public class UsingProtectedCon extends ProtectedConstructor {
public UsingProtectedCon() {
super();
}
public static void main(String... a) {
}
}
因此换句话说,您的代码无法编译,因为无法解析默认构造函数中对super()
的调用。
答案 1 :(得分:3)
constructor
是field
和method
类的成员,因此访问修饰符适用于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编译器不允许构造函数具有父项中私有的构造函数。