来自JLS(§15.8.2):
类文字计算指定类型(或void)的Class对象,该类对象由当前实例的类的定义类加载器(第12.2节)定义。
这是有道理的,但如果没有“当前实例”怎么办? (即表达式采用类方法,又名'静态方法')
我的直觉告诉我使用相同的规则,将“当前实例的类”换成“类方法类”之类的东西。但是,我在JLS中找不到任何这样的规则,根据我的经验,这些规则往往非常明确。这让我对自己的直觉不确定。
另一种选择是我假设在类方法中没有'当前实例'是不正确的。如果是这样的话 - 在类方法中确定'当前实例'的规则是什么?
答案 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
}
}