我需要有一个可以从我的 API 中的任何位置访问但不能从使用 API 的应用程序访问的 java 方法

Posted

技术标签:

【中文标题】我需要有一个可以从我的 API 中的任何位置访问但不能从使用 API 的应用程序访问的 java 方法【英文标题】:I need to have a java method that can be accessed from anywhere within my API but cannot be accessed from the application using the API 【发布时间】:2014-07-20 15:48:57 【问题描述】:

我正在开发一个 java API。在我的开发过程中,我一直面临以下问题:

我在两个不同的包中有两个类。包 x 中的 A 类,包 y 中的 B 类。我需要类 A 来访问类 B 中定义的方法 M。因此,应该用于方法 M 的修饰符是 public。但是,我不想让将在他/她的 java 应用程序中使用我的 API 的开发人员访问方法 M。问题是方法 M 有我提到的 public 修饰符,因此任何人都可以访问它在 API 内或从 API 外。同时,如果我将方法 M 的修饰符级别降低到 protectedprivate,类 A 将无法访问方法 M,因为它属于不同的包。我怎么解决这个问题?将 A 和 B 放在同一个包中是我唯一的解决方案吗?

【问题讨论】:

客户能否访问课堂B中的其他内容? 如果您需要类似的东西,您很可能应该重新设计您的代码结构。没有办法实现您正在寻找的东西。不幸的是,它有点过于抽象,无法给出更好的建议,它可能更适合编程。se 不幸的是,没有语言级别的结构可以完全满足您的需求。根据其他人调用M 的糟糕程度,您可以做的一件事是使用“不供外部消费”记录它,例如com.sun 包。 你可以用 OSGi 做到这一点,但它有异味。 【参考方案1】:

创建一个接口并仅将其公开给公众,隐藏您的实现。例如:

我的实现(比如说,application.jar):

public class Test implements TestInterface 
    public void somePrivateStuff()  

    public void somePublicStuff()  

亲爱的,这是我的 API(例如,publicAPI.jar):

public interface TestInterface 
    public void somePublicStuff();

其他开发人员会针对您的 publicAPI.jar 进行编译。运行时实现将来自您的 application.jar。

【讨论】:

这就是我的想法。只有当最终用户不需要自己构建类时才有效,当然工厂可以解决这个问题【参考方案2】:

限制对特定类的访问的唯一方法是使方法受保护或包私有。两者都只允许在包内访问。我建议重新格式化你的包结构。

【讨论】:

是的,你是对的。看来我读错了。我会修改帖子以反映这一点。【参考方案3】:

在方法内部,可以插入:

Throwable th = new Throwable().fillInStackTrace();
StackTraceElement element = th.getStackTrace()[TEST BETWEEN 3 AND 5];

if (element.getClassName().startsWith("your.package")) 
  // CONTINUE YOUR METHOD.

else 
  // USER ACCESSING FROM AN APPLICATION.
  // THROW EXCEPTIONS, SHUTDOWN THE SYSTEM... DO WHAT YOU WANT.

在第二行,在 3、4 和 5 之间进行测试,看看哪一个返回正确的element.getClassName()

【讨论】:

【参考方案4】:

您可以将项目拆分为 2:公共 API 及其实现。 为B类定义2个接口:

    图书馆用户的公共界面(在 API 项目中)。 您的内部接口扩展了公共接口并添加了方法 M。

用户将在编译时依赖于您的 API,并将在运行时获得实现。

【讨论】:

【参考方案5】:

你可以使用反射。这是一个例子。

package b;

public class B 
    private void m() 
        System.out.println("Called m()");
    

package a;

import b.B;

import java.lang.reflect.Method;

public class A 
    public static void main(String[] args) throws Exception 
        B b = new B();
        Method m = B.class.getDeclaredMethod("m");
        m.setAccessible(true);
        m.invoke(b);
    

哪些输出

调用 m()

【讨论】:

客户端不能也这样改修饰符吗?这太可怕了。 @TravelingSalesman 是的,根据您的代码运行的环境,可以使用反射访问任何私有方法

以上是关于我需要有一个可以从我的 API 中的任何位置访问但不能从使用 API 的应用程序访问的 java 方法的主要内容,如果未能解决你的问题,请参考以下文章