Java Class类
什么是Class类
在Java中,Class
类是反射机制的基础和入口点。每当我们定义一个新的类,Java虚拟机(JVM)就会创建一个Class
对象来描 述这个类的各种信息,包括类名、包名、构造方法、成员变量、成员方法等。Class
类位于java.lang
包中,是Java反射API的核心。
简单来说,Class
类是用来描述Java类的元数据的类,也就是"类的类"。
提示
Class
类的实例表示正在运行的Java应用程序中的类和接口。枚举类型是一种类,注解是一种接口。
获取Class对象的方式
在Java中,有三种主要方法可以获取一个类的Class
对象:
1. 使用类的全限定名
通过Class.forName()
静态方法获取:
try {
Class<?> clazz = Class.forName("java.lang.String");
System.out.println("类名: " + clazz.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
输出结果:
类名: java.lang.String
2. 通过类的实例获取
使用对象的getClass()
方法:
String str = "Hello";
Class<?> clazz = str.getClass();
System.out.println("类名: " + clazz.getName());
输出结果:
类名: java.lang.String
3. 通过类字面常量获取
使用.class
语法(最简单、最安全):
Class<?> clazz = String.class;
System.out.println("类名: " + clazz.getName());
输出结果:
类名: java.lang.String
备注
使用.class
方式获取Class
对象不会初始化该类,而Class.forName()
会触发类的初始化。
Class类的常用方法
Class
类提供了许多方法来获取类的信息:
获取类的基本信息
Class<?> clazz = Student.class;
// 获取完整类名
System.out.println("完整类名: " + clazz.getName());
// 获取简单类名
System.out.println("简单类名: " + clazz.getSimpleName());
// 获取包名
System.out.println("包名: " + clazz.getPackage().getName());
// 判断是否为接口
System.out.println("是否为接口: " + clazz.isInterface());
// 判断是否为枚举
System.out.println("是否为枚举: " + clazz.isEnum());
// 获取父类
System.out.println("父类: " + clazz.getSuperclass().getName());
假设有一个Student
类,输出结果可能是:
完整类名: com.example.Student
简单类名: Student
包名: com.example
是否为接口: false
是否为枚举: false
父类: java.lang.Object
获取构造方法
Class<?> clazz = Student.class;
Constructor<?>[] constructors = clazz.getConstructors();
System.out.println("Student类的公有构造方法:");
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
// 获取指定参数类型的构造方法
try {
Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
System.out.println("获取到的构造方法: " + constructor);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
获取成员变量
Class<?> clazz = Student.class;
// 获取所有公有字段
Field[] publicFields = clazz.getFields();
System.out.println("公有字段个数: " + publicFields.length);
// 获取所有字段(包括私有、保护、默认和公有)
Field[] allFields = clazz.getDeclaredFields();
System.out.println("所有字段个数: " + allFields.length);
for (Field field : allFields) {
System.out.println("字段名: " + field.getName() + ", 类型: " + field.getType().getSimpleName());
}
获取成员方法
Class<?> clazz = Student.class;
// 获取所有公有方法(包括从父类继承的方法)
Method[] publicMethods = clazz.getMethods();
System.out.println("公有方法个数: " + publicMethods.length);
// 获取本类声明的所有方法(不包括继承的方法)
Method[] declaredMethods = clazz.getDeclaredMethods();
System.out.println("本类声明的方法个数: " + declaredMethods.length);
for (Method method : declaredMethods) {
System.out.println("方法名: " + method.getName() +
", 返回类型: " + method.getReturnType().getSimpleName());
}
使用Class类创建对象
通过Class
类,我们可以动态创建类的实例:
try {
Class<?> clazz = Class.forName("com.example.Student");
// 使用无参构造方法创建对象
Object obj1 = clazz.newInstance(); // 已过时
// 推荐的方式:
Object obj2 = clazz.getDeclaredConstructor().newInstance();
// 使用带参构造方法创建对象
Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
Object obj3 = constructor.newInstance("张三", 20);
System.out.println(obj3);
} catch (Exception e) {
e.printStackTrace();
}
警告
Class.newInstance()
方法在Java 9中已被标记为过时,建议使用getDeclaredConstructor().newInstance()
代替。
Class类在泛型中的应用
在Java泛型编程中,Class
类经常用作类型令牌(Type Token):
public class GenericFactory<T> {
private Class<T> type;
public GenericFactory(Class<T> type) {
this.type = type;
}
public T create() throws Exception {
return type.getDeclaredConstructor().newInstance();
}
}
// 使用示例
GenericFactory<String> factory = new GenericFactory<>(String.class);
String str = factory.create();