文章目录
当前java版本: 17.0.7
类定义
public final class Class<T> implements java.io.Serializable,
GenericDeclaration,
Type,
AnnotatedElement,
TypeDescriptor.OfField<Class<?>>,
Constable {
// ...
}
GenericDeclaration接口
Java 反射 API 中的一个接口,用于表示可以声明泛型类型参数的类。Java 泛型系统的一部分,它主要用于描述声明类型参数的元素,比如类、接口、方法和构造函数。它的常见实现类包括 Class、Method 和 Constructor。
public interface GenericDeclaration extends AnnotatedElement {
/**
* 返回该元素声明的泛型类型参数; 返回一个TypeVariable<?>[]对象数组,按声明顺序表示此GenericDeclaration对象所表示泛型类型参数。
* 如果基础泛型声明没有声明类型变量,则返回长度为0的数组。
*/
public TypeVariable<?>[] getTypeParameters();
}
例如,如果某个类声明为 public class MyClass<T> {…},则该getTypeParameters
方法会返回一个 TypeVariable 数组,其中包含一个代表 T 的类型变量。
import java.lang.reflect.*;
public class GenericDeclarationExample<T> {
public <U> void sampleMethod() {
// 空方法
}
public static void main(String[] args) throws NoSuchMethodException {
// 获取类的声明类型参数
GenericDeclarationExample<String> example = new GenericDeclarationExample<>();
Class<?> clazz = example.getClass();
// 获取类的泛型参数(这里是 <T>)
TypeVariable<?>[] typeParameters = clazz.getTypeParameters();
System.out.println("Class Type Parameters:");
for (TypeVariable<?> typeVariable : typeParameters) {
System.out.println(typeVariable.getName());
}
// 获取方法的泛型参数(这里是 <U>)
Method method = clazz.getMethod("sampleMethod");
TypeVariable<?>[] methodTypeParameters = method.getTypeParameters();
System.out.println("Method Type Parameters:");
for (TypeVariable<?> typeVariable : methodTypeParameters) {
System.out.println(typeVariable.getName());
}
}
}
运行结果
Class Type Parameters:
T
Method Type Parameters:
U
AnnotatedElement 接口
AnnotatedElement 是 Java 反射 API 中的另一个接口,GenericDeclaration 继承了它。AnnotatedElement 提供了操作和访问注解的相关方法,因此 GenericDeclaration 可以同时处理注解和泛型声明。
常见的 AnnotatedElement 方法包括:
• isAnnotationPresent(Class<? extends Annotation> annotationClass): 判断是否存在某个注解。
• getAnnotation(Class<A> annotationClass): 获取指定类型的注解。
Type接口
作用:Type 接口是 Java 反射 API 中的一个基础接口,用来表示 Java 中所有类型。它被用来获取和表示在运行时可访问的类型信息,比如类、接口、数组、原始类型、泛型类型等。
实现类:
• Class<?>:表示具体的类或接口类型。
• ParameterizedType:表示泛型类或接口类型(例如 List<String>)。
• GenericArrayType:表示泛型数组类型(例如 T[])。
• WildcardType:表示泛型通配符类型(例如 ? extends Number)。
• TypeVariable:表示类型变量(例如 T)。
在 Class 中的作用:Class 实现了 Type 接口,因此它可以表示所有的类和接口。通过 Type,你可以访问更为详细的类型信息,特别是在处理泛型时,例如通过反射 API 获取泛型类型参数的信息。
获取Class类的方法
1.通过.class
1.int.class、Integer.class、Enum.class
@Test
void primitiveType() {
Class<Integer> intClass = int.class;
Class<Integer> integerClass1 = Integer.class;
System.out.println(intClass == integerClass1); // false
Integer a = 1;
System.out.println(a.getClass() == integerClass1); // true
System.out.println(intClass); // int
System.out.println(a.getClass()); // class java.lang.Integer
Class<? super Integer> intSuperclass = intClass.getSuperclass();
Type intGenericSuperclass = intClass.getGenericSuperclass();
Class<?>[] intInterfaces = intClass.getInterfaces();
Type[] intGenericInterfaces = intClass.getGenericInterfaces();
System.out.println("int:superclass:" + intSuperclass); // null
System.out.println("int:genericSuperclass:" + intGenericSuperclass); // null
System.out.println("int:interfaces:" + intInterfaces); // [Ljava.lang.Class;@568bf312
System.out.println("int:genericInterfaces:" + intGenericInterfaces); // [Ljava.lang.Class;@ca263c2
Class<? super Integer> superclass = integerClass1.getSuperclass();
Type genericSuperclass = integerClass1.getGenericSuperclass();
Class<?>[] interfaces = integerClass1.getInterfaces();
Type[] genericInterfaces = integerClass1.getGenericInterfaces();
System.out.println("integer:superclass:" + superclass); // class java.lang.Number
System.out.println("integer:genericSuperclass:" + genericSuperclass); // class java.lang.Number
System.out.println("integer:interfaces:" + interfaces); // [Ljava.lang.Class;@8e0379d
System.out.println("integer:genericInterfaces:" + genericInterfaces); // [Ljava.lang.reflect.Type;@341b80b2
}
枚举类
@AllArgsConstructor
@Getter
public enum YesNo {
YES(1, "是"),
NO(0, "否");
private final Integer code;
private final String desc;
}
@Test
void enumTest() {
Class<? extends YesNo> aClass = YesNo.YES.getClass();
System.out.println(aClass); // class per.qiao.myutils.enums.YesNo
System.out.println(aClass.isEnum()); // true
// 获取所有的枚举元素
YesNo[] enumConstants = aClass.getEnumConstants();
Arrays.stream(enumConstants).forEach(System.out::println); // YES NO
Map<String, ? extends YesNo> stringMap = EnumUtils.enum2Map(aClass);
for (Map.Entry<String, ? extends YesNo> me : stringMap.entrySet()) {
System.out.println(me.getKey() + ":" + me.getValue());
}
Map<String, YesNo> stringYesNoMap = EnumUtils.enum2Map(YesNo.class);
for (Map.Entry<String, YesNo> stringYesNoEntry : stringYesNoMap.entrySet()) {
System.out.println(stringYesNoEntry.getKey() + ":" + stringYesNoEntry.getValue());
}
YesNo enumBypProperties = EnumUtils.getEnumBypProperties(YesNo.class, YesNo::getCode, 1);
System.out.println(enumBypProperties);
String desc = EnumUtils.getValByKey(YesNo.class, YesNo::getCode, YesNo::getDesc, 0);
System.out.println(desc);
}
枚举工具类
public class EnumUtils {
private static final Map<Class<?>, Map<String, ?>> ENUM_MAP = new ConcurrentHashMap<>();
/**
* 将枚举类转换为map; key:枚举类的名称 value:枚举类对象
* <blockquote><pre>{@code
Map<String, YesNo> stringYesNoMap = EnumUtils.enum2Map(YesNo.class);
for (Map.Entry<String, YesNo> me : stringYesNoMap.entrySet()) {
System.out.println(me.getKey() + ":" + me.getValue());
}
* }</pre></blockquote>
* @param clazz 枚举类class
* @return 枚举类map
* @param <T> 枚举类类型
*/
@SuppressWarnings("unchecked")
public static <T extends Enum<?>> Map<String, T> enum2Map(Class<T> clazz) {
Map<String, T> result = new HashMap<>();
if (!clazz.isEnum()) {
return result;
}
if (ENUM_MAP.containsKey(clazz)) {
return (Map<String, T>) ENUM_MAP.get(clazz);
}
Enum<?>[] enumConstants = clazz.getEnumConstants();
for (Enum<?> enumConstant : enumConstants) {
result.put(enumConstant.name(), (T) enumConstant);
}
ENUM_MAP.put(clazz, result);
return result;
}
/**
* 根据属性获取枚举, 默认返回null
* <pre>
* EnumUtils.getEnumBypProperties(YesNo.class, YesNo::getCode, 1);
* </pre>
* @param clazz 枚举类型
* @param valFunc 属性的获取方法
* @param val 属性值
* @return 枚举对象
* @param <T> 枚举类型
* @param <V> 属性值类型
*/
@SuppressWarnings("unchecked")
public static <T extends Enum<?>, V> T getEnumBypProperties(Class<T> clazz, Function<T, V> valFunc, V val) {
Enum<?>[] enumConstants = clazz.getEnumConstants();
for (Enum<?> enumConstant : enumConstants) {
T t = (T) enumConstant;
V obj = valFunc.apply(t);
if (val.getClass().isPrimitive()) {
if (obj == val) {
return t;
}
} else {
if (obj != null && obj.equals(val)) {
return t;
}
}
}
return null;
}
/**
* 根据key获取枚举值, 默认返回null
* <pre>
* EnumUtils.getValByKey(YesNo.class, YesNo::getCode, YesNo::getDesc, 0);
* </pre>
* @param clazz 枚举类型
* @param keyFunc key的获取方法
* @param valFunc 值的获取方法
* @param keyParam key参数
* @return key对应的值
* @param <T> 枚举类型
* @param <K> key类型
* @param <V> 值类型
*/
@SuppressWarnings("unchecked")
public static <T extends Enum<?>, K, V> V getValByKey(Class<T> clazz, Function<T, K> keyFunc, Function<T, V> valFunc, K keyParam) {
Enum<?>[] enumConstants = clazz.getEnumConstants();
for (Enum<?> enumConstant : enumConstants) {
T t = (T) enumConstant;
K key = keyFunc.apply(t);
if (keyParam.getClass().isPrimitive()) {
if (keyParam == key) {
return valFunc.apply(t);
}
} else {
if (key != null && key.equals(keyParam)) {
return valFunc.apply(t);
}
}
}
return null;
}
}
注解类
@Test
void annotationTest() {
Class<AllArgsConstructor> userInfoClass = AllArgsConstructor.class;
System.out.println(userInfoClass); // interface lombok.AllArgsConstructor
System.out.println(userInfoClass.isAnnotation()); // true
}
数组类型
@Test
void arrayTest() {
int[] arr1 = {1, 2, 3};
Class<? extends int[]> aClass = arr1.getClass();
// Class<int[]> nowDimArrayClass = int[].class;
System.out.println(aClass); // class [I
System.out.println(aClass.isArray()); // true
// 获取数组的元素类型
System.out.println(aClass.getComponentType()); // int
int[][] arr2 = {{1, 2}, {3, 4}};
Class<? extends int[][]> aClass1 = arr2.getClass(); // class [[I
System.out.println(aClass1);
System.out.println(aClass1.isArray()); // true
System.out.println(aClass1.getComponentType()); // class [I
Class<?> componentType = aClass1.getComponentType();
Class<?> componentType1 = componentType.getComponentType();
// 二维数组的元素类型
System.out.println(componentType1);
}
void类型
@Test
void voidTest() {
Class<Void> voidClass = void.class;
System.out.println(voidClass);
System.out.println(voidClass == void.class); // true
System.out.println(voidClass.isPrimitive()); // true
}
Class.forName
通过反射
public class TempClass implements Serializable {
private static final long serialVersionUID = 1L;
static {
System.out.println("静态代码块执行了");
}
private String firstName;
public TempClass() {
System.out.println("TempClass类实例化了");
}
public void hello() {
System.out.println("hello world");
}
public static String getName(String name) {
return "getName" + name;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getFirstName() {
return firstName;
}
}
@Test
void classForNameTest() {
try {
// 获取class; 默认会执行类的静态代码块
Class.forName("per.qiao.myutils.clazz.TempClass");
ClassLoader platformClassLoader = this.getClass().getClassLoader();
// 使用参数指定需不需要执行静态代码块
Class<?> aClass = Class.forName("per.qiao.myutils.clazz.TempClass", false, platformClassLoader);
System.out.println("是否为编译器自动生成的类:" + aClass.isSynthetic()); // false
// System.out.println(aClass);
} catch (Exception e) {
e.printStackTrace();
}
}
类加载器获取Class对象
@Test
void classLoadTest() throws Exception {
// 获取class; 不会执行类的静态代码块
Class<?> aClass = ClassGenerateTest.class.getClassLoader().loadClass("per.qiao.myutils.clazz.TempClass");
}
使用 MethodHandles.Lookup.defineClass 定义类
/**
* 使用 MethodHandles.Lookup.defineClass 定义类
* @throws Throwable
*/
@Test
void MethodHandlesLookupDefineClassTest() throws Throwable {
Path path = Paths.get("/Users/qiaoyueping/project/myproject/myutils/target/classes/per/qiao/myutils/clazz/TempClass.class");
// 类的字节码
byte[] bytecodes = Files.readAllBytes(path);
// 加密
String classStr = Base64.getEncoder().encodeToString(bytecodes);
// 解密
// byte[] classInBytes = Base64.getDecoder().decode(classStr);
System.out.println(classStr);
MethodHandles.Lookup lookup = MethodHandles.lookup();
Class<?> dynamicClass = lookup.defineClass(bytecodes);
System.out.println("是否为编译器自动生成的类:" + dynamicClass.isSynthetic()); // false
System.out.println("类名:" + dynamicClass.getName());
// 输出类有哪些函数
for(Method method : dynamicClass.getDeclaredMethods()) {
System.out.println("方法名:" + method.getName());
}
// 非静态方法要这么使用; 使用 privateLookupIn 获取 TempClass 的专属权限
MethodHandles.Lookup privateLookupIn = MethodHandles.privateLookupIn(dynamicClass, lookup);
// 创建 TempClass 的实例
Object tempClassInstance = dynamicClass.getDeclaredConstructor().newInstance();
// 2. 调用hello函数(普通方法)
MethodHandle mh = privateLookupIn.findSpecial(dynamicClass, "hello", MethodType.methodType(void.class), dynamicClass);
mh.invoke(tempClassInstance);
// 调用静态方法
MethodHandle getName = privateLookupIn.findStatic(dynamicClass, "getName", MethodType.methodType(String.class, String.class));
Object obj = getName.invoke("动态类型测试");
System.out.println(obj);
// getName.invokeExact("动态类型测试");
Object obj2 = getName.invokeWithArguments("动态类型测试2");
System.out.println(obj2);
}
隐藏类
/**
* 生成隐藏类; 隐藏类不能被其它类型调用, 只能用在当前session
* @throws Throwable
*/
@Test
void MethodHandlesLookupDefineHiddenClass() throws Throwable {
Path path = Paths.get("/Users/qiaoyueping/project/myproject/myutils/target/classes/per/qiao/myutils/clazz/TempClass.class");
// 类的字节码
byte[] classBytes = Files.readAllBytes(path);
MethodHandles.Lookup lookup = MethodHandles.lookup();
Class<?> hiddenClass = lookup.defineHiddenClass(classBytes, true, MethodHandles.Lookup.ClassOption.NESTMATE)
.lookupClass();
System.out.println("是否为编译器自动生成的类:" + hiddenClass.isSynthetic()); // false
System.out.println("类名:" + hiddenClass.getName());
System.out.println("toGenericString:" + hiddenClass.toGenericString());
System.out.println("是否为隐藏类:" + hiddenClass.isHidden()); // true
for (Method method : hiddenClass.getDeclaredMethods()) {
System.out.println("方法名:" + method.getName());
}
// 调用hello方法
Object tempClassInstance = hiddenClass.getDeclaredConstructor().newInstance();
MethodHandle hello = lookup.findVirtual(hiddenClass, "hello", MethodType.methodType(void.class));
hello.invoke(tempClassInstance);
// 使用findSpecial
MethodHandles.Lookup privateLookupIn = MethodHandles.privateLookupIn(hiddenClass, lookup);
MethodHandle mh = privateLookupIn.findSpecial(hiddenClass, "hello", MethodType.methodType(void.class), hiddenClass);
mh.invoke(tempClassInstance);
}
序列化与反序列化生成Class
@Test
void serializableTest() throws Exception {
TempClass tempClass = new TempClass();
tempClass.setFirstName("qiao");
System.out.println(tempClass.getFirstName());
// ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("temp.txt"));
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(byteArrayOutputStream);
oos.writeObject(tempClass);
oos.close();
// ObjectInputStream ois = new ObjectInputStream(new FileInputStream("temp.txt"));
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
ObjectInputStream ois = new ObjectInputStream(byteArrayInputStream);
// 这里并不会调用构造器
Object o = ois.readObject();
System.out.println("是否为编译器自动生成的类:" + o.getClass().isSynthetic()); // false
TempClass tempClass1 = (TempClass) o;
System.out.println(tempClass1.getFirstName());
}
动态代理
public interface Hello {
void sayHello();
default void sayHi() {
System.out.println("hi");
}
}
/**
* 动态代理;动态生成的代理类会通过类加载器加载。
* 实际上,JVM 在内部会使用 java.lang.reflect.Proxy 类来生成这个动态代理的字节码,并将其加载为 Class 对象
*/
@Test
void proxyTest() {
Hello proxy = (Hello) Proxy.newProxyInstance(
Hello.class.getClassLoader(),
new Class<?>[] { Hello.class },
(obj, method, args) -> {
if (method.isDefault()) {
return InvocationHandler.invokeDefault(obj, method, args);
} else if ("sayHello".equals(method.getName())) {
System.out.println("Hello from sayHello!");
return null;
}
return method.invoke(obj, args);
});
proxy.sayHi();
proxy.sayHello();
System.out.println(proxy.getClass().isSynthetic()); // false
}
类加载器获取
/**
* 自定义类加载器
*/
public class MyClassLoader extends ClassLoader {
private String path;
public MyClassLoader(String path) {
this.path = path;
}
@Override
public Class<?> findClass(String name) throws ClassNotFoundException {
try {
String replaceName = name.replace('.', File.separatorChar);
FileInputStream fis = new FileInputStream(path + replaceName + ".class");
byte[] bytes = new byte[fis.available()];
fis.read(bytes);
fis.close();
return defineClass(name, bytes, 0, bytes.length);
} catch (IOException e) {
throw new ClassNotFoundException("Class not found: " + name, e);
}
}
}
@Test
void defineClassTest() throws Exception {
MyClassLoader myClassLoader = new MyClassLoader("/Users/qiaoyueping/project/myproject/myutils/target/classes/");
Class<?> clazz = myClassLoader.findClass("per.qiao.myutils.clazz.TempClass");
System.out.println(clazz.getName());
System.out.println(clazz.isSynthetic()); // false
}
字节码操作库
使用asm动态创建对象
@Test
void asmTest() throws Exception {
// 创建 ClassWriter,指定自动计算栈和局部变量大小
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
String packagePath = "per/qiao/myutils/clazz/proxy";
String className = "HelloWorld";
String fullClassName = packagePath + "/" + className; // 类的完整路径
// 定义类的基本信息:版本号,访问标志,类名,签名,父类,接口
classWriter.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, fullClassName, null, "java/lang/Object", null);
// 创建默认构造函数
MethodVisitor constructor = classWriter.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
constructor.visitCode();
constructor.visitVarInsn(Opcodes.ALOAD, 0);
constructor.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
constructor.visitInsn(Opcodes.RETURN);
constructor.visitMaxs(0, 0);
constructor.visitEnd();
// 创建 sayHello 方法
MethodVisitor method = classWriter.visitMethod(Opcodes.ACC_PUBLIC, "sayHello", "()V", null, null);
method.visitCode();
method.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
method.visitLdcInsn("Hello, World!");
method.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
method.visitInsn(Opcodes.RETURN);
method.visitMaxs(0, 0);
method.visitEnd();
// 结束类的创建
classWriter.visitEnd();
// 将生成的字节码写入文件
String path = "/Users/qiaoyueping/project/myproject/myutils/target/classes/";
String filePath = path + packagePath + "/" + className + ".class";
File file = new File(filePath);
if (!file.exists()) {
file.createNewFile();
}
// 将生成的字节码写入文件
byte[] byteCode = classWriter.toByteArray();
try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write(byteCode);
}
System.out.println("Class generated: HelloWorld");
String packageName = fullClassName.replace('/', '.');
// 加载动态生成的 HelloWorld 类
Class<?> helloWorldClass = Class.forName(packageName);
Object helloWorldInstance = helloWorldClass.getDeclaredConstructor().newInstance();
helloWorldClass.getMethod("sayHello").invoke(helloWorldInstance); // Hello, World!
}
Java Compiler API
@Test
void JavaCompilerAPITest() throws Exception {
// 1. 源代码字符串,直接在内存中定义
String sourceCode = """
import java.util.*;
public class HelloWorld {
public void sayHello() {
System.out.println("Hello, In-Memory World!");
}
public void aa() {
List<String> list = new ArrayList<>();
list.add("aa");
list.add("bb");
System.out.println(list);
}
}
""";
// 2. 创建一个内存中的 JavaFileObject,表示源代码
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
InMemoryJavaFileObject javaFileObject = new InMemoryJavaFileObject("HelloWorld", sourceCode);
// 3. 创建一个内存管理器,用于处理编译结果
InMemoryFileManager fileManager = new InMemoryFileManager(compiler.getStandardFileManager(null, null, null));
// 4. 编译源代码
StringWriter writer = new StringWriter();
Boolean success = compiler.getTask(writer, fileManager, null, null, null, Arrays.asList(javaFileObject)).call();
if (!success) {
System.out.println("Compilation failed: " + writer);
return;
}
// 5. 从内存中加载生成的类
Class<?> helloWorldClass = fileManager.getClassLoader(null).loadClass("HelloWorld");
// 6. 创建实例并调用方法
Object instance = helloWorldClass.getDeclaredConstructor().newInstance();
Method sayHelloMethod = helloWorldClass.getMethod("sayHello");
sayHelloMethod.invoke(instance); // 输出 "Hello, In-Memory World!"
Method aaMethod = helloWorldClass.getMethod("aa");
aaMethod.invoke(instance);
}
// 自定义 JavaFileObject 实现,用于表示内存中的源代码
static class InMemoryJavaFileObject extends SimpleJavaFileObject {
private final String sourceCode;
public InMemoryJavaFileObject(String className, String sourceCode) {
super(URI.create("string:///" + className + Kind.SOURCE.extension), Kind.SOURCE);
this.sourceCode = sourceCode;
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return sourceCode;
}
}
// 自定义 JavaFileObject 实现,用于存储编译后的字节码
static class InMemoryClassFileObject extends SimpleJavaFileObject {
private final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
public InMemoryClassFileObject(String className, Kind kind) {
super(URI.create("mem:///" + className + kind.extension), kind);
}
@Override
public OutputStream openOutputStream() {
return byteArrayOutputStream;
}
public byte[] getBytecode() {
return byteArrayOutputStream.toByteArray();
}
}
// 内存中的 FileManager,用于管理 JavaFileObjects
static class InMemoryFileManager extends ForwardingJavaFileManager<StandardJavaFileManager> {
private final Map<String, InMemoryClassFileObject> classFileObjects = new HashMap<>();
public InMemoryFileManager(StandardJavaFileManager standardManager) {
super(standardManager);
}
@Override
public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, FileObject sibling) {
InMemoryClassFileObject classFileObject = new InMemoryClassFileObject(className, kind);
classFileObjects.put(className, classFileObject);
return classFileObject;
}
@Override
public ClassLoader getClassLoader(Location location) {
return new ClassLoader() {
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
InMemoryClassFileObject classFileObject = classFileObjects.get(name);
if (classFileObject != null) {
byte[] byteCode = classFileObject.getBytecode();
return defineClass(name, byteCode, 0, byteCode.length);
}
return super.findClass(name);
}
};
}
}
总结
通过 Class 类的静态方法获取已加载类的 Class 对象。例如,String.class 可以直接获取 String 类的 Class 对象,而不需要通过类加载器。