1.为啥用反射?
用框架时,
想要调用 哪个类 中的 哪个方法。
不必改源码,
直接在 配置文件=解耦=封装性 中改。
2.子类 通过反射 能拿到父类公有,拿不到 父类私有
尝试拿 父类 的 私有属性、方法:
私有的不能被子类继承
肯定 即便是 子类用 declared也不能拿到
3.单例模式 不让new对象;反射 直接通过字节码文件获取对象
岂不是和单例模式冲突了???
没有冲突。
不存在冲突 不冲突的问题。
设计模式不属于java中真正的底层知识点,
他只是一种代码的 设计思想
一共有23例设计模式,用了有更好的效果 不用也可以。
那单例模式里面有办法可以避免反射吗?
没有。
私有属性方法 用反射都能打破,更别说只是个设计模式了。
4.用反射 属性值要怎么拿到?方法要怎么执行?
面向对象!
属性、方法
都由 对象 搞
5.写代码吧
5.1 创建1个Animal类
import javax.xml.transform.Source;
import java.sql.SQLOutput;
public class Animal {
//私有属性 爱人
private String lover="person";
//公有属性 名字
public String name="lucy";
//此处不必要 加 私有构造方法 仅可拿公有构造getConstructor
//公有、无参 构造
public Animal() {
System.out.println("公有 、 无参 构造执行了");
}
//私有方法
private void sleep(){
System.out.println("私有方法睡觉 执行了");
}
//公有方法
public void eat(String name,String food){
System.out.println(name+"开始吃"+food);
System.out.println("公有方法吃饭 执行了");
}
}
5.2测试类:
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class MyReflect {
public static void main(String[] args) throws Exception {
//show属性
// showField();
//show方法
showMethod();
}
//通过反射 拿到 指定属性 的 值
// 1.拿到类对象=字节码对象
// 2.拿到属性
// 3.拿到属性值
public static void showField() throws Exception {
//forName(String className)
//返回与给定字符串名称的类或接口相关联的 类对象=字节码对象。
//框架中 读取配置文件 获取到的都是字符串数据类型,所以常用此种 参数正好为字符串数据类型
Class aClass = Class.forName("Animal");//全限定名=绝对路径
// Class<Animal> animalClass = Animal.class;
// Class<? extends Animal> aClass1 = new Animal().getClass();
//----------------拿 公有属性值 开始---------------------------
Field name = aClass.getField("name");
// System.out.println(name);
//public java.lang.String Animal.name
//get(Object obj)
//返回该所表示的字段的值 Field ,指定的对象上。 =属性值
//此中obj
// 面向对象 属性、方法 均由 对象执行
Object o = aClass.newInstance();
// System.out.println(o);
//公有无参 构造执行了
//Animal@1540e19d
Object o2 = name.get(o);
System.out.println(o2);
//lucy
//----------------拿 公有属性值 结束---------------------------
//----------------拿 私有属性值 开始---------------------------
//1.拿到字节码
//2.拿到私有属性
//3.设置可访问为true
//4.拿到属性值
// Field[] fields = aClass.getDeclaredFields();
// Field field = fields[0];
Field lover = aClass.getDeclaredField("lover");
//拿到属性后 直接获取私有值=报错 先暴力破解
lover.setAccessible(true);//Accessible=可访问
Object o3 = lover.get(new Animal());
System.out.println(o3);
//公有 、 无参 构造执行了
//person
//----------------拿 私有属性值 结束--------------------------
}
/**
*通过反射 执行 指定方法
* 1.拿 字节码对象
* 2.拿方法
* 3.invoke执行
*/
public static void showMethod() throws Exception{
Class aClass = Class.forName("Animal");
//getMethod(String name, 类<?>... parameterTypes)
Method eat = aClass.getMethod("eat",String.class,String.class);
eat.invoke(aClass.newInstance(),"苏溪","披萨");
//公有 、 无参 构造执行了
//苏溪开始吃披萨
//公有方法吃饭 执行了
//------------执行 私有方法 开始--------------
//只要是 私有 设可访问为true
// Method[] declaredMethods = aClass.getDeclaredMethods();
Method sleep = aClass.getDeclaredMethod("sleep");
sleep.setAccessible(true);
sleep.invoke((Animal)aClass.getConstructor(null).newInstance());
//公有 、 无参 构造执行了
//私有方法睡觉 执行了
}
}
6.总结
6.1 由以上可看出
反射创建实例的难点在于,很多人不知道:
clazz.newInstance()底层还是调用Contructor对象的newInstance()。
所以,要想调用clazz.newInstance(),必须保证编写类的时候有个 无参构造。
6.2浅谈反射机制【有空深入理解一下这篇文章】
https://zhuanlan.zhihu.com/p/66853751