定义:
- 在java反射过程中给定一个类对象(Class对象),通过反射可以获取该对象的所有成员结构和类结构。
- 给定一个对象,通过反射可以动态调用他的方法以及任意属性值得获取和赋值。静态成员变量和方法不需要给定对象。
- 这种动态获取类的内容、创建对象以及动态调用对象的方法及操作属性的机制称为反射。
优势:
- 增加程序的灵活性,避免将程序逻辑写死在代码里面。
- 代码简洁,可读性,提高代码复用率。
劣势:
- 比直接调用性能要低。
- 存在一些内部暴露和安全隐患。
与反射有关的主要的类:
- java.lang.Class //java的类字节码对象,java的每个类都有一个该对象。是对java类的描述。
- java.lang.reflect.Constructor。//java对类构造器的描述。
- java.lang.reflect.Method。 //对java方法的描述。
- java.lang.reflect.Field。 //对java成员的描述。
获取Class实例的4种方法:
- 已经知道具体的类:比如:String.class;
- 使用类的某个对象获取:object.getClass();
- 使用Class类的静态方法:Class.forName(“java.lang.String”);
该方法有重载:Class.forName(String name//类的全路径,boolean initialize//是否初始化,ClassLoader loader//类加载器)。 - 通过类加载器加载类:classLoad.loadClass(String name//类全路径);
Class类的方法:
//判断cls对象的类是不是clazz对象的类的子类,是就返回true,复制返回false。
boolean isAssignableFrom = clazz.isAssignableFrom(Class cls);
boolean isInstance = clazz.isInstance(Class cls) ;
//获取类的修饰符返回是一个int类型,具体每种修饰符的int值请查看java.lang.reflect.Modifier类。
//比如public是0x00000001 也就是1。static 是0x00000008 也就是8。
//组合就要相加 比如 public static 是9。
int Modifiers = clazz.getModifiers();
//判断该类是不是接口。
boolean isInterface = clazz.isInterface();
//判断是不是数组
boolean isArray = clazz.isArray();
//判断是不是八大基本类型的Class对象,比如int.class就为true,Integer.class就为false。
boolean isPrimitive = clazz.isPrimitive();
//获取他的父类的Class对象。接口类对象和八大基本类型类对象还有Object类对象调用返回null值。
Class superclass = clazz.getSuperclass();
//获取该类的全限定名称。
String name = clazz.getName();
//获取类或者父类上的指定注解,参数是指定获得注解的class类对象。如果不存在就返回null。
Annotation annotation = clazz.getAnnotation(Class clazz);
//获取该类上所有的注解。包括父类(父类的父类...以此类推)的注解(该注解要可以继承,也就是该注解要被@Inherited元注解修饰)
Annotation[] annotations = clazz.getAnnotations();
//获取该类上的指定注解,不包括父类。
Annotation annotation = clazz.getDeclaredAnnotation(Class clazz);
//获取该类上的所有注解,不包括父类。
Annotation[] annotations = clazz.getDeclaredAnnotations();
//获取全限定名称
String canonicalName = clazz.getCanonicalName();
//获取加载该类的类加载器。
ClassLoader classLoader = clazz.getClassLoader();
//获取这个类的公有的内部类,包括父类(父类的父类...以此类推)的公有内部类
Class[] clazzs = clazz.getClasses();
//获取该类所有的内部类,不包括父类。
Class[] clazzs = clazz.getDeclaredClasses();
//获取该类的指定公有构造器,根据参数列表指定。
Constructor constructor = clazz.getConstructor(Class[] clazzs//参数列表);
//获取该类所有公有构造器。因为构造器不能继承,所以获取不到父类的构造器。
Constructor[] constructors = clazz.getConstructors();
//获取该类的指定构造器,根据参数列表指定。
Constructor constructor = clazz.getDeclaredConstructor(Class[] clazzs//参数列表);
//获取该类的所有构造器
Constructor[] constructors = clazz.getDeclaredConstructors();
//获取该类的成员指定成员变量,参数是变量名。不包括父类。
Field field = clazz.getDeclaredField(String name);
//获取该类的所有成员变量。不包括父类
Field fields = clazz.getDeclaredFields();
//获取指定的公有成员变量,包括父类(父类的父类...以此类推)的。
Field field = clazz.getField(String name);
//获取该类所有的公有成员变量,包括父类(父类的父类...以此类推)的。
Field fields = clazz.getFields();
//获取该类的指定方法,name是方法名,clazzs是参数列表。不包括父类。
Method method = clazz.getDeclaredMethod(String name,Class[] clazzs);
//获取该类的所有方法,不包括父类。
Method[] methods = clazz.getDeclaredMethods();
//获取该类的指定公有方法,name是方法名,clazzs是参数列表。包括父类(父类的父类..,以此类推)。
Method method = clazz.getMethod(String name,Class[] clazzs);
//获取该类的所有公有方法,包括父类(父类的父类..,以此类推)。
Method[] methods = clazz.getMethods();
//获取该内部类的外部类,如果不是内部类,就返回null。
Class cla = clazz.getEnclosingClass();
//获取该枚举类的全部实例。如果不是枚举返回空数组。
Object[] enums = clazz.getEnumConstants();
//获取该类实现的所有接口。仅仅是该类。
Class[] interfaces = clazz.getInterfaces();
//获取定义改类的包。
Package package = clazz.getPackage();
//动态获取文件的全路径URL,这个要写一篇新的来讲。
URL url = clazz.getResource(String name);
//获取文件的全路径并生成输入流。
InputStream in = clazz.getResourceAsStream(String name);
//该类是不是注解
boolean isAnnotation = clazz.isAnnotation();
//该类上是否有注解clazz
boolean isAnnotationPresent= clazz.isAnnotationPresent(Class clazz);
//该类是不是枚举类
boolean isEnum= clazz.isEnum();
//创建对象 使用的是默认构造器创建。
Object obj = clazz.newInstance();
构造器类方法:
//获取该构造器的修饰符。
int Modifiers = constructor.getModifiers();
//获取该构造器的全限定名。
String name = constructor.getName();
//获取该构造器上指定的注解,因为构造器不能继承,所以不包括父类的。
Annotation annotation = constructor.getAnnotation(Class clazz);
//获取该构造器的所有注解,因为构造器不能继承,所以不包括父类的。
Annotation[] annotations = constructor.getDeclaredAnnotations();
//获取定义该构造器的类。
Class clazz = constructor.getDeclaringClass();
//获取该构造器的参数列表
Class[] clazz = constructor.getParameterTypes();
//创建对象。参数objs是要传到构造器的参数。
Object obj = constructor(Object[] objs);
//获取构造器的全名称,比如 public com.fanshe.demo.A(int,String)
String genericStringName = constructor.toGenericString();
//获取构造器的参数上的注解,这是一个二维数组,一维是参数,二维是参数上的注解。
Annotation[][] annotations = constructor.getParameterAnnotations();
//获取该构造器的参数个数。
int paramCount = constructor.getParameterCount();
//判断该构造器是否具有可变参数。
boolean isVarArgs = constructor.isVarArgs();
//获取该构造器抛出的异常。
Class[] exceptions = constructor.getExceptionTypes();
//获取该构造器上指定的注解。
Annotation[] annotation = constructor.getAnnotationsByType(Class clazz);
//获取该构造器上的所有注解,因为构造器不能继承,所有不包括父类。
Annotation[] annotations = constructor.getAnnotations();
//获取该构造器上指定注解。
Annotation annotation = constructor.getDeclaredAnnotation(Class clazz);
//获取该构造器上是否有指定注解
boolean isAnnotationPresent = constructor.isAnnotationPresent(Class clazz);
//判断该构造器是否关闭了安全访问检查,而不是是否可以访问。
//如果返回false则表示该构造器开启了安全访问检查,返回true则表示关闭了安全访问检查,
//关闭安全访问检查可以提高一定的反射效率。
boolean isAccessible = constructor.isAccessible();
//是否关闭安全访问检查,而不是设置是否可以访问,flag为true时就关闭安全访问检查,为false时就开启。默认开启。
constructor.setAccessible(boolean flag);
Field相关的方法:
//获取该成员变量的值,参数obj1是这个成员变量值所属的对象。
//如果该字段是静态成员变量,则obj1可以等于null。
Object obj = field.get(Object obj1)
//获取该成员变量的修饰符
int modifiers = field.getModifiers();
//获取成员变量的变量名称。
String name = field.getName();
//获取该成员变量上指定的注解。如果父类的成员变量被子类重写了,父类该成员变量上的注解不会继承到子类上。
Annotation annotation = field.getAnnotation(Class clazz);
//获取该成员变量上的所有注解。
Annotation[] annotations = field.getDeclaredAnnotations();
//获取该成员变量定义的类。
Class clazz = field.getDeclaringClass();
//获取该成员变量的详细名称:比如 public java.lang.String fanshe.entries.Person.email
String genericString = field.toGenericString();
//获取成员变量的类型。
Class clazz = field.getType();
//判断该成员变量是不是枚举类型。
boolean isEnumConstant = field.isEnumConstant();
//为该成员变量设置值,obj是成员变量所属的对象,value是要设置的值。
//如果该成员变量是静态变量,则obj可以为null。
field.set(Object obj,Object value);
//获取该成员变量上的所有注解。
Annotation[] annotation = field.getAnnotations();
//获取该成员变量上的指定注解
Annnotation annotation = field.getDeclaredAnnotation(Class clazz);
//判断该成员变量上是否存在注解annotationClass.
boolean isAnnotationPresent = field.isAnnotationPresent(Class annotationClass);
//判断该成员变量是否关闭了安全访问检查,而不是是否可以访问。
//如果返回false则表示该成员变量开启了安全访问检查,返回true则表示关闭了安全访问检查,
//关闭安全访问检查可以提高一定的反射效率。
boolean isAccessible = field.isAccessible();
//设置是否关闭安全检查,true就关闭,false就开启。
field.setAccessible(boolean flag);
Method相关方法:
//调用该方法,obj1是该方法的对象,如果是静态方法,则obj1可以为null,params是调用该方法的参数。
Object obj = method.invoke(Object obj1,Object[] params);
//获取该方法的修饰符。
int modifiers = method.getModifiers();
//获取该方法的名字,仅仅是名字,比如 getName。
String name = method.getName();
//获取该方法上的指定注解。方法上的注解不能在父子类之间继承。
Annotation annotation = method.getAnnotation(Class clazz);
//获取该方法上的所有注解
Annotation[] annotations = method.getDeclaredAnnotations();
//获取该方法定义的类。
Class clazz = method.getDeclaringClass();
//获取该方法的参数类型列表
Class[] clazzs = method.getParameterTypes();
//获取该方法的返回值类型。
Class clazz = method.getReturnType();
//判断该方法是不是被default修饰的方法,jdk1.8以后可以在接口中定义实现用default关键字修饰的方法。
boolean isDefault = method.isDefault();
//获取该方法的详细签名。比如:public void fanshe.entries.Teacher.sayHello(java.lang.String)
String genericString = method.toGenericString();
//获取该方法的参数上的注解,是一个二维数组,一维是参数,二维是参数上的注解。
Annotation[][] annotations = method.getParameterAnnotations();
//获取该方法的参数个数。
int paramCount = method.getParameterCount();
//判断该方式是否有可变参数。
boolean isVarArgs = method.isVarArgs();
//获取该方法抛出的异常类型列表,异常不会在父子类之间继承
Class[] clazzs = method.getExceptionTypes();
//获取该方法上的指定注解。
Annotation annotation = method.getDeclaredAnnotation(Class clazz);
//获取该方法上的所有注解
Annotation[] annotations = method.getAnnotations();
//判断该方法上是否存在注解annotationClass.
boolean isAnnotationPresent = method.isAnnotationPresent(Class annotationClass);
//判断该方法是否关闭了安全访问检查,而不是是否可以访问。
//如果返回false则表示该方法开启了安全访问检查,返回true则表示关闭了安全访问检查,
//关闭安全访问检查可以提高一定的反射效率。
boolean isAccessible = method.isAccessible();
//设置是否关闭安全检查,true就关闭,false就开启。
method.setAccessible(boolean flag);