我是Java新手。我想知道在私有类中使用 public 构造函数是什么。类中的私有类可以从同一个类初始化,那么将私有类的构造函数公开为什么呢?
public class MainActivity extends Activity {
private class AcceptThread extends Thread {
public AcceptThread() {
}
}
}
答案 0 :(得分:14)
对于具有私有类的公共或受保护修饰符,似乎没有任何实际用例。如果您在单个文件中有多个类(但不是嵌套或本地),则需要非私有构造函数来实例化私有类。
// X.java
public class X {
private Y y = new Y();
}
class Y {
Y () {
// if this were private, X wouldn't be able to create an instance of Y
}
}
实际上默认或protected
可见性足以在这种情况下创建实例。所有非私有修饰符都允许您从同一个包中的其他类创建实例,但实际上具有相同的可见性。
public
方法在此处没有用。protected
也没有用。IllegalAccessException
。它首先检查类可见性,然后检查成员可见性。默认修饰符是限制性最强的修饰符,允许您直接从其他类调用构造函数,因此package-private似乎是构造函数以及任何其他非适当的可见性。私人方法。这样做的另一个好处是,如果您将来更改类可见性,则不会意外地将构造函数或任何方法暴露给公众。
答案 1 :(得分:6)
你知道,我几乎每次创建私人内部课时都会问自己这个问题,但我总是认为公共构造函数可能有一些(可能是人为的)理由。所以@kapep的回答让我感到刺痛,并鼓励他找到在私人内部课堂上要求公共构造函数的方法,但是我想的越多越好,我认为漏洞就越多。
可能的角度,所有这些都让我失望:
序列化 :当解组其超类不可序列化的对象时,超类需要一个可从子类访问的无参数构造函数 。所以,protected
应该总是足够了。
反射工具 :使用反射通过返回的实例获取内部类构造函数的代码。失败,因为首先检查类型可见性,正如@kapep指出的那样,尽管它留下了一个相当有趣的错误消息:
线程“main”中的异常java.lang.IllegalAccessException:类A无法访问类的设计成员.B $ C,修饰符为“public”
内部类扩展恶作剧 :请勿在家中尝试:
package a;
class Outer {
private class Inner {
}
}
package b;
// compile error: Outer.Inner has private access in Outer
class Extender extends a.Outer.Inner {
Extender(a.Outer outer) {
outer.super();
}
}
起初看起来很有希望,但我对这一点并没有太远。
最后,我找不到在私有内部类有用上创建公共构造函数的方法。
那为什么这在技术上是合法的,尽管没有用?可能是因为当没有提供其他构造函数时,编译器会自动插入一个无参数的公共构造函数。因此,语言不应该禁止这种结构。但更多的是人工制品而不是理由。