2009-10-06 36 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

相关问题