2009-10-06 63 views
2

比方說,我有包:有沒有辦法訪問另一個沒有public修飾符的包?

com.mycomp.packone 
com.mycomp.packtwo 

有什麼辦法,我訪問類的保護成員在packone從packtwo一類,但不允許公衆用戶這樣做呢?我能想到的唯一方法是使用受保護的訪問和使用子類。但是,這只是將問題推入子類,因爲我希望在那裏也有相同的訪問限制。

上下文爲此我們正在重新設計我們的主要API,並希望使其更加模塊化。現在它全部在一個巨大的包裝中。我不是爲這種設計而來的,但我認爲這是因爲有很多保護用途。

+0

等待JDK7模塊? – 2009-10-06 17:47:06

回答

0

protected修飾符是您現在唯一的選擇(JDK7尚未出現)。正如你所說,這仍然允許其他包中的子類訪問受保護的成員。您可以通過將類聲明爲final來防止子類化,但我不確定這是否與您的用例兼容。記住這一點也很重要,全部 Java中的訪問修飾符僅僅是建議,並且很容易被反射繞過。

1

Java程序包受到嚴格限制(恕我直言),因爲它們之間沒有對包和層次結構進行特殊處理。每個包裝都是獨立的,點符號僅用於人眼。限制訪問特定客戶端的能力也被打破了(它是如何讓我希望C++的友誼機制有時候......)

AFAIK,這是你現在唯一的選擇,直到Java 7有望解決問題。

你可以考慮的一件事(如果你的項目適合)是使用類似OGSi的東西。它的模塊化和出口基礎設施可以讓你做比語言更容易調整的事情。

0

像亞薩說,打破使用反射規則(使用getDeclaredMethod的方法,而不是一個字段):

package com.mycomp.packone; 

public class Introvert { 
    protected String secret = "TOP SECRET!"; 
} 

package com.mycomp.packtwo; 

import java.lang.reflect.Field; 

public class Extrovert { 
    public String talk(){ 
     return this.getSecret(); 
    } 

    @SuppressWarnings("unchecked") 
    protected String getSecret(){ // everybody in packtwo can call me! 
     try { 
      Class introvertClass = Class.forName("com.mycomp.packone.Introvert"); 
      Object introvert = introvertClass.newInstance(); 
      Field secretField = introvertClass.getDeclaredField("secret"); 
      secretField.setAccessible(true); 
      return (String) secretField.get(introvert); 
     } catch (Exception e) { 
      throw new RuntimeException(e); 
     } 
    } 

    public static void main(String[] args){ 
     Extrovert extrovert = new Extrovert(); 
     System.out.println(extrovert.talk()); 
    } 
} 
0

考慮重新設計自己的API有「外部」和「內部」的API。

雖然你不能做到這一點使用本地Java訪問修飾符,您可以用打包類:

package com.mycomp 
package com.mycomp.internal 

com.mycomp包,您發佈的公共API,你讓「大衆」用戶取決於;大多數情況下,這個包中的接口比類更多。

com.mycomp.internal包是您實現最com.mycomp發現的接口。內部命名一個包有效地告訴人們,包中的類是API的內部,並且選擇依賴於內部包可能會在將來的版本中破壞它們的代碼。更重要的是,如果您可以使用OSGi,則只能導出com.mycomp包,從而使com.mycomp.internal有效地「隱藏」於世界其他地方。

FWIW,mockito採用這種包裝其API的方法。

這種方法的缺點是依賴於一個約定。

+0

我在這一點上傾向於這個解決方案。 OSGi對於模塊化看起來很有希望,但是我們將這個API發送給客戶,我不確定OSGi會對他們產生什麼樣的影響和增加的需求 – user26270 2009-10-12 14:12:51

+0

@ codeman73:兼容OSGi的jar可以像普通的一樣使用;因此,即使您的客戶不採用OSGi,也不會受到不利影響。 此外,您也可以在不採用OSGi的情況下使用「外部/內部」包裝規範。 – shaolang 2009-10-13 02:18:36

相關問題