为什么可以从private
类中的public
方法返回public
嵌套类?难道编译器不应该抱怨返回类型的可见性小于方法吗?
public final class Outer {
private static final class Configurator {
private Configurator() {
}
}
public static Configurator configure() {
return new Configurator();
}
}
答案 0 :(得分:4)
你可以从课外调用这样的方法,但前提是你乐意抛弃结果。
public class TestClass {
public static void main(String[] args) throws Exception {
Outer.configure(); // this is valid
}
}
或者如果您乐意将结果称为Object
:
public class TestClass {
public static void main(String[] args) throws Exception {
Object o = Outer.configure(); // this is valid
}
}
编译器允许这样做,因为它不会破坏任何Java规则。 Object
只是您私人班级中唯一可公开获得的超类。
我怀疑这种模式有很多实际用途。如果你想返回一个不透明的对象,最好通过传回一个没有公共方法的公共类来完成,因为你至少可以在传回需要使用它的类时对其进行类型检查。
答案 1 :(得分:2)
严格要求interface
方法必须为public
。因此,当返回非public
类型的方法符合interface
合约时,必须 public
:
class Foo implements Supplier<NonPublicType> {
public NonPublicType get() { // must be public !
…
}
}
此外,如果声明类和方法是public
,仍然可以从包外部调用此方法。但是如果要使用,则必须将结果分配给非public
类的可访问超类型。例如。如果上面示例中的NonPublicType
实现了CharSequence
,您可以在包外面说CharSequence cs=foo.get();
(如果我们将Foo
更改为public
)。
请注意,有问题的方法可能会覆盖超类方法,该方法返回public
类型并返回更具体的非public
类型(又名Covariant return type)。可以使用更具体的类型从同一个包中的类调用该方法。
答案 2 :(得分:0)
嵌套类是其封闭类的成员,因此就像在单例设计模式中一样,当您调用public方法仅通过该方法获取私有静态实例时,也可以将私有静态类调用为成员或其中一种方法。 嵌套它的原因可能是以下之一:
例如,如果它是私人的,你就不能说:
OuterClass.StaticNestedClass nestedObject =
new OuterClass.StaticNestedClass();
因此,在这种情况下,您需要一个公共方法来访问它。
答案 3 :(得分:0)
完全可能并且有意义,尽管一个简短的实际例子相当困难。可以返回私有类来代替其任何超类。这里已经提到了Object,但它不一定是Object。这个例子有点古怪,但它有效。
abstract class Super {
abstract void zipper();
}
final class Outer {
private static final class Configurator extends Super {
private Configurator() {
}
@Override
void zipper() {
System.out.println("Zip!");
}
public void zoomer() {
System.out.println("Zoom!");
}
}
public static Configurator configure() {
return new Configurator();
}
}
public final class PublicPrivate {
public static void main(final String[] args) {
/* Outer.configure returns an instance of Configurator,
a subclass of Super */
final Super = Outer.configure();
/* Configurator.zoomer() is not available,
because Configurator is private */
// o.zoomer(); /* Uncomment this line and the compile will fail */
/* But Super.zipper() is available,
in the form in which Configurator overrid it */
o.zipper();
}
}
答案 4 :(得分:-1)
我认为这是因为您将如何处理被叫方中的对象可以推迟到最后一刻。例如,假设
private static class X{
}
public static MyClass.X getX() {
return new MyClass.X();
}
然后从另一个班级,我做了类似
的事情public void get() {
System.out.println(MyClass.getX());
}
我不需要知道X在这里是什么类型因为println只想要它的toString(),它继承自Object。
另一个例子
private static class X implements Serializable{
}
public static MyClass.X getX() {
return new MyClass.X();
}
在这种情况下,我不知道X,但我知道它是Serializable,所以我可以做类似的事情
public void get() {
Serializable x= MyClass.getX();
}
当然,我无法使用MyClass外部的X类型,但在我真正需要它之前,它只是Object的另一个实例