框架是个好东西,可早晚有一天会过时,这世界上就没有亘古不变的东西,来学下Java基础吧
反射机制
Java语言的反射机制是指:在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用他的任意一个属性和方法,这种动态获取的信息以及动态调用对象的方法的功能成为反射机制
如何获取这些信息呢?依赖于Class对象,Class对象将一个类的方法,变量等信息告诉运行的程序
获取Class对象的两种方法:
已知类名为TargetObject
- Class alunbarClass = TargetObject.class;
- Class alunbarClass1 = Class.forName("cn.luckycurve.TargetObject");
反射使用实例
供调用的TargetObject类
public class TargetObject {
private String value;
public TargetObject() {
value = "LuckyCurve";
}
public void publicMethod(String name) {
System.out.println("I love " + name);
}
private void privateMethod(String name) {
System.out.println("I hate " + name);
}
}
调用Target的Main类
public class Main {
// 操作Traget类
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
Class<?> targetClass = Class.forName("cn.luckycurve.demo9.TargetObject");
// 从Java 9 开始不推荐使用以下写法
// TargetObject o = (TargetObject) targetClass.newInstance();
// 推荐写法为
TargetObject target = (TargetObject) targetClass.getDeclaredConstructor().newInstance();
// 获取类中的所有方法
Method[] methods = targetClass.getDeclaredMethods();
for (Method method : methods) {
System.out.println("method name :" + method.getName());
}
// 获取指定方法并调用,要指定方法名和参数信息
Method publicMethod = targetClass.getDeclaredMethod("publicMethod", String.class);
// 由于是非静态方法,要指定调用方法的对象
publicMethod.invoke(target, "Java");
// 直接获取和修改private类型的字段
Field value = targetClass.getDeclaredField("value");
// 因为value是private的,取消安全检查,不然会抛出异常
value.setAccessible(true);
String string = (String) value.get(target);
System.out.println("修改前 value:" + string);
value.set(target,"LuckyCurve2");
String string2 = (String) value.get(target);
System.out.println("修改后 value:" + string2);
// 调用私有方法
Method privateMethod = targetClass.getDeclaredMethod("privateMethod", String.class);
// 取消安全检查
privateMethod.setAccessible(true);
privateMethod.invoke(target,"lazy");
}
}
<<<method name :publicMethod
<<<method name :privateMethod
<<<I love Java
<<<修改前 value:LuckyCurve
<<<修改后 value:LuckyCurve2
<<<I hate lazy
总结:
1.调用非静态方法,要将对象传进invoke方法中
2.所有声明为private的字段和方法,在使用前都要调用feild.setAccessible(true)或者method.setAccessible(true)来解除安全检查
静态编译和动态编译
- 静态编译:在编译时确定类型,绑定对象
- 动态编译:在运行时确定类型,绑定对象
C++里面有详细的描述(C++的语言颗粒度细,程序很容易涉及到底层)
反射的优缺点
- 优点:动态编译,增加了灵活性
- 缺点:运行效率低,需要JVM进行一系列解释操作。安全问题,反射甚至可以操作私有字段和方法(也是优点,增加了灵活性 )
反射的应用场景
反射是框架的灵魂
虽然开发的时候很难用到反射机制,但也不能说明反射机制没有什么用,动态代理的设计模式,模块化的开发,还有我们日常使用的Spring / Hibernate等框架,都大量用到了反射机制
- JDBC连接数据库时候使用了Class.forName
- Spring框架的IOC以及AOP
- …