1. 什么是Class
java中一切皆对象。java中所有的类或接口(enum或annotation也是一种接口)其实都是对象,它们都是Class类的实例。数组类型也是一种Class对象,它抽象了所有元素类型相同且维度相同的数组。基础数据类型(比如int、byte)也可以作为Class类的对象。
2. 获取Class对象
Class对象是在类加载时由java虚拟机自动创建的。
/*
* 构造器为private,只有JVM才能创建Class对象
*/
private Class(ClassLoader loader) {
// Initialize final field for classLoader. The initialization value of non-null
// prevents future JIT optimizations from assuming this final field is null.
classLoader = loader;
}
(1)我们可以通过对某个对象obj调用它的getClass方法就可以获取到这个对象所属类的Class对象。比如:
Number n = 0;
Class<? extends Number> c = n.getClass();
getClass方法被定义Object类中。该方法返回调用对象的运行时类。注意到,真实的返回值类型应该是这个调用对象类的超类。
/**
* <p><b>The actual result type is {@code Class<? extends |X|>}
* where {@code |X|} is the erasure of the static type of the
* expression on which {@code getClass} is called.
*
*/
public final native Class<?> getClass();
此外,如果我们对泛型对象调用getClass方法类获取其运行时类对象,将无法获取到泛型信息,因为在java中的泛型信息在编译期都会被擦除。比如:
List<Integer> list = new ArrayList<>();
Class<? extends List> aClass = list.getClass();
System.out.println(aClass);//结果是class java.util.ArrayList
(2)通过形如String.class的方式获取到类的Class对象,“."号前为类的字面名称。比如:
Class<String> stringClass = String.class;
(3)通过调用Class类中的forName方法来获取Class对象,参数为类的完整名称(具体到哪个包下的哪个类)。比如:
Class<?> string = Class.forName("java.lang.String");
其中的Class<?>等价于Class。
3. 将Class对象转换成字符串
3.1 toString()方法
该方法将一个Class对象转化为一个字符串。
首先,判断该对象是interface、基本数据类型还是class,然后调用getName方法获得全类名。
如果这个Class对象表示的是基本数据类型,则getName会返回基本类型的名称;
如果表示的是void类型,则getName会返回“void"。
public String toString() {
return (isInterface() ? "interface " : (isPrimitive() ? "" : "class "))
+ getName();
}
比如:
String str = "abc";
Class strClass = str.getClass();
String s1 = strClass.toString();
System.out.println(s1);//得到class java.lang.String
3.2 toGenericString()方法
该方法返回更详细的类信息,除了全类名外,还包括修饰符和泛型类型参数。比如:
Map<Integer,String> map = new HashMap<>();
Class<? extends Map> mapClass = map.getClass();
String s = mapClass.toGenericString();
System.out.println(s);//得到 public class java.util.HashMap<K,V>
下面具体来看toGenericString方法。
public String toGenericString() {
//如果是原始数据类型,则不存在修饰符和类型信息
if (isPrimitive()) {
return toString();
} else {
//新建一个StringBuilder对象,用于拼接各类信息
StringBuilder sb = new StringBuilder(