公共方法如何返回私有类型?

时间:2014-09-25 11:36:16

标签: java oop visibility

为什么可以从private类中的public方法返回public嵌套类?难道编译器不应该抱怨返回类型的可见性小于方法吗?

public final class Outer {
    private static final class Configurator {
        private Configurator() {
        }
    }

    public static Configurator configure() {
        return new Configurator();
    }
}

5 个答案:

答案 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的另一个实例