Java 私有构造函数可见性
Java private constructors visibility
我试图理解为什么在谈论构造函数时 class 成员的可访问性存在差异。
考虑以下示例:
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 (6.6.1. Determining Accessibility),我们可以读到:
[...]
A member (class, interface, field, or method) of a reference type, or a constructor of a class type, is accessible only if the type is accessible and the member or constructor is declared to permit access:
[...]
Otherwise, the member or constructor is declared private
, and access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.
任何人都可以解释为什么构造函数可以从 C
访问,即使在声明 private
时也是如此?
方法 foo()
是私有的,因此您不能继承它,也不能直接从 C
class 调用它。
但是,您可以从 B
中看到私有方法和构造函数,因为所有内容都在包含 class 的同一文件中声明,并使用 super
访问它们,这就是为什么 [=14] =] 有效。
同理,可以用super.foo()
.
访问foo
请注意,您可以在 C
中重新定义一个新的 foo 方法,但此方法不会覆盖 B.foo()
。
所以这里的技巧可能如下:
您无法访问 foo
,因为它被声明为私有的,所以您不能在 C 中继承它。
但是,如评论中所述,您可以访问 super.foo();
,因为 super
指的是在同一顶级 class 中声明的类型(请参阅 JLS 6.6.1这个)。
那么诀窍是调用 super(s)
可以被视为调用 super.<init>(s)
最终与 super.foo()
相同
Foo() 方法在 class C 中不可访问,因为 foo() 方法是私有的,私有方法不能继承到基础 class.
对于构造函数,构造函数永远不会被继承。另外,我编译了这段代码:
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 访问私有构造函数。如果我们能够初始化或访问私有构造函数,那么创建私有构造函数的意义何在。
我试图理解为什么在谈论构造函数时 class 成员的可访问性存在差异。
考虑以下示例:
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 (6.6.1. Determining Accessibility),我们可以读到:
[...]
A member (class, interface, field, or method) of a reference type, or a constructor of a class type, is accessible only if the type is accessible and the member or constructor is declared to permit access:
[...]
Otherwise, the member or constructor is declared
private
, and access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.
任何人都可以解释为什么构造函数可以从 C
访问,即使在声明 private
时也是如此?
方法 foo()
是私有的,因此您不能继承它,也不能直接从 C
class 调用它。
但是,您可以从 B
中看到私有方法和构造函数,因为所有内容都在包含 class 的同一文件中声明,并使用 super
访问它们,这就是为什么 [=14] =] 有效。
同理,可以用super.foo()
.
foo
请注意,您可以在 C
中重新定义一个新的 foo 方法,但此方法不会覆盖 B.foo()
。
所以这里的技巧可能如下:
您无法访问 foo
,因为它被声明为私有的,所以您不能在 C 中继承它。
但是,如评论中所述,您可以访问 super.foo();
,因为 super
指的是在同一顶级 class 中声明的类型(请参阅 JLS 6.6.1这个)。
那么诀窍是调用 super(s)
可以被视为调用 super.<init>(s)
最终与 super.foo()
Foo() 方法在 class C 中不可访问,因为 foo() 方法是私有的,私有方法不能继承到基础 class.
对于构造函数,构造函数永远不会被继承。另外,我编译了这段代码:
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 访问私有构造函数。如果我们能够初始化或访问私有构造函数,那么创建私有构造函数的意义何在。