反射
1、什么是反射机制
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制(注意关键词:运行状态)换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods
2、java Reflection API简介
Class类:代表一个类,位于java.lang包下
Field类:代表类的成员变量(成员变量也称为类的属性)
Method类:代表类的方法
Constructor类:代表类的构造方法
Array类:提供了动态创建数组,以及访问数组的元素的静态方法
3、Class类对象
3.1、java中的Class对象三种获取方式
利用对象调用getClass()方法获取该对象的Class实例;
使用Class类的静态方法forName(),用类的名字获取一个Class实例 ;
运用.class的方式来获取Class实例,对于基本数据类型的封装类,还可以采用.TYPE来获取相对应的基本数据类型的Class实例;
3.2、Class类的方法
getClassLoader() 获取加载这个类的类加载器
getSuperclass() 获取这个类的父类
getInterfaces() 获取这个类实现的所有接口
newInstance() 返回此Class所表示的类,通过调用默认的(即无参数)构造函数创建的一个新实例,在JDK1.9中已经被废弃,不建议再使用
3.2.1、获取类中的构造器
getConstructor(Class...<?> parameterTypes) 获得该类中与参数类型匹配的公有构造方法
getConstructors() 获得该类的所有公有构造方法
getDeclaredConstructor(Class...<?> parameterTypes) 获得该类中与参数类型匹配的构造方法(public+private),可以破坏单例模式,获取到私有构造方法
getDeclaredConstructors() 获得该类所有构造方法(public+private)
3.2.2、获取类中的属性
getField(String name) 获得某个公有的属性对象
getFields() 获得所有公有的属性对象
getDeclaredField(String name) 获得某个属性对象(public+private)
getDeclaredFields() 获得所有属性对象(public+private)
3.2.3、获取类中的方法
getMethod(String name, Class...<?> parameterTypes) 获得该类某个公有的方法
getMethods() 获得该类所有公有的方法
getDeclaredMethod(String name, Class...<?> parameterTypes) 获得该类某个方法(public+private)
getDeclaredMethods() 获得该类所有方法(public+private)
3.2.4、获取类中的注解
getAnnotation(Class<A> annotationClass) 返回该类中与参数类型匹配的公有注解对象
getAnnotations() 返回该类所有的公有注解对象
getDeclaredAnnotation(Class<A> annotationClass) 返回该类中与参数类型匹配的所有注解对象(public+private)
getDeclaredAnnotations() 返回该类所有的注解对象(public+private)
3.2.5、其他方法
isAnnotation() 如果是注解类型则返回true
isAnnotationPresent(Class<? extends Annotation> annotationClass) 如果是指定类型注解类型则返回true
isAnonymousClass() 如果是匿名类则返回true
isArray() 如果是一个数组类则返回true
isEnum() 如果是枚举类则返回true
isInstance(Object obj) 如果obj是该类的实例则返回true
isInterface() 如果是接口类则返回true
isLocalClass() 如果是局部类则返回true
isMemberClass() 如果是内部类则返回true
4、Constructor类对象
newInstance(Object... initargs) 根据传递的参数创建类的对象,适用于有参构造方法,并且还可以破坏单例模式,调用私有构造方法;
getParameterTypes() 获取方法的传入参数类型
getModifiers() 可以得到构造方法的类型,返回参数为int,需要做转换 Modifier.toString(c.getModifiers())
setAccessible(Boolean boolean) 参数值为true,取消禁用访问控制检查,为false则 相反,private的构造器需要先取消禁用访问
5、Method 类的方法
getReturnType() 获取方法的返回类型
getParameterTypes() 获取方法的传入参数类型
invoke(Object obj, Object... args) 传递object对象及参数 调用该对象对应的方法
setAccessible(Boolean boolean) 参数值为true,取消禁用访问控制检查,为false则相反,private的方法需要先取消禁用访问
6、Filed类对象
equals(Object obj) 属性与obj相等则返回true
get(Object obj) 获得obj中对应的属性值
set(Object obj, Object value) 设置obj中对应属性值,被final关键字修饰的Field字段是安全的,在运行时可以接收任何修改,但最终其实际值是不会发生改变的
setAccessible(Boolean boolean) 参数值为true,取消禁用访问控制检查,为false则相反,private的属性需要先取消禁用访问
被反射的类
package reflect; public class Book { private int page; public String name; public Book(){} public Book(String name){ this.name=name; } private Book(String name,int page){ this.name=name; this.page=page; } public String toString(){ return String.format("book.name=%s,book.page=%d",name,page); } private void print(){ System.out.println("这是私有方法"); } public int getPage() { return page; } public void setPage(int page) { this.page = page; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
测试反射的类
package reflect; import org.testng.annotations.Test; import java.lang.reflect.*; public class ReflectTest { //获取 Class 对象 @Test public void getClazz(){ //方式 1 Book book=new Book(); Class<?> clz1=book.getClass(); //方式 2 Class<?> clz2=Book.class; //方式 3 try { Class<?> clz3=Class.forName("reflect.Book"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } //获取 类的构造器 @Test public void getConstruct(){ Class<?> clz=Book.class; //获取 所有构造器 Constructor<?>[] constructor1=clz.getDeclaredConstructors(); for(Constructor<?> c:constructor1){ //获取 所有构造器的修饰符 System.out.println("修饰符:"+Modifier.toString(c.getModifiers())); } //获取 私有构造器 Constructor<?> constructor2=null; try { constructor2=clz.getDeclaredConstructor(String.class,int.class); for(Class<?> clz2:constructor2.getParameterTypes()){ //获取私有构造器的修饰符 和 参数类型 System.out.println("修饰符:"+Modifier.toString(constructor2.getModifiers())+",参数:"+clz2); } } catch (NoSuchMethodException e) { e.printStackTrace(); } //使用私有构造器新建对象 try { //取消禁用权限 constructor2.setAccessible(true); Book book= (Book) constructor2.newInstance("小说",100); System.out.println(book.toString()); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } //获取类的方法 @Test public void getMethod(){ Class<?> clz=Book.class; Book book =new Book(); //获取所有方法 Method[] allMethod=clz.getDeclaredMethods(); for(Method m:allMethod){ System.out.println("方法名:"+m.getName()+",返回类型:"+m.getReturnType()+",修饰符:"+Modifier.toString(m.getModifiers())); } //获取私有方法 try { Method method1=clz.getDeclaredMethod("print"); System.out.println(Modifier.toString(method1.getModifiers())); //取消禁用权限 method1.setAccessible(true); //使用这个方法 System.out.println((method1.invoke(book))); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } //获取公有方法,并执行这些方法 try { clz.getDeclaredMethod("setName",String.class).invoke(book,"小说"); clz.getDeclaredMethod("setPage", int.class).invoke(book,100); String str= (String) clz.getDeclaredMethod("toString").invoke(book); System.out.println(str); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } } //获取类的属性 @Test public void getField(){ Book book=new Book(); Class<?> clz=book.getClass(); //获取类的所有属性 Field[] fields=clz.getDeclaredFields(); for(Field f:fields){ System.out.println(Modifier.toString(f.getModifiers())); } //获取公有属性并设置值 try { Field field1=clz.getDeclaredField("name"); field1.set(book,"小说"); System.out.println(field1.get(book)); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } //获取私有属性并设置值 try { Field field2=clz.getDeclaredField("page"); field2.setAccessible(true); field2.set(book,100); System.out.println(field2.get(book)); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } //打印上面的属性值 try { String str= (String) clz.getMethod("toString").invoke(book); System.out.println(str); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } } }