反射
- 在运行时动态的获取类的完整信息
- 增加程序的灵活性
- JDK 动态代理使用了反射
概述
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.
- 对类,可以获取其所有的属性和方法
- 对对象,可以调用其任意方法和属性
- 获取的过程是借用class对象来实现的
- 每个类都有一个class文件(字节码)
- 加载的时候,会将class文件转换为class对象
基础使用
获取class对象的三种方式
三种方式常用第三种,第一种对象都有了还要反射干什么。第二种需要导入类的包,依赖太强,不导包就抛编译错误。一般都第三种,一个字符串可以传入也可写在配置文件中等多种方法。
- 通过
getClass()
方法
Person p1=new Person();
Class c1=p1.getClass();
- 通过类名的属性
.class
来获取(任何数据类型都有这个静态属性,包括基本类型数据属性),安全可靠,性能更高
Class c1=Person.class
- 通过Class类的
forName()
静态方法来获取,使用最多
Class c1=Class.forName("com.xxx.Person")
一个类在 JVM 中只会有一个 Class 实例,即我们对上面获取的 class对象进行 equals 比较,发现都是true
class类常用方法
declared:通常是指类声明的,所以不包含继承
直接去获取类的某项属性的话,只能访问到为public修饰的属性,包含继承的
-
getName()
获取类完整的名字String className = c1.getName(); System.out.println(className);//输出com.xx.Person
-
getFields()
获取类的public属性(包括继承的一些public修饰的属性)Field[] fields=c1.getFields();//这里的field是字段的意思 for(Field field:fields){ System.out.println(field.getName());//只有public修饰的属性,包括继承的一些public修饰的属性 }
-
getDeclaredFields()
获取类的 声明的所有属性(不包含继承)Field[] fields=c1.getDeclaredFields(); for(Field field:fields){ System.out.println(field.getName());//所有类声明的属性 }
-
getMethods()
获取类的public方法(包括继承的一些public修饰的方法)Method[] methods=c1.getMethods(); for (Method method : methods) { System.out.println(method.getName());//包含类的所有的public方法,包括继承的一些方法,(不会包括类的构造方法) }
-
getDeclaredMethods()
获取类的声明的所有方法(不包含构造方法,不包含继承)Method[] methods=c1.getDeclaredMethods(); for (Method method : methods) { System.out.println(method.getName()); }
-
getConstructors()
获取类的public的构造方法(不包含继承来的)Constructor [] constructors=c1.getConstructors(); for (Constructor constructor : constructors) { System.out.println(constructor.toString()); }
-
getDeclaredConstructors()
获取类声明的所有构造方法Constructor [] constructors=c1.getDeclaredConstructors(); for (Constructor constructor : constructors) { System.out.println(constructor.toString()); }
-
getConstructor()
获取指定参数类型的构造方法Constructor constructor=c1.getConstructor(String.class);
-
getField(String name)
获得指定类的public属性,只能获取由public修饰的属性,包括继承来的Field field=c1.getField("xx"); System.out.println(field);
-
getDeclaredField(String name)
获取指定类声明的的属性,不包括继承来的Field field=c1.getDeclaredField("f"); System.out.println(field);
-
反射中的另外一个常用方法
setAccessible()
设置是否打开java 的语言访问检查-
Method
、Field
、Constructor
类型的方法 - true表示关闭语言访问检查,可以提高反射的性能
- 调用私有方法或者获取私有属性需要关掉检查
Method m = c1.getDeclaredMethod("getUname", null); m.setAccessible(true);
-
Field
字段的使用
set(obj,value)
设置对象对应字段的值
Field field=c1.getField("a");
// 如果为私有属性,需要关掉检查来进行改变
field.set(o,6);// 设置o对象a的值为6
Constructor
构造器的使用
newInstance()
生成新实例
Constructor constructor=c1.getDeclaredConstructor(int.class,int.class);
//如果是私有的构造方法时关掉检查即可
//constructor.setAccessible(true);//关掉检查
Object o =constructor.newInstance(2,3);
Method
方法的使用
invoke(Object obj, Object... args)
调用方法
Method method=c1.getMethod("sayHello");
//如果是私有的方法时关掉检查即可
method.invoke(o,null);// 无参为null
应用
https://blog.csdn.net/sinat_38259539/article/details/71799078
网友评论