java反射
2019-03-06 本文已影响0人
0640fefbc8bf
Class的理解:
https://www.cnblogs.com/flyme/p/4571030.html
反射概念:
反射机制在【运行状态】中:
- 对于任意一个类,都能够知道这个类的属性和方法
- 对于任意一个对象,都能够调用他的方法与属性
反射提供的功能(具体能做什么事情):
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时判断任意一个类所具有的成员变量和方法
- 在运行时调用任意一个对象的方法
- 生成动态代理
declared:公然的,公开的
反射中基本类型(int,char)和包装类(Integer,Character)是不同的类型
第一步:获取反射对象(反射入口)
- 类型为Class
- 获取反射对象(反射入口)
1.Class.forname(全类名) (带异常处理 推荐使用)
// 1.Class.forName(全类名)
try {
Class<?> perclass = Class.forName("reflect.Person");
System.out.println(perclass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
2.类名.Class
Class<?> perclass2 = Person.class;
System.out.println(perclass2);
3.对象.getclass()
Person person = new Person();
Class<?> perclass3 = person.getClass();
System.out.println(perclass3);
- 注意凡是反射必须是Class
获取方法
第一步还是获取反射接口
// 1.Class.forName(全类名)
try {
Class<?> perclass = Class.forName("reflect.Person");
System.out.println(perclass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
获取所有的公共方法(1.本类以及父类中以及接口中所有的方法,2.符合访问修饰符规律 public private不行)
Method[] methods = perclass.getMethods();
for (Method method:methods){
System.out.println(method);
}
//获取当前类的所有方法(1.忽略访问修饰符规律 2.只限当前类)
Method[] methods1 = perclass. getDeclaredMethods();
for (Method method:methods1){
System.out.println(method);
获取属性
//获得所有的公共属性(第一步仍然是获取反射接口)
Field[] fields= perclass.getFields();
for (Field field:fields){
System.out.println(field);
}
//所有的属性
Field[] fields1 = perclass.getDeclaredFields();
for (Field field:fields1){
System.out.println(field);
获得所有的反射接口
Class<?>[] interfaces = perclass.getInterfaces();
for (Class<?> inter:interfaces){
System.out.println(inter);
获得父类
Class<?> superclass = perclass.getSuperclass() ;
System.out.println(superclass);
获取对象
Object instance = perclass.newInstance();
Person person = (Person) instance;
person.interfaceMethod();
注意 所以得获取前提都是先获得反射接口
获得对象的实例并且操作对象
1.首先拿到类
Class<?> perclass = null;
try {
perclass = Class.forName("reflect.Person");
System.out.println(perclass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
2.转化为实例
Person person = (Person)perclass.newInstance();//将instance转化为Person
3.调用属性和方法并测试
person.setNama("zhangsan");
person.setAge(22);
操作属性
1.首先拿到类
Class<?> perclass = null;
try {
perclass = Class.forName("reflect.Person");
System.out.println(perclass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
2.转化为实例
Person person = (Person)perclass.newInstance();//将instance转化为Person
3.设置属性
idField.set(person,"1"); 等同于//person.setid(1)
Field idField = perclass.getDeclaredField("id");
idField.set(person,"1");//person.setid(1)
System.out.println(person.getId());
这时候运行一下会报错
错误提示
错误原因:
访问的是private修饰的id,但是private是私有的 只能本类访问
措施
修改属性访问权限 ,使用反射时如果因为访问修饰符造成异常 可以通过Field/Method/Constructor.setAccessible(true)
操作方法
Method method = perclass.getDeclaredMethod("privateMethod",null);
method.setAccessible(true);
method.invoke(person,null);//方法的调用invoke()
//person.say(xxx)
这里的null是表示parameter参数 QQ截图20190305173104.png
Method method = perclass.getDeclaredMethod("object",parameter);
这是一个不带参数的方法 所以填写null
带参方法的操作
带参.pngMethod method1 = perclass.getDeclaredMethod("privateMethod2",String.class);
method1.setAccessible(true);
method1.invoke(person,"zhangsan");
两个方法都是用private修饰 所以需要我们Method.setAccessible(true);
操作构造方法
获取全部公共构造方法
Constructor<?>[] constructors = perclass.getConstructors();
for (Constructor constructor:constructors){
System.out.println(constructor);
获取本类全部 构造.png
Constructor<?>[] constructors02 = perclass.getDeclaredConstructors();
for (Constructor constructor:constructors02) {
System.out.println(constructor);
获取指定构造方法
构造方法分为有参无参以及public修饰和private修饰
1.操作无参构造方法
QQ截图20190305185007无参.png1.1获取指定构造方法
Constructor<?> constructor02 = perclass.getConstructor() ;
1.2创建对象进行强制转换
Person person1 = (Person) constructor02.newInstance();
System.out.println(person1);
2.操作有参构造方法 指定.png
2.1.获取反射入口
Class<?> perclass = null;
try {
perclass = Class.forName("reflect.Person");
System.out.println(perclass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
2.2获取指定构造方法getConstructor(属性类型.class)
Constructor<?> constructor = perclass.getConstructor(String.class) ;
2.3创建对象进行赋值
Person person = (Person)constructor.newInstance("za");//转化为Person类
System.out.println(person);
3.操作private修饰的构造方法
构造.png3.1获取指定构造方法
Constructor<?> constructor03 = perclass.getDeclaredConstructor(int.class) ;
3.2因为是private修饰 这个需要释放权限
constructor03.setAccessible(true);
3.3创建对象并赋值
Person person2 = (Person)constructor03.newInstance(22);
System.out.println(person2);
动态加载类名和方法
1.首先在项目下建立一个class.txt文本
微信截图_20190306154031.png2.读取文件(在运行时调用方法 创建对象 运行之前不知道)
Properties prop = new Properties();
prop.load( new FileReader("class.txt"));
String classname = prop.getProperty("classname");//获得类名
String methodname = prop.getProperty("methodname");//获得方法名
获得反射入口...
try {
perclass = Class.forName(classname);//这里的类名不是指定的了
System.out.println(perclass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
拿到方法并调用方法
Method method = perclass.getMethod(methodname);
method.invoke(perclass.newInstance());//创建对象调用方法
//反射可以越过泛型检查(虽然可以通过反射可以访问private等访问修饰符不允许访问的属性和方法,也可以忽略泛型的约束 但实际开发不建议)
ArrayList<Integer> list = new ArrayList<>();//这里指定可以添加Integer类型
list.add(12);
list.add(14);
list.add(15);
Class<?> listClass = list.getClass();
Method method = listClass.getMethod("add",Object.class);
method.invoke(list,"zs");//因为上面创建过对象所以这边不需要listClass.newInstance 一个新的对象
System.out.println(list);
通过反射写一个万能赋值方法
//person.setXxx(value);一一对应
public static void setProperty(Object obj, String propertyName, Object value) throws NoSuchFieldException, IllegalAccessException {
Class<?> perclass = obj.getClass();
Field field = perclass.getDeclaredField( propertyName);//获得属性
field.setAccessible(true);//因为是私有的
field.set(obj,value);//(对象,方法)
}
Person person = new Person();
PropertyUtil.setProperty(person,"nama","zs");
System.out.println(person.getNama());