2013-04-13 88 views
2

我想測試以下情況:公共方法如何返回私有類實例?

  1. 有一個主要的。 (city.Main
  2. 有一個包。 (package castle
  3. 包內有一個公共類(castle.Guard)和一個包私人類類(castle.Princess)。
  4. 如果public類正在返回一個私有類的實例呢?

這裏是我的代碼:

Main.java

package city; 

import castle.Guard; 

public class Main { 

    public static void main(String[] args) { 
     Princess princess = Guard.getPrincessStatic(); 
     // Error: Princess cannot be resolved to a type 

     Guard.getPrincessStatic().sayHi(); 
     // Error: The type Princess is not visible 

     Guard guard = new Guard(); 
     guard.getPrincess().sayHi(); 
     // Error: The type Princess is not visible 

     guard.getPrincessMember().sayHi(); 
     // Error: The type Princess is not visible 
    } 

} 

Guard.java

package castle; 

public class Guard { 

    public Princess getPrincess() { 
     return new Princess(); 
    } 

    public static Princess getPrincessStatic() { 
     return new Princess(); 
    } 

    private Princess m_princess = new Princess(); 

    public Princess getPrincessMember() { 
     return m_princess; 
    } 
} 

Princess.java

package castle; 

class Princess { 
    public void sayHi() { System.out.println("Hi world"); } 
} 

通知所有4個main()報表有錯誤。

我也做了一些研究。實際上我想模仿this answer。但我不是爲什麼我的代碼拋出錯誤。

感謝您的任何解釋!


編輯:

我正在打算使castle-Princess包私人。我知道返回一個包私人類的包,我應該爲錯誤做好準備。但爲什麼that answer工作,但我的不?

+0

錯誤基本上是說「私人手段*私人*!」這些鏈接可能有所幫助:[Java語言規範:可見性](http://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#d5e8032),http://stackoverflow.com/ questions/5203205/why-can-we-override-a-base-class-method-with-private-extended-class-method,[Visibility and Coupling](http://www.leepoint.net/JavaBasics/oop/) oop-70-visibility.html) – paulsm4

回答

3

Princess類默認範圍爲castle包,所以它在city包內不可見。爲了規避:

(我們可以做以下三種方法之一。)

1)使Princesspublic並使用它。

package castle; 

// added public modifier 
public class Princess { 
    public void sayHi() { System.out.println("Hi world"); } 
} 

2)或者,定義public interface,讓Princess實現它,並使用interface reference代替class reference。我更喜歡這個。

城堡\ IPrincess.java

// Interface definition 
package castle; 

public interface IPrincess { 
    public void sayHi(); 
} 

城堡\ Princess.java

// Implement the interface in Princess class 
package castle; 

class Princess implements IPrincess { 
    public void sayHi() { System.out.println("Hi world"); } 
} 

城堡\ Guard.java

// Modify the Guard class 
package castle; 

public class Guard { 
    public IPrincess getPrincess() { 
     return new Princess(); 
    } 
    public static IPrincess getPrincessStatic() { 
     return new Princess(); 
    } 

    // for here i use Princess instead of IPrincess. (@midnite) 
    private Princess m_princess = new Princess(); 
    public IPrincess getPrincessMember() { 
     return m_princess; 
    } 
} 

城市\ Main.java

// Modify the main class 
    package city; 

    import castle.Guard; 
    import castle.IPrincess; 

    public class Main { 

    public static void main(String[] args) { 

    IPrincess princess = Guard.getPrincessStatic(); 

    Guard.getPrincessStatic().sayHi(); 

    Guard guard = new Guard(); 
    guard.getPrincess().sayHi(); 

    guard.getPrincessMember().sayHi(); 
    } 
} 

3)或者,把所有的班同一個包。

+0

這真是一個不錯的解決方案!請允許我編輯一點你的答案以獲得更好的可讀性:-) – midnite

1

你不能夠返回一個類中私有的類型。如果任何外部資源在另一個類的私人範圍內,它甚至可以知道該類型是什麼類型?

這個設計甚至不會編譯。

編輯:

簡單的解決辦法是把它公開,然後你可以在外部使用它的程序包之外。

0

問題出在一個非常小的錯誤在你的公主類的定義:

package castle; 

class Princess { 
    public void sayHi() { System.out.println("Hi world"); } 
} 

所有看起來不錯,在第一,但你錯過的類名前public修改:

package castle; 

//here! 
public class Princess { 
    public void sayHi() { System.out.println("Hi world"); } 
} 

沒有public修飾符,公主類不能在聲明它的文件之外訪問。

1

你試圖模仿作品的答案是因爲所有的類都在同一個包內。

如果您將UntrustworthyFriendFriend置於不同的包中(如您的場景),則會出現相同的問題。

Princess.java

package castle; 

public class Princess { 
    public void sayHi() { System.out.println("Hi world"); } 
} 

此外,請務必將其導入Main

Princess outsite它的包,如果public只能是可見的。

+0

你是對的!如果我把'UntrustworthyFriend.java'和'Friend.java'放在不同的包中,'friendWithSecret.getMySecret().verify()'這一行給出錯誤:'類型Secret不可見。所以,以我的觀點來看,@Andy想要說明的僅僅是返回一個私有成員變量,而不是私有類,這不是真正特殊的IMO(我們所有的getter方法都這樣做)。 – midnite

+0

@midnite:@Andy says _「然而,方法仍然可以在'UntrustworthyFriend'內的'Secret'上調用。」_但是,這隻有在'UntrustworthyFriend'中可以看到'Secret'的情況下才有效。只有'祕密'或者是'公開'或者與'不可信賴的朋友'在同一個軟件包中才會這樣。 – acdcjunior

+0

@ acdc junior:是的。在'UntrustworthyFriend.main()'中,我甚至可以做'System.out.println((new Secret(「blah」))。reveal());'。我根本不需要一個「朋友」: -/ – midnite

0

你的例子是不同的,因爲你的課程在不同的包中,Guard和Princess從Main中不可見。

但是公共方法可以返回一個私有類的實例。 JDK是滿的例子,這裏是一個從java.util.Arrays

public static <T> List<T> asList(T... a) { 
    return new ArrayList<>(a); 
} 
... 
private static class ArrayList<E> extends AbstractList<E> { 
... 

這是你的要求。訣竅是方法的返回類型是私有類實現的公共接口。你可以做類似的事情。

+0

謝謝@ED。這很有趣!我想這應該是@早期實現的技巧? – midnite

相關問題