我需要有一个可以从我的 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 的修饰符级别降低到 protected
或 private
,类 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 方法的主要内容,如果未能解决你的问题,请参考以下文章
是否有任何 API 可以将跟踪号和订单状态从我的应用程序添加到 PayPal?
从我的Mac查询到Pandas DataFrame的DB2 sql
如何从我的 Ruby on Rails API 解析这些散列转换为字符串,以便它可以作为 Javascript 中的对象进行访问?