一、反射技术
1、引入:
编译不知道类或对象的具体信息。==》使用反射来实现。
2、反射作用:
- 动态创建对象
- 动态操作属性
- 动态调用方法
- 动态操作泛型和注解
3、反射的入口
Class类是Java 反射机制的起源和入口。是所有类的图纸。
(1)获取一个类的类对象的方法:
- Class.forName("全路径名")
- 类名.class:不仅可以应用于普通的类、接口,还可以获取基本数据类型、数组的Class对象信息。
- 对象名.getClass
4、使用反射创建对象:Class clazz = Class.forName();
- 创建无参对象:clazz.newInstance();
- 创建无参对象:Constructor constructor = clazz.getDeclaredConstructor();
constructor.newInstance(); - 创建有参对象:Constructor constructor = clazz.getDeclaredConstructor(String.class,int.class);
//突破封装性的限制,即使是private、默认的也可以访问
constructor.setAccessible(true);
constructor.newInstance("小明",18);
二、反射技术
1、使用反射操作属性
- Field f1 = clazz.getField("name");
- f1.set(person,"小黑")
- f1.get(person)
- clazz.getDeclaredField("age")
2、使用反射执行方法
- Method m1 = clazz.getMethod("add",int.class,int.class);
- m1.invoke(person,10,20)
3、使用反射操作泛型
mport java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class GenericTest1 {
public static List<Integer> method(Map<Integer, Cat> map, ArrayList<Double> arr,String s) {
return new ArrayList<>();
}
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//创建类对象
/*Class<GenericTest1> clazz = GenericTest1.class;
//获取方法
Method method = clazz.getDeclaredMethod("method", Map.class, ArrayList.class,String.class);*/
//获取参数类型(带泛型)
/*Type[] types = method.getGenericParameterTypes();
for (Type type : types) {
System.out.println("type.getTypeName() = " + type.getTypeName());
if (type instanceof ParameterizedType){
ParameterizedType parameterizedType = (ParameterizedType)type;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println("actualTypeArgument = " + actualTypeArgument);
}
}
}*/
/*//获取返回值上的参数
Type genericReturnType = method.getGenericReturnType();
System.out.println("genericReturnType = " + genericReturnType);
ParameterizedType parameterizedType = (ParameterizedType)genericReturnType;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println("actualTypeArgument.getTypeName() = " + actualTypeArgument.getTypeName());
}*/
//操作泛型
ArrayList<String> arrayList = new ArrayList<>();
//获取类对象
Class<? extends ArrayList> clazz = arrayList.getClass();
//获取方法
Method add = clazz.getDeclaredMethod("add", Object.class);
add.invoke(arrayList, new Cat("小黑", "母", 3, "白色"));
add.invoke(arrayList, 10);
System.out.println("arrayList = " + arrayList);
}
}
三、注解
1、内置注解
- Override:方法重写
- Deprecated:标记过时的方法
- SuppressWarnings:禁止警告
2、元注解
- @Retention:用来约束注解的生命周期,分别有三个值,源码级别(source),类文件级别(class)或者运行时级别(runtime)。
- @Target:用来约束注解可以应用的地方。
- @Document:标记这些注解是否包含在用户文档中。
- @Inherited:指示注解类型被自动继承。
3、自定义注解
- 定义注解的关键字是@interface
- 自定义注解中可以定义多个配置参数,不是成员方法,不是成员变量;说明参数的名称,以及参数值的类型
- 如果只有一个配置参数,一般命名为value
- 如果配置参数是value,并且只有一个配置参数,value可以省略
4、使用反射读取注解
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Arrays;
public class Test {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
//创建类对象
Class<?> clazz = Class.forName("com.bjsxt.review2.Student");
//获取类上的注解
Annotation[] annotations = clazz.getAnnotations();
Table annotation = clazz.getAnnotation(Table.class);
System.out.println(annotation.annotationType() + annotation.value());
//获取属性
//获取属性上的注释
Field name = clazz.getDeclaredField("name");
Column annotation1 = name.getAnnotation(Column.class);
System.out.println("annotation1.type()+annotation1.name()+annotation1.decision()+annotation1.length() = "
+ annotation1.type() + annotation1.name() + annotation1.decision() + annotation1.length());
}
}