Java私有构造函数可见性
我试图理解为什么在谈到构造函数时,类成员的可访问性之间存在差异 考虑以下示例:Java私有构造函数可见性,java,constructor,private,Java,Constructor,Private,我试图理解为什么在谈到构造函数时,类成员的可访问性之间存在差异 考虑以下示例: class A { static class B { private B(String s) {} private void foo() {} } static class C extends B { public C(String s) { super(s); // call B(String), which is private, and obviously a
class A {
static class B {
private B(String s) {}
private void foo() {}
}
static class C extends B {
public C(String s) {
super(s); // call B(String), which is private, and obviously accessible
}
void bar() {
foo(); // compilation error (symbol unknown), as B.foo() is private
}
}
}
A
的私有成员作为私有成员,不应从B
访问。对于字段和方法,情况确实如此,但构造函数似乎没有遵循相同的规则
从JLS-8(),我们可以看到:
[……]
引用类型的成员(类、接口、字段或方法)或类类型的构造函数只有在类型可访问且声明该成员或构造函数允许访问时才可访问:
- [……]
- 否则,成员或构造函数被声明为私有的,并且只有当且仅当它发生在包含成员或构造函数声明的顶级类(§7.6)的主体内时,才允许访问
有人能解释一下为什么构造函数可以从
C
访问,即使它被声明为private
?方法foo()
是私有的,因此您不能继承它,也不能直接从C
类调用它
但是,您可以从B
中看到私有方法和构造函数,因为所有内容都在同一个包含类中声明,并使用super
访问它们,这就是super()
工作的原因。
同样,您可以使用super.foo()
访问foo
请注意,您可以在
C
中重新定义新的foo方法,但此方法不会覆盖B.foo()
,因此这里的技巧可能是:
您无法访问foo
,因为它被声明为私有,所以您不会在C中继承它
但是,正如注释中所指出的,您可以访问super.foo()代码>因为super
指的是在同一顶级类中声明的类型(请参见JLS 6.6.1)
然后诀窍是调用super(s)
可以被视为调用super(s)
,这与super.foo()
foo()方法在类C中是不可访问的,因为foo()方法是私有的,私有方法不能继承到基类
对于构造函数,永远不会继承构造函数。此外,我编译了以下代码:
class Vehicle{
int speed=50;
private Vehicle()
{
System.out.println("Private Vehicle constructor");
}
}
public class Bike4 extends Vehicle{
int speed=100;
Bike4()
{
super();
System.out.println("Hi I n constructor");
}
void display(){
System.out.println(super.speed);//will print speed of Vehicle now
}
public static void main(String args[]){
Bike4 b=new Bike4();
b.display();
}
}
获取编译时错误:Vehicle()在Vehicle中具有私有访问权限
超级();
^
这清楚地表明,不能使用super访问私有构造函数。如果我们能够初始化或访问私有构造函数,那么创建私有构造函数的意义何在。仅仅因为可以调用super并不意味着构造函数是可访问的。有人能解释一下为什么即使在声明为私有的情况下,也可以从C访问构造函数吗?->因为B和C都是A的内部类。如果将B和C移到A之外,它们将不再工作。@JörnBuitink:如果是这样,为什么foo()
无法访问?这里似乎有不一致的地方。请注意super.foo()
是有效的。@Arun这是C#。不是Java。静态类在Java中可以有构造函数。非常感谢您的回答WilQu&@benzonico。这似乎是个骗局。因此,我接受你的答案。请看其他答案,你的答案与问题并不相关。