4

我有

public class A {
    static X s_x = new X(A.class);
}

public class B {
    static X s_x = new X(B.class);
}

等等对于许多没有任何特殊关系或共性的类。我真正希望我能做的是在超类中初始化 s_x,但使用子类特定的代码;这是不可能的,因为静态代码不可覆盖。所以,我想至少让我的复制粘贴更容易。我想要一个计算为 Class 对象的魔术表达式,即写:

    static X s_x = new X(/* magic expression here */);

无论我在其中声明 X 的类如何,魔术表达式都是相同的,但与上面的示例相同。次优选择是达到相同效果的静态方法。

笔记:

  • 如果可能的话,Java 6。
  • 这个问题(不一定)与日志记录有关......
4

8 回答 8

1

在 HotSpot/OpenJDK 你可以使用

 Class c = Reflection.getCallerClass(1)

注意:这是一个内部 API,可能不适用于所有 JVM。

于 2013-01-17T12:56:19.940 回答
1

这是一个应该在 Java 5+ JVM 中工作并且不会向您的代码添加任何额外导入的单行代码:

new Object(){}.getClass().getEnclosingClass()

它创建一个匿名内部类,获取它的Class对象,然后获取它的封闭类实例,它应该是你的类。例如:

public class HelloClass {
    static final Class<?> THIS_CLASS = new Object(){}.getClass().getEnclosingClass();

    public static void main(String[] args) {
        System.out.println(THIS_CLASS); // prints "class HelloClass"
    }
}

在你的问题的背景下:

static X s_x = new X(new Object(){}.getClass().getEnclosingClass());
于 2013-01-17T19:45:31.410 回答
1

我曾经也有这个奇怪的要求,我试图搜索但没有找到任何东西,所以我想答案是不可能的。

但是我被告知要重新考虑我的方法,当我尝试时,我想出了相同的解决方案,而没有这个奇怪的要求。所以请重新考虑你的方法。我相信你能像我一样解决它。另外,如果您可以发布您要解决的问题/场景,也许我可以提供帮助。

于 2013-01-17T12:39:17.733 回答
1

在 Java 7 中,您可以使用该类java.lang.invoke.MethodHandles

Class c = MethodHandle.lookup().lookupClass()

您可能会收到有关使用原始类型而不是参数化版本的警告,Class<X>但我看不出如何避免这种情况,而无需自己恢复对类名进行硬编码。

于 2013-01-17T12:42:52.740 回答
0

您可以这样做,但需要对您的方法进行一些重新考虑:

试试这个:

class X
{

   public X(String cName)
   {
     try
     {
       Class.forName(cName);
      }catch(ClassNotFoundException cne)
       {}
   }
}

public class Test
{
    static X x1 = new X(Thread.currentThread().getStackTrace()[1].getClassName());
}
于 2013-01-17T12:56:20.650 回答
0

如果你想创建一个日志对象,你可以使用lombok为你注入一个日志对象。页面示例:

@Log
public class LogExample {

  public static void main(String... args) {
    log.error("Something's wrong here");
  }
}
于 2013-01-17T13:22:43.710 回答
0

这里的一些答案有解决方案的想法,但不是我需要的代码片段。所以在这里,在任何 JVM 上工作:

static X s_x = new X(getClassStatic());

public static Class<?> getClassStatic() {
    try {
        // we're using the third highest stack element, since the
        // first highest is the getStackTrace() method, followed by this method itself. We
        // want the calling code's class.
        String name = Thread.currentThread().getStackTrace()[2].getClassName();
        return Class.forName(name);
    } catch (ClassNotFoundException e) {
        // shouldn't be able to get here...
        return null;
    }
}

或者,对于选定的 JVM,按照 Peter Lawrey 的建议:

static X s_x = new X(getCallerClass(1));
于 2013-01-17T13:31:58.550 回答
0

我认为唯一的解决方案是从当前的堆栈跟踪中提取类名(请参阅 参考资料Thread.getStackTrace()),这会将它作为 a 提供给您String,您可以从中获取Class对象 using Class.forName(String),但这比您当前的方法要丑陋得多。

于 2013-01-17T12:41:00.660 回答