我希望通过反思给将要使用我的代码的程序员提供一些便利。为了实现我想要的结果,我想获得扩展我的代码的类的类对象。即使他们无法覆盖我希望从中访问信息的静态方法,它也会有用。我可能最终只是为了避免这种情况而重构设计,但是想把这个问题抛给社区。 p>
我所知道的实现这一目标的唯一方法是获取当前线程,导航堆栈跟踪,并提取类名,然后将其转换为类的实际实例。
还有其他建议吗?
旁注:上述方法也是我了解获取调用方法的唯一方法。
答案 0 :(得分:2)
不幸的是,走堆栈并不一定安全:
来自JDK 6 Javadoc for getStackTrace:
某些虚拟机可能在某些情况下 情况,省略一个或多个堆栈 堆栈跟踪中的帧。在里面 极端情况下,虚拟机 没有堆栈跟踪信息 关于这个扔掉是允许的 返回一个零长度数组 这种方法。一般来说, 这个方法返回的数组会 每帧包含一个元素 这将由印刷 的printStackTrace。
您也许可以使用调试器api来完成它。我相信调试的东西能够全速使用HotSpot(我可能是错的)所以你不会看到这样做的巨大速度。您可以先看一下:http://java.sun.com/javase/6/docs/technotes/guides/jpda/trace.html
此外,建立在未答复的答案......
class Base
{
// instance method helper
public final int foo()
{
return (foo(this.getClass()));
}
// the real helper, with access to the class
private static int foo(final Class clazz)
{
return (0);
}
}
class Child
extends Base
{
public void bar()
{
final int x;
x = foo();
}
}
答案 1 :(得分:1)
在静态方法中,从你的扩展中获得的某个(任何)类是什么保证在堆栈中?
如果你仔细想一想,我怀疑你会意识到你所寻找的东西是不存在的。
/编辑1 / 我认为你需要的是
abstract class B {
<T extends B> B create(Class<T> clazz) {
....
}
嗯。如果create
是protected
方法怎么办?然后,您可以非常确定来电者是B
,如果调用者无法分配给UnsupportedOperation
,您甚至可以要求IllegalState
或B
。
您可以使用Thread.currentThread().getStackTrace()
答案 2 :(得分:1)
创建Throwable非常昂贵,所以如果经常调用你的方法(例如,每秒超过一次),请不要使用它 稍微好一点的方法是Thread.currentThread()。getStackTrace()。
如果使用Sun的JVM,另一种方法是Reflection.getCallerClass(n)。这要快得多,但不能移植到其他JVM。如果你担心这个问题,你可以使用另一种方法,如果它可用则调用它,如果没有则使用堆栈跟踪。
所有这些假设您的静态方法不公开。如果所有赌注都已关闭,因为任何类都可以调用您的方法,而不仅仅是扩展您的方法。
答案 3 :(得分:0)
我建议避免反思的泥潭。你似乎正在做一些简单的编程。使用简单的实现(没有足够的信息来合理猜测可能是什么)。