2014-09-25 106 views
3

爲什麼有可能從public類中的public方法返回private嵌套類?編譯器不應該抱怨返回類型的可見性低於方法嗎?公用方法如何返回私有類型?

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

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

這是不可能的。請張貼一些代碼。我假設方法的簽名_returns_是一個公共接口(或類似的),而方法的實現返回該接口的私有子類。這是允許的。 – Seelenvirtuose 2014-09-25 11:38:32

+1

@Seelenvirtuose:它*是可能的,令人驚訝的。感覺像一個Java設計缺陷給我。 (C#不允許。) – 2014-09-25 11:42:11

+0

啊,好的。我懂了。簡單的技術解釋:在此方法聲明的範圍內,(私有)類是可見的,因此可用作方法簽名中的返回類型。但是,您只能從該課程內部調用此方法。由於無法訪問該私有類,因此每個其他類中的代碼都無法調用此方法。 – Seelenvirtuose 2014-09-25 11:43:42

回答

3

可以從類的外部調用該方法,但只有當你高興地扔掉的結果。

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是您的私人課程中唯一公開可用的超類。

我懷疑這種模式有很多實際用途。如果您希望返回一個不透明的對象,那麼最好通過傳回一個沒有公共方法的公共類來完成,因爲您至少可以在返回需要使用它的類時進行類型檢查。

+0

+1 - 事實上,你的第二個例子說明了這種(看似)異常語言功能的使用。 – 2014-09-25 11:55:26

+0

其實[有*是*重要的實際用途](http://stackoverflow.com/a/26038350/2711488) – Holger 2014-09-25 12:20:32

+0

@Holger除非我誤解了你的觀點,那麼這正是我在我的最後一段中所說的回答。這種模式可以用來創建不透明的對象,但有更好的方法來做到這一點。 – 2014-09-25 12:35:15

-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,但我知道這是序列化的,所以我可以做這樣的事情

public void get() { 
    Serializable x= MyClass.getX(); 
} 

我不能這樣做,當然是使用MyClass外部的類型X,但直到我真的需要它,它只是對象的另一個實例

0

嵌套類是它的封閉類的成員,所以就像在單例設計中一樣ttern,當你調用public方法只通過該方法獲取私有靜態實例時,也可以將私有靜態類作爲成員或其方法之一進行調用。 你嵌套它的原因可能是下列之一:

  • 邏輯分組類,只在一個地方
  • 使用要增加封裝
  • 爲了獲得更多的閱讀和維護代碼

例如,如果它是私人的,你不能說:

OuterClass.StaticNestedClass nestedObject = 
new OuterClass.StaticNestedClass(); 

所以你需要一個公開的方法來訪問它在這種情況下。

2

有一個嚴格的要求,interface方法必須是public。因此,當返回一個非public型的方法還履行合同interface必須public

class Foo implements Supplier<NonPublicType> { 
    public NonPublicType get() { // must be public ! 
    … 
    } 
} 

此外,仍有可能從包的外部調用此方法,如果聲明類和該方法是public。但是如果要使用的話,結果必須分配給非易失性類的非易失性類。例如。如果上述示例中的NonPublicType實現了CharSequence,那麼可以在包外部指定CharSequence cs=foo.get();(如果我們將Foo更改爲public)。

請注意,該方法可能會覆蓋超類方法,該方法返回public類型並返回更具體的非public類型(又名Covariant return type)。該方法可以從同一個包中的類使用更具體的類型來調用。

0

這是完全可能的,也是有道理的,雖然一個簡短的實例很難。私人課程可以代替它的任何超級課程返回。對象在這裏被提到,但它不一定是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(); 
    } 

} 
相關問題