Java 私有构造函数可见性
Posted
技术标签:
【中文标题】Java 私有构造函数可见性【英文标题】:Java private constructors visibility 【发布时间】:2016-02-21 09:16:02 【问题描述】:在谈到构造函数时,我试图理解为什么类成员的可访问性之间存在差异。
考虑以下示例:
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),我们可以阅读:
[...]
引用类型的成员(类、接口、字段或方法)或类类型的构造函数,只有在该类型可访问并且声明成员或构造函数允许访问时才可访问:
[...]
否则,成员或构造函数被声明为
private
,并且当且仅当它出现在包含成员或构造函数声明的***类(第 7.6 节)的主体内时才允许访问。
谁能解释一下为什么构造函数可以从C
访问,即使被声明为private
?
【问题讨论】:
可以调用 super 并不意味着可以访问构造函数 谁能解释为什么构造函数可以从 C 访问,即使被声明为私有? -> 因为 B 和 C 都是 A 的内部类。如果将 B 和 C 移到 A 之外,将不再起作用。 @JörnBuitink:如果是这样,那为什么foo()
不可访问?这里似乎确实存在不一致。
请注意super.foo()
有效。
@Arun 那是 C#。不是Java。静态类在 Java 中可以有构造函数。
【参考方案1】:
方法foo()
是私有的,所以你不继承它,也不能直接从C
类调用。
但是,您可以从 B
看到私有方法和构造函数,因为所有内容都在同一个包含类中声明,并使用 super
访问它们,这就是 super()
起作用的原因。
同理,可以通过super.foo()
访问foo
。
注意你可以在C
中重新定义一个新的foo方法,但是这个方法不会覆盖B.foo()
。
【讨论】:
非常感谢您的回答 WilQu 和 @benzonico。这似乎是诀窍。因此我接受你的回答。【参考方案2】:所以这里的诀窍可能如下:
您无法访问foo
,因为它被声明为私有,因此您不能在 C 中继承它。
但是,正如 cmets 中所述,您可以访问 super.foo();
,因为 super
指的是在同一***类中声明的类型(有关此内容,请参见 JLS 6.6.1)。
然后诀窍是调用super(s)
可以被视为调用super.<init>(s)
最终与super.foo()
相同
【讨论】:
【参考方案3】: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 访问私有构造函数。如果我们能够初始化或访问私有构造函数,那么创建私有构造函数的意义何在。
【讨论】:
请查看其他答案,您的答案与问题无关。以上是关于Java 私有构造函数可见性的主要内容,如果未能解决你的问题,请参考以下文章