在静态方法中如何评估类文字?

时间:2014-08-22 19:41:05

标签: java jls

来自JLS(§15.8.2):

  

类文字计算指定类型(或void)的Class对象,该类对象由当前实例的类的定义类加载器(第12.2节)定义。

这是有道理的,但如果没有“当前实例”怎么办? (即表达式采用类方法,又名'静态方法')

我的直觉告诉我使用相同的规则,将“当前实例的类”换成“类方法类”之类的东西。但是,我在JLS中找不到任何这样的规则,根据我的经验,这些规则往往非常明确。这让我对自己的直觉不确定。

另一种选择是我假设在类方法中没有'当前实例'是不正确的。如果是这样的话 - 在类方法中确定'当前实例'的规则是什么?

3 个答案:

答案 0 :(得分:3)

当前实例的类表示类型为T的 java.lang.Class 的实例。即使考虑的类具有静态方法,它始终是 java.lang.Class 的实例。

您可以在Java文档中获取java.lang.Class的相关说明:

  

类Class的实例表示正在运行的Java应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组也属于一个类,它反映为一个Class对象,由具有相同元素类型和维数的所有数组共享。原始Java类型(boolean,byte,char,short,int,long,float和double)以及关键字void也表示为Class对象。

类没有公共构造函数。相反,类对象是在加载类时由Java虚拟机自动构造的,并且通过调用类加载器中的defineClass方法来构建。

以下示例使用Class对象打印对象的类名:

 void printClassName(Object obj) {
     System.out.println("The class of " + obj +
                        " is " + obj.getClass().getName());
 }

也可以使用类文字获取命名类型(或void)的Class对象。请参阅Java™语言规范的第15.8.2节。例如:

System.out.println("The name of class Foo is: "+Foo.class.getName());

答案 1 :(得分:2)

我认为在这种情况下“实例”是指本身的实例,即类定义,而不是对象实例

class A {}

class B {
    Class<A> a = A.class;
}

此处,表达式A.class在类B内执行。但是,类B可能会使用不同的类加载器多次加载到运行时。因此,当文档说“由当前实例的类的定义类加载器(第12.2节)定义”时,我认为它指的是加载{{1的副本(“实例”)的任何类加载器当前正在执行的类。

简而言之,分配给B的{​​{1}}实例将从加载Class<A>的同一个类加载器加载。

在实践中,这不是您可能不必担心的事情。大多数Java开发人员不必在日常工作中处理多个类加载器。

答案 2 :(得分:0)

class文字永远不会单独出现,它必须始终由类名或基本类型名称限定。当您需要静态访问类对象时,应使用class。当您需要在运行时访问对象类时,应使用someObject.getClass()

因此:

public class Foo {
  public static String getMyFooClassNameStatic_good() {
    return Foo.class.getName(); // ok
  }

  public static String getBarClassName() {
    // the Bar class will be looked up in the same class loader as 
    // the one that the the Foo CLASS instance was loaded from that 
    // is executing this method.  So if there are multiple versions 
    // of Bar floating around, the one you will get is the one that
    // was loaded from the same class loader as the loaded Foo.  That's
    // what the language about "current instance" in the spec is 
    // getting at.
    return Bar.class.getName(); 
  }

  public static String getMyFooClassNameStatic_bad() {
    return class.getName(); // syntax error - 
    // use one of:
    // Foo.class.getName()
    // (new Foo()).getClass().getName()
    // Class.forName("Foo").getName()
  }

  public static String getIntClassName() {
    return int.class.getName(); // ok
  }
}