如何从Java中的静态方法调用getClass()?

Ram*_*ama 334 java static-methods

我有一个必须有一些静态方法的类.在这些静态方法中,我需要调用方法getClass()来进行以下调用:

public static void startMusic() {
  URL songPath = getClass().getClassLoader().getResource("background.midi");
}
Run Code Online (Sandbox Code Playgroud)

然而Eclipse告诉我:

Cannot make a static reference to the non-static method getClass() 
from the type Object
Run Code Online (Sandbox Code Playgroud)

修复此编译时错误的适当方法是什么?

Mar*_*ers 578

只需使用TheClassName.class而不是getClass().

  • 当不正确的代码在另一个类中运行时,这将导致复制/粘贴和令人悲伤的结果。 (3认同)

Ser*_*kov 113

至于问题中的代码示例,标准解决方案是通过名称显式引用类,甚至可以不进行getClassLoader()调用:

class MyClass {
  public static void startMusic() {
    URL songPath = MyClass.class.getResource("background.midi");
  }
}
Run Code Online (Sandbox Code Playgroud)

这种方法仍有一个背面,即如果您需要将此代码复制到许多类似的类,它对复制/粘贴错误不是很安全.

至于标题中的确切问题,相邻线程中有一个技巧:

Class currentClass = new Object() { }.getClass().getEnclosingClass();
Run Code Online (Sandbox Code Playgroud)

它使用嵌套的匿名Object子类来获取执行上下文.这个技巧有复制/粘贴安全的好处......

在其他类继承的基类中使用它时的注意事项:

值得注意的是,如果此片段被形成为某个基类的静态方法,则currentClassvalue将始终是对该基类的引用,而不是对可能正在使用该方法的任何子类的引用.

  • 到目前为止我最喜欢的答案 NameOfClass.class很明显,但这需要您知道您的类的名称.getEnclosingClass技巧不仅对复制粘贴很有用,对于利用内省的静态基类方法也很有用. (22认同)
  • 顺便提一下,`Class.getResource()` 的行为可能与 `ClassLoader.getResource()` 略有不同;见 http://stackoverflow.com/a/676273 (2认同)

Rei*_*ein 63

在Java7 +中,您可以在静态方法/字段中执行此操作:

MethodHandles.lookup().lookupClass()
Run Code Online (Sandbox Code Playgroud)

  • 我一直在寻找一种"复制粘贴"解决方案,用于在每个地方添加记录器,而不是每次都更改类名.你把它给了我:`private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());` (3认同)

小智 22

我自己也在努力.一个很好的技巧是使用当前线程在静态上下文中获取ClassLoader.这也适用于Hadoop MapReduce.其他方法在本地运行时有效,但在MapReduce中使用时返回null InputStream.

public static InputStream getResource(String resource) throws Exception {
   ClassLoader cl = Thread.currentThread().getContextClassLoader();
   InputStream is = cl.getResourceAsStream(resource);
   return is;
}
Run Code Online (Sandbox Code Playgroud)


Mic*_*rdt 14

只需使用一个类文字,即 NameOfClass.class


mel*_*lik 10

getClass() 方法在Object类中定义,具有以下签名:

public final类getClass()

由于未定义为static,因此无法在静态代码块中调用它.有关更多信息,请参阅以下答案:Q1,Q2,Q3.

如果你处于静态上下文中,那么你必须使用类文字表达式来获取Class,所以你基本上必须这样做:

让Foo.class

这种类型的表达式称为类文字,它们在Java语言规范手册中进行了解释,如下所示:

类文字是一个表达式,由类,接口,数组或基本类型的名称组成,后跟一个"." 和令牌类.类文字的类型是Class.它计算为由当前实例的类的定义类加载器定义的命名类型(或void)的Class对象.

您还可以在Class的API文档中找到有关此主题的信息.


小智 7

试试吧

Thread.currentThread().getStackTrace()[1].getClassName()
Run Code Online (Sandbox Code Playgroud)

要么

Thread.currentThread().getStackTrace()[2].getClassName()
Run Code Online (Sandbox Code Playgroud)