java反射特性学习
反射
1 反射和Class类
反射是什么
反射是通过对象获得一个类的Class对象。
Class对象是类加载时完成后,堆内存的方法区里字节码
的程序表现。
Class对象能够完整包含一个类的结构,包括所有的域,方法。
- 优点:
可以实现动态创建对象和编译,体现出很大的灵活性. - 缺点:
对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,
我们希望做什么并且它满足我们的要求。这类操作总是慢于直接执行相同的操作。
反射相关主要API
java.lang.Class :代表一个类
java.lang.reflect.Method:代表类的方法
java.lang.reflect.Field:代表类的成员变量
java.lang.reflect.Constructor:代表类的构造器
反射的几种获得方法:
- 若已知具体的类,通过类的class属性获取,该方法最为安全可靠,程序性能最高。
- 已知某个类的实例,调用该实例的getClass()方法获取Class对象
- 已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName()获取,可能抛出ClassNotFoundException
- 基本数据类型的包装类.Type和.class的不同
// Class.forName("类路径")方法,此方法Class的泛型不能固定,常写为通配符<?>
Class<?> c1 = Class.forName("com.reflection.test.ReflectionTest");
// 获得包名+类名
System.out.println(c1.getName());
// 获得类名
System.out.println(c1.getSimpleName());
// getClass()方法:
ReflectionTest reflectionTest = new ReflectionTest();
Class<? extends ReflectionTest> c2 = reflectionTest.getClass();
// 类名.class方法:
Class<ReflectionTest> c3 = ReflectionTest.class;
// 基本数据类型的包装类.Type, 比较以下的不同
Class<Integer> integerClass1 = Integer.class; //返回本类型
Class<Integer> integerClass2 = Integer.TYPE; //返回包装的类型
System.out.println("======================");
System.out.println(integerClass1);
System.out.println(integerClass2);
// 一个类只能获得一个Class对象:
System.out.println("======================");
System.out.println(c1 == c2);
System.out.println(c2 == c3);
哪些类型可以有Class 对象?
- class:外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类。
- interface:接口
- [] :数组
- enum:枚举
- annotation:注解 @interface
- primitive type :基本数据类型
- void
// 类:
Class<Object> objectClass = Object.class;
System.out.println(objectClass);
// 接口:
Class<?> comparableClass = Comparable.class;
System.out.println(comparableClass);
// 数组:
Class<String[]> aClass = String[].class;
System.out.println(aClass);
// 二维数组:
Class<String[][]> aClass1 = String[][].class;
System.out.println(aClass1);
// 枚举:
Class<ElementType> elementTypeClass = ElementType.class;
System.out.println(elementTypeClass);
// 注解:
Class<MyAnnotation> myAnnotationClass = MyAnnotation.class;
System.out.println(myAnnotationClass);
// 基本数据类型:
Class<Integer> integerClass = int.class;
System.out.println(integerClass);
// void:
Class<Void> voidClass = void.class;
System.out.println(voidClass);
2 通过反射获得类的所有结构
通过反射获得类的以下结构
Field、Method、Constructor、Superclass、Interface、Annotation
- 实现的全部接口
- 所继承的父类
- 全部的构造器,包括参数
- 全部的方法,包括返回值、参数、泛型
- 全部的Field
- 注解,包括注解内的值
StudentTest studentTest = new StudentTest();
Class<? extends StudentTest> c1 = studentTest.getClass();
// 获得父类
Class<?> superclass = c1.getSuperclass();
System.out.println("========================");
System.out.println("SuperClass:" + superclass.getSimpleName());
// 获得全部的构造器
Constructor<?>[] constructors = c1.getDeclaredConstructors();
System.out.println("========================");
System.out.println("Constructor:");
for (Constructor<?> constructor : constructors) {
System.out.println(constructor.getName() + ":");
System.out.println(Arrays.toString(constructor.getParameterTypes()));
}
// 获得全部的方法
Method[] methods = c1.getDeclaredMethods();
System.out.println("========================");
System.out.println("Methods:");
for (Method method : methods) {
System.out.println(method.getName() + ":");
System.out.println(Arrays.toString(method.getParameterTypes()));
}
// 获得全部的field
// 定义的所有方法
Field[] declaredFields = c1.getDeclaredFields();
System.out.println("========================");
System.out.println("DeclareFields:");
for (Field field : declaredFields) {
System.out.println(field.getName());
}
// 所有能找到的public方法和父类的方法
Field[] fields = c1.getFields();
System.out.println("========================");
System.out.println("PublicFields+superFields:");
for (Field field : fields) {
System.out.println(field.getName());
}
反射获取注解,ORM练习
Object Relationship Mapping对象关系映射
该性质是数据库建立的基础
- 类和表结构对应
- 属性和字段对应
- 对象和记录对应
Class<?> classPerson = Class.forName("com.reflection.test.PersonTest");
System.out.println("========================");
// 获得类的注解
Annotation[] annotations = classPerson.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println("ClassAnnotation:" + annotation);
System.out.println("注解名:" + annotation.annotationType().getSimpleName());
}
// 获得注解的值
MyTable annotation = classPerson.getAnnotation(MyTable.class); //填写需要的注解的类
String value = annotation.value();
System.out.println("MyTable注解的值:" + value);
// 获得类中域的注解
// 获得所有域
System.out.println("========================");
System.out.println("获得所有域的注解、和值:");
Field[] classPersonDeclaredFields = classPerson.getDeclaredFields();
for (Field classPersonDeclaredField : classPersonDeclaredFields) {
// 取出每个域的注解
MyField ann = classPersonDeclaredField.getAnnotation(MyField.class);
// 取出注解的值
String columnName = ann.columnName();
String type = ann.type();
int length = ann.length();
boolean isNull = ann.isNull();
System.out.println(classPersonDeclaredField.getName() + ":\n"
+ " columnName:" + columnName
+ " type:" + type
+ " length:" + length
+ " isNull" + isNull);
}
}
}
3 使用Class对象创建新实例
使用Class对象创建新实例
- 通过Class类的getDeclaredConstructor(Class … parameterTypes)取得本类的指定形参类型的构造器
- 向构造器的形参中传递Class对象,里面包含了构造器中所需的各个参数
- 通过Constructor实例化对象
public class GetNewInstance03 {
public static void main(String[] args)
throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
Class<?> c1 = Class.forName("com.reflection.test.PersonTest");
// 获得指定参数的构造器
Constructor<?> personConstructor = c1.getDeclaredConstructor(int.class, String.class, String.class);
// 已知类名,强转(从Object->PersonTest)高转低,用constructor.newInstance(构造参数)获得新的对象
PersonTest person = (PersonTest) personConstructor.newInstance(15, "tsh", "student");
System.out.println(person);
通过反射调用方法、修改私有属性
// 通过反射调用方法、修改私有属性
Method setName = c1.getDeclaredMethod("setName", String.class);
// 方法调用, methodName.invoke(对象, 参数列表)
setName.invoke(person, "tsh_test");
System.out.println(person);
// 设置setAccessible(true);可以访问私用方法、属性。
// 并且效率更高。
System.out.println("=============================");
Field age = c1.getDeclaredField("age");
// 设置可访问private
age.setAccessible(true);
age.set(person, 50);
System.out.println(person);
}
}

浙公网安备 33010602011771号