Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Java中从静态方法调用getClass()?_Java_Static Methods - Fatal编程技术网

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

如何在Java中从静态方法调用getClass()?,java,static-methods,Java,Static Methods,我有一个类,它必须有一些静态方法。在这些静态方法中,我需要调用getClass()方法进行以下调用: public static void startMusic() { URL songPath = getClass().getClassLoader().getResource("background.midi"); } 但是Eclipse告诉我: Cannot make a static reference to the non-static method getClass() fro

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

public static void startMusic() {
  URL songPath = getClass().getClassLoader().getResource("background.midi");
}
但是Eclipse告诉我:

Cannot make a static reference to the non-static method getClass() 
from the type Object
修复此编译时错误的适当方法是什么?

答案 只需使用
classname.class
而不是
getClass()

申报伐木工人 由于这对于一个特定的用例(提供一种插入日志声明的简单方法)非常重要,我想我应该补充一下我的想法。日志框架通常期望日志被约束到特定的上下文中,比如说一个完全限定的类名。因此,如果不进行修改,它们是不可复制的。其他答案中提供了粘贴安全日志声明的建议,但它们也有缺点,如增加字节码或添加运行时内省。我不推荐这些。复制粘贴是一个编辑器问题,因此编辑器解决方案是最合适的

在IntelliJ中,我建议添加一个活动模板:

  • 使用“log”作为缩写
  • 使用
    private static final org.slf4j.Logger Logger=org.slf4j.LoggerFactory.getLogger($CLASS$.CLASS)作为模板文本
    
  • 单击编辑变量并使用表达式
    className()
  • 选中复选框以重新格式化和缩短FQ名称
  • 将上下文更改为Java:declaration
现在,如果您键入
log
,它将自动展开为

private static final Logger logger = LoggerFactory.getLogger(ClassName.class);

并自动为您重新格式化和优化导入。

只需使用类文字,即
NameOfClass。class
getClass()
方法在对象类中定义,并具有以下签名:

公共最终类getClass()

因为它没有定义为静态的,所以不能在静态代码块中调用它。有关更多信息,请参见以下答案:

如果处于静态上下文中,则必须使用类文字表达式来获取类,因此基本上必须执行以下操作:

Foo.class

这种类型的表达式称为类字面值,其解释如下:

类文字是由类、接口、数组或基元类型的名称后跟“.”和标记类组成的表达式。类文本的类型是class。它计算为当前实例类的定义类加载器定义的命名类型(或void)的类对象


您还可以在for Class上找到有关此主题的信息。

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

class MyClass {
  public static void startMusic() {
    URL songPath = MyClass.class.getResource("background.midi");
  }
}
这种方法仍然有一个缺点,即当您需要将此代码复制到许多类似的类时,它不能非常安全地防止复制/粘贴错误

至于标题中的确切问题,有一个技巧贴在报纸上:

它使用嵌套的匿名
对象
子类来获取执行上下文。此技巧的优点是复制/粘贴安全

在其他类继承自的基类中使用此选项时要小心:


还值得注意的是,如果这个代码段被塑造成某个基类的静态方法,那么
currentClass
值将始终是对该基类的引用,而不是对可能使用该方法的任何子类的引用。

我自己也在努力解决这个问题。一个很好的技巧是在静态上下文中使用当前线程获取类加载器。这也适用于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;
}

试试这样的。它对我有用。日志(类名)


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

MethodHandles.lookup().lookupClass()
试试看


假设有一个实用程序类,那么示例代码将是——

    URL url = Utility.class.getClassLoader().getResource("customLocation/".concat("abc.txt"));
CustomLocation—如果资源中有任何文件夹结构,请删除此字符串文字

我也有同样的问题! 但要解决这个问题,只需修改代码如下

public static void startMusic() {
URL songPath = YouClassName.class.getClassLoader().getResource("background.midi");
}

这对我来说很好,希望它也能对您很好。

在出现用户定义(例如非J2SE)类的实例之前使用
getResource()
有时会失败。问题是JRE在那个阶段将使用引导类装入器,而引导类装入器的类路径上没有应用程序资源。class.class的名称是显而易见的,但这要求您知道类的名称。GetEnclosuringClass技巧不仅适用于复制粘贴,也适用于静态基类方法,这些方法间接地利用了内省
类。getResource()
的行为可能与
类加载器.getResource()
稍有不同;请参阅“不确定为什么要提供此线程中已有的相同答案”三次:从2011年起两次,从2013年起一次。如果类加载器通过访问“resources\\config”文件夹加载类日志,则此解决方案有效。在一些具有多个类加载器的服务器上(例如,一个类加载器用于加载lib文件夹,另一个用于加载app lib和资源),情况并非如此。出于这个原因,这个答案的解决方案有时只是巧合!如果您只需要getSimpleName()调用来打印main方法的帮助,那么这是一个不错的解决方案。我正在寻找一个“复制粘贴”解决方案,用于在不每次更改类名的情况下,随时随地添加记录器。你给了我:
private static final Logger LOG=LoggerFactory.getLogger(MethodHandles.lookup().lookupClass())受支持的最佳解决方案,缺点是Android在API 26(即Android 8)之前不支持此功能。当运行错误代码时,这将导致复制/粘贴和sad结果
Thread.currentThread().getStackTrace()[1].getClassName()
Thread.currentThread().getStackTrace()[2].getClassName()
    URL url = Utility.class.getClassLoader().getResource("customLocation/".concat("abc.txt"));
public static void startMusic() {
URL songPath = YouClassName.class.getClassLoader().getResource("background.midi");
}