文章目录
版本约定
本篇基于java17版本写的
api一览
1. 获取类信息的方法
这些方法用于获取类本身的信息,例如类名、修饰符、包等。
getName():返回类的全限定名(包括包名)。
• getSimpleName():返回类的简单名称(不包括包名)。
• getCanonicalName():返回类的规范名称,如果类没有规范名称则返回 null。
• getModifiers():返回类的修饰符(如 public、private、abstract 等),以 int 值表示。
• getPackage():返回该类所属的包。
• getSuperclass():返回该类的直接父类的 Class 对象。
• getInterfaces():返回该类实现的所有接口的 Class 数组。
• isInterface():判断该 Class 对象是否表示一个接口。
• isEnum():判断该 Class 对象是否表示一个枚举类型。
• isAnnotation():判断该 Class 对象是否表示一个注解类型。
• isArray():判断该 Class 对象是否表示一个数组类型。
• isPrimitive():判断该 Class 对象是否表示一个基本类型(如 int、boolean 等)。
2. 获取类成员(字段、方法、构造函数)的方法
这些方法用于获取类中的字段、方法、构造函数等成员信息。
• getFields():返回所有 public 字段(包括父类继承的)。
• getDeclaredFields():返回所有字段(仅包括本类声明的,且不论访问修饰符)。
• getField(String name):返回指定名称的 public 字段。
• getDeclaredField(String name):返回指定名称的字段(不论修饰符)。
• getMethods():返回所有 public 方法(包括继承的)。
• getDeclaredMethods():返回所有声明的方法(包括 private 和 protected,但不包括父类的方法)。
• getMethod(String name, Class<?>… parameterTypes):返回指定名称和参数类型的 public 方法。
• getDeclaredMethod(String name, Class<?>… parameterTypes):返回指定名称和参数类型的方法(不论修饰符)。
• getConstructors():返回所有 public 构造函数。
• getDeclaredConstructors():返回所有声明的构造函数(包括 private 构造函数)。
• getConstructor(Class<?>… parameterTypes):返回指定参数类型的 public 构造函数。
• getDeclaredConstructor(Class<?>… parameterTypes):返回指定参数类型的构造函数(不论修饰符)。
3. 操作类成员的方法
这些方法用于通过反射调用类中的字段、方法、构造函数等。
• getField(String name) 和 getDeclaredField(String name) 返回的 Field 对象可以用于读取或修改字段的值。
- Field.get(Object obj):获取对象的字段值。
- Field.set(Object obj, Object value):设置对象的字段值。
• getMethod(String name, Class<?>… parameterTypes) 和 getDeclaredMethod(String name, Class<?>… parameterTypes) 返回的 Method 对象可以用于调用方法。
- Method.invoke(Object obj, Object… args):调用对象的方法。
• getConstructor(Class<?>… parameterTypes) 和 getDeclaredConstructor(Class<?>… parameterTypes) 返回的 Constructor 对象可以用于创建对象。
- Constructor.newInstance(Object… initargs):通过构造函数创建对象。
4. 类型检查和类型转换的方法
这些方法用于检查类的类型、类之间的继承关系,以及进行安全的类型转换。
• isInstance(Object obj):判断某个对象是否是该类的实例,等同于 instanceof 操作符。
• isAssignableFrom(Class<?> cls):判断该类是否是指定类的父类或接口,等同于 cls instanceof Class<?> 的形式。
• cast(Object obj):将指定对象转换为该类的类型,等同于强制类型转换 (ClassType) obj。
• asSubclass(Class<U> clazz):将当前 Class 对象表示的类转换为指定的子类。
5. 数组相关的方法
这些方法用于操作数组类型的类。
• getComponentType():如果当前 Class 对象表示一个数组,则返回数组元素的类型。
• arrayType():用于表示数组类型的 Class 对象。
6. 注解相关的方法
这些方法用于获取类上的注解信息。
• getAnnotations():返回该类上的所有注解。
• getDeclaredAnnotations():返回该类上声明的注解(不包括父类中的注解)。
• getAnnotation(Class<T> annotationClass):返回指定类型的注解。
• isAnnotationPresent(Class<? extends Annotation> annotationClass):判断该类是否带有指定的注解。
7. 类加载和反射相关的辅助方法
这些方法用于辅助类的加载、反射操作或判断。
• forName(String className):返回指定类名的 Class 对象。
• getClassLoader():返回加载当前类的类加载器。
• desiredAssertionStatus():返回类的断言状态。
• getProtectionDomain():返回类的保护域,主要用于安全管理。
方法 | 返回值类型 | 适用场景 |
---|---|---|
getCanonicalName() | 规范名称(带包名和点号的嵌套类名) | 获取类的规范名,适用于非匿名类、局部类的场景 |
getSimpleName() | 简单名称(类名,不带包名) | 获取类的短名称,适用于显示、日志等场景 |
getName() | 全限定名称(包名+类名,用 $$ 表示内部类) | 获取类的内部名称,适用于反射、序列化等需要全名的场景,包含匿名类和局部类名 |
getTypeName() | 类型名称(更人性化的名称) | 获取类的类型名称,对数组、泛型类型友好,适合显示和日志用途 |
api测试
定义几个类来辅助测试
public interface InterfaceClass<T> {
}
public class Level0Class<T> implements InterfaceClass<T> {
}
public class Level1Class<T> extends Level0Class<List<T>> implements InterfaceClass<List<T>> {
public Object c;
public Level1Class() {
// 本地类
class ClassA {
}
c = new ClassA();
}
public Object getC() {
return c;
}
public Object classAObject() {
class ClassA {
}
return new ClassA();
}
public static class InnerClass{}
}
public class OuterClass {
// 公共成员类
public class PublicInnerClass {}
// 私有成员类
private class PrivateInnerClass {}
// 公共静态嵌套类
public static class PublicStaticNestedClass {}
// 私有静态嵌套类
private static class PrivateStaticNestedClass {}
// 公共接口
public interface PublicInterface {}
// 私有接口
private interface PrivateInterface {}
}
isA的判断
@Test
void isATest() {
Class<String> stringClass = String.class;
String str = "Hello";
// A.isInstance(B) 判断B是否为A的实例
System.out.println(stringClass.isInstance(str)); // true
// System.out.println(String.class.isInstance(str)); // true
Class<Number> numberClass = Number.class;
Class<Integer> integerClass = Integer.class;
// A.isAssignableFrom(B) 判断B是否的实例是否为赋值给A; 也就是 ? extends A B就是这个?
System.out.println(numberClass.isAssignableFrom(integerClass)); // true
// 判断A是否为B的实例
System.out.println(str instanceof String); // true
}
isSynthetic判断动态类
/**
* 判断一个类是否为动态生成的类
*/
@Test
void isSyntheticTest() {
Runnable r = () -> System.out.println("hello");
System.out.println("是否为编译器自动生成的类:" + r.getClass().isSynthetic()); // true
System.out.println("是否为编译器自动生成的类:" + TempClass.class.isSynthetic()); // false
Function<String, String> func = String::valueOf;
System.out.println("是否为编译器自动生成的类:" + func.getClass().isSynthetic()); // true
Consumer<String> aa = this::say;
System.out.println("是否为编译器自动生成的类:" + aa.getClass().isSynthetic()); // true
}
private void say(String a) {
}
获取泛型类型
/**
* 获取类声明中定义的泛型类型参数
*/
@Test
void getTypeParametersTest() {
// 获取类声明中定义的泛型类型参数
TypeVariable<Class<Level1Class>>[] typeParameters = Level1Class.class.getTypeParameters();
System.out.println(typeParameters[0].getName()); // T
// getGenericDeclaration: 获取类型变量声明的位置; 例如Level1Class<T>中T声明在Level1Class中, 它可以是 Class、Method 或 Constructor,用于获取声明泛型的上下文
System.out.println(typeParameters[0].getGenericDeclaration().getSimpleName()); // Level1Class
System.out.println(typeParameters[0].getTypeName()); // T
}
获取直接继承的泛型父类
/**
* 返回当前类的直接父类的泛型类型; 注意: 是直接父类
*/
@Test
void getGenericSuperclassTest() {
// per.qiao.myutils.clazz.Level0Class<java.util.List<T>>
System.out.println(Level1Class.class.getGenericSuperclass());
// per.qiao.myutils.clazz.Level0Class<java.util.List<T>>
System.out.println(Level1Class.class.getGenericSuperclass().getTypeName());
// class sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
System.out.println(Level1Class.class.getGenericSuperclass().getClass());
}
方法中的本地类
/**
* 返回类所在的直接方法;(类是在哪个方法中定义的)
*/
@Test
void getEnclosingMethodTest() {
Class c = (new Level1Class()).classAObject().getClass();
// public java.lang.Object per.qiao.myutils.clazz.Level1Class.classAObject()
System.out.println(c.getEnclosingMethod());
// class per.qiao.myutils.clazz.Level1Class
System.out.println("宿主:" + c.getNestHost());
Class c1 = new Level1Class().getC().getClass();
System.out.println(c1.getEnclosingMethod()); // null
}
构造器中的本地类
/**
* 返回类所在的直接构造器;(类是在哪个构造器中定义的)
*/
@Test
void getEnclosingConstructorTest() {
Class c = new Level1Class().getC().getClass();
// 宿主:class per.qiao.myutils.clazz.Level1Class
System.out.println("宿主:" + c.getNestHost());
// public per.qiao.myutils.clazz.Level1Class()
System.out.println(c.getEnclosingConstructor());
}
内部类判断
/**
* 返回当前类是哪个类的内部类(即嵌套类)的情况。如果当前类是某个类的内部类,getDeclaringClass() 方法将返回该外部类的 Class 对象;如果当前类不是内部类,则返回 null。
* 注意: 不包括匿名类和局部类;
*/
@Test
void getDeclaringClassTest() {
Class<?> declaringClass = Level1Class.InnerClass.class.getDeclaringClass();
System.out.println("InnerClass定义所在类为:" + declaringClass);//class per.qiao.myutils.clazz.Level1Class
// class per.qiao.myutils.clazz.Level1Class
System.out.println("宿主:" + declaringClass.getNestHost());
System.out.println(declaringClass.getEnclosingClass()); // null
}
/**
* 返回当前类是哪个类的内部类-包括匿名类和局部类;
*/
@Test
void getEnclosingClassTest() {
// class per.qiao.myutils.clazz.Level1Class
System.out.println(Level1Class.InnerClass.class.getEnclosingClass());
Class c = (new Level1Class()).classAObject().getClass();
// class per.qiao.myutils.clazz.Level1Class
System.out.println(c.getEnclosingClass());
}
类名称
/**
* getName, getCanonicalName, getSimpleName, getTypeName
*/
@Test
void nameTest() {
int[] arr = {0};
// 返回类的完全限定名,如果类是匿名类或局部类,或者类没有规范名称,则返回 null。;
// per.qiao.myutils.clazz.Level1Class
System.out.println(Level1Class.class.getCanonicalName());
// 局部类
Class c = (new Level1Class()).classAObject().getClass();
System.out.println(c.getCanonicalName()); // null
System.out.println(arr.getClass().getCanonicalName()); // int[]
// Level1Class
System.out.println(Level1Class.class.getSimpleName());
System.out.println(arr.getClass().getSimpleName()); // int[]
// 返回类的完全限定名;
// per.qiao.myutils.clazz.Level1Class
System.out.println(Level1Class.class.getName());
// 对于匿名类或局部类,也能返回类的名称。
System.out.println(c.getName()); // per.qiao.myutils.clazz.Level1Class$1
// 对于数组类型,返回的是内部表示法,如[Ljava.lang.String、[I
System.out.println(arr.getClass().getName()); // [I
// per.qiao.myutils.clazz.Level1Class
System.out.println(Level1Class.class.getTypeName());
// per.qiao.myutils.clazz.Level0Class<java.util.List<T>>
System.out.println(Level1Class.class.getGenericSuperclass().getTypeName());
System.out.println(arr.getClass().getTypeName()); // int[]
}
匿名类判断
/**
* 判断是否为匿名类
*/
@Test
void isAnonymousClassTest() {
// 方法内部类
Class c = (new Level1Class()).classAObject().getClass();
System.out.println(c.isAnonymousClass()); // false
Runnable r = new Runnable() {
@Override
public void run() {}
};
System.out.println(r.getClass().isAnonymousClass()); // true
}
这里注意runable简写后就不是普通的匿名类了
判断本地类
/**
* isLocalClass() 是 Class 类中的一个方法,用于判断当前类是否是一个本地类(local class)。
* 本地类是在某个方法、构造函数或者初始化块中定义的类。
*/
@Test
void isLocalClassTest() {
Class c = (new Level1Class()).classAObject().getClass();
System.out.println(c.isLocalClass()); // true
}
判断成员类
/**
* 判断是否为成员类; 静态类不是成员类; 本地类也不是成员类
*/
@Test
void isMemberClassTest() {
Class c = (new Level1Class()).classAObject().getClass();
System.out.println(c.isMemberClass()); // false
Class c1 = Level1Class.InnerClass.class;
System.out.println(c1.isMemberClass()); // true
}
获取成员类
/**
* 它返回一个数组,包含当前类和父类中声明的所有公共成员类、接口、枚举类的 Class 对象。
* 这个方法只返回公共的(public)嵌套类和接口,不包含非公共的成员类或本地类、匿名类。
*/
@Test
void getClassesTest() {
Class<OuterClass> outerClassClass = OuterClass.class;
Class<?>[] classes = outerClassClass.getClasses();
for (Class<?> aClass : classes) {
// interface per.qiao.myutils.clazz.OuterClass$PublicInterface
// class per.qiao.myutils.clazz.OuterClass$PublicStaticNestedClass
// class per.qiao.myutils.clazz.OuterClass$PublicInnerClass
System.out.println(aClass);
}
}
/**
* 返回当前类中声明的所有嵌套类、接口和枚举,包括私有、受保护、包级私有等非公共类
*/
@Test
void getDeclaredClassesTest() {
Class<?>[] declaredClasses = OuterClass.class.getDeclaredClasses();
for (Class<?> clazz : declaredClasses) {
System.out.println(clazz.getName());
}
}
cast
类型强转
/**
* 类型转换, 底层通过isInstance判断
*/
@Test
void castTest() {
Object obj = new Level1Class();
// isInstance
Level1Class cast = Level1Class.class.cast(obj);
System.out.println(cast);
}
asSubclass
class之间的转换
/**
* 子转父
*/
@Test
void asSubclassTest() {
boolean assignableFrom = Level0Class.class.isAssignableFrom(Level1Class.class);
System.out.println(assignableFrom);
Class<? extends Level0Class> subclass = Level1Class.class.asSubclass(Level0Class.class);
System.out.println(subclass);
}
获取宿主类
/**
* 用于获取当前类的嵌套类的宿主类(即它的外部类)。
* 这是与嵌套类(Nested Class)相关的一部分,特别是在处理内部类和静态嵌套类时。
*/
@Test
void getNestHostTest() {
// 获取内部类的宿主类 per.qiao.myutils.clazz.OuterClass
Class<?> innerClassHost = OuterClass.PublicInnerClass.class.getNestHost();
System.out.println("InnerClass host: " + innerClassHost.getName());
// 获取静态嵌套类的宿主类 per.qiao.myutils.clazz.OuterClass
Class<?> staticNestedClassHost = OuterClass.PublicStaticNestedClass.class.getNestHost();
System.out.println("StaticNestedClass host: " + staticNestedClassHost.getName());
// 获取外部类的宿主类; per.qiao.myutils.clazz.OuterClass
Class<?> outerClassHost = OuterClass.class.getNestHost();
System.out.println("OuterClass host: " + outerClassHost);
}
不同类判断同一宿主类
/**
* 用于判断当前类是否与指定类是嵌套类的同伴(Nest Mate)。
* 嵌套类同伴是指同一个外部类的嵌套类,它们可以访问彼此的私有成员。
*/
@Test
void isNestmateOfTest() {
Class<?> innerClass1 = OuterClass.PublicInnerClass.class;
Class<?> innerClass2 = OuterClass.PublicInterface.class;
Class<?> staticNestedClass = OuterClass.PublicStaticNestedClass.class;
// 检查两个内部类是否为同伴
boolean isNestmate1 = innerClass1.isNestmateOf(innerClass2);
boolean isNestmate2 = innerClass1.isNestmateOf(staticNestedClass);
System.out.println("InnerClass1 is nestmate of InnerClass2: " + isNestmate1); // true
System.out.println("InnerClass1 is nestmate of StaticNestedClass: " + isNestmate2); // true
}
查询嵌套类
/**
* 获取指定类的嵌套成员
*/
@Test
void getNestMembersTest() {
Class<?>[] nestMembers = OuterClass.class.getNestMembers();
for (Class<?> nestMember : nestMembers) {
System.out.println(nestMember.getName());
}
}
类描述
/**
* 获取类描述
*/
@Test
void descriptorStringTest() {
System.out.println(Level1Class.class.descriptorString());
}
获取数组类型
@Test
void arrayTypeTest() {
System.out.println(Level1Class.class.arrayType());
}
密封类
// 密封接口
public sealed interface SealedInterface permits NonSealedSubA {
}
// 定义非密封实现
public non-sealed class NonSealedSubA implements SealedInterface {
}
// 密封类
public sealed class SealedClass permits SealedSubClass, SealedSubClass2 {
}
// 密封类的普通实现, 需要用final标识
public final class SealedSubClass extends SealedClass {
}
// 密封类的非密封实现, 需要用non-sealed标识
public non-sealed class SealedSubClass2 extends SealedClass {
}
/**
* 获取密封类的所有允许的子类
*/
@Test
void getPermittedSubclassesTest() {
Class<?>[] permittedSubclasses = SealedClass.class.getPermittedSubclasses();
for (Class<?> permittedSubclass : permittedSubclasses) {
// per.qiao.myutils.clazz.sealed.SealedSubClass
// per.qiao.myutils.clazz.sealed.SealedSubClass2
System.out.println(permittedSubclass.getName());
}
Class<?>[] permittedSubclasses2 = SealedInterface.class.getPermittedSubclasses();
for (Class<?> permittedSubclass : permittedSubclasses2) {
// per.qiao.myutils.clazz.sealed.NonSealedSubA
System.out.println(permittedSubclass.getName());
}
}
/**
* isSealed判断一个类是不是密封类
*/
@Test
void isSealedTest() {
System.out.println(SealedClass.class.isSealed()); // true
System.out.println(SealedInterface.class.isSealed()); // true
System.out.println(SealedSubClass2.class.isSealed()); // false
System.out.println(NonSealedSubA.class.isSealed()); // false
}
个人公众号