java Reflection:
1,反射机制允许程序在执行期间借助Reflection API 取得任何类的内部信息(比如成员变量,构造器,成员方法等)。并且能操作对象的属性及方法。反射在设计模式和框架底层都会用到;
2,加载完类之后,在堆中就产生了一个Clss类型的对象(一个类中有一个Class对象),这个对象包含了类的完整结构信息。通过这个对象得到类的结构。这个Class对象就像一面镜子,透过这个镜子看到类的结构,所以,形象的称之为“反射”。
反射机制原理图:
1,代码 / 编译阶段:代码经过 Javac 编译后得到 Cat.class 字节码文件;
2,Class类阶段(加载阶段):当你创建一个对象时如:Cat cat = new Cat(); 时,会导致类加载,即:使用类加载器 ClassLoader 加载 Cat.class 字节码文件到堆内存中,生成一个 Cat 的 Class 类对象。这个Class类对象在堆中其实是一个数据结构,在底层把对象中的成员变量,构造器等当成一个对象对待。类加载完成后才生成运行阶段的 cat 对象;
3,Runtime运行阶段:类加载完成后在堆中生成 Cat 对象,该对象知道自身是属于哪个Class对象,得到 Class 对象后就可以使用 Class 对象中的内容。
反射相关的主要类:
1, java.lang.Class :代表一个类(这个类就叫class),Class对象表示某个类加载后在堆中的对象;
2,java.lang.reflect.Method:代表类的方法, Method对象表示类的某个方法。
3,java.lang.reflect.Field:代表类的成员变量,Field对象表示某个类的成员变量。
4.java.lang.reflect.Constructor:代表类的构造方法,Constructor对象表示构造器。
这些类在 java.lang.reflection 中
因为Class类对象在堆中其实是一个数据结构,底层把Class类中的成员变量,方法等都当成对象对待,所以成员变量,方法等都需要一个对应的类。
Cat类:
public class Cat {
private String name = "招财猫";
public String name1 = "哆啦A梦";
public Cat(){}
public Cat(String name){
this.name = name;
}
public void cry(){
System.out.println(name + "喵~~~");
}
public void hi(){
System.out.println(name + "hi");
}
}
re.properties 配置文件:
classfullpath=com.hsp.Cat method=hi
使用反射机制根据配置文件创建Cat对象:
import java.io.FileInputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Properties;
public class Reflection01 {
public static void main(String[] args) throws Exception{
//使用Properties类,读取配置文件
Properties properties = new Properties();
properties.load(new FileInputStream("src\re.properties"));
//classfullpath读取配置文件中Cat类的包的所在位置,"com.hsp.Cat"
String classfullpath = properties.get("classfullpath").toString();
String methodName = properties.get("method").toString();
//加载类,返回Class类型的对象cls
Class cls = Class.forName(classfullpath);
//通过 cls 得到 加载的类 com.hsp.Cat 的对象实例
Object o = cls.newInstance();
System.out.println("o的运行类型=" + o.getClass());
//java.lang.reflect.Method:
// 通过 cls 得到 com.hsp.Cat 的 methodName"hi" 的方法对象
//反射中把方法当成对象(万物皆对象的思想);
Method method1 = cls.getMethod(methodName);
Method method2 = cls.getMethod("hi");
//通过Method(方法)对象 method1 调用方法,即通过方法对象来调用方法
method1.invoke(o);//传统的调用方法:对象.方法()。反射:方法.invoke(对象)
method2.invoke(o);
//java.lang.reflect.Field:代表类的成员变量,Field对象表示某个类的成员变量
//getField不能获得私有属性
Field nameField = cls.getField("name1");
//传统:对象.成员变量。反射:成员变量对象。get(对象)
System.out.println(nameField.get(o));
//java.lang.reflect.Constructor:代表类的构造方法,Constructor对象表示构造器
Constructor constructor = cls.getConstructor();//()中可以指定构造器参数类型,放回无参构造器
System.out.println(constructor);
Constructor constructor1 =cls.getConstructor(String.class);//这里传入的String.class,就是String类的Class对象
System.out.println(constructor1);
}
}
反射的优缺点:
优点:可以动态的创建和使用对象(也是框架底层的核心),使用灵活,没有反射机制,框架技术就失去底层支撑。
缺点:使用反射基本是解释执行,对执行速度有影响。
反射调用优化:
1,关闭访问检查:Method和Field,Constructor 对象都有 setAccessible() 方法,setAccessible 的作用是启动和禁用访问安全检查开关。参数值为 true 表示反射的对象子使用时取消访问检查,提供反射的效率。参数值为 false 则表示反射的对象执行访问检查。(优化提高不会太高)
待续……



