一、概念
反射:反射就是把java类中的各种成分映射成一个个的Java对象
Class对象的由来是将class文件读入内存,并为之创建一个Class对象,同一个类只创建一个Class对象
二、程序的运行过程
classLoader将class文件load到内存中的code segment中,运行环境找到main方法开始执行,运行过程中会动态的加载其他的
class文件
三、classLoader的类加载机制
(1)并不是一次性的加载,而是需要的时候再加载(运行期间动态加载)
(2)static{}:静态语句块,只加载一次
(3){}:动态语句块,每次new新的对象会执行一次,等同于构造方法的语句
若想在eclipse中观察到类的具体加载过程,可以设置:
run as--> run configurations -->VM arguments 设置 -verbose:class
四、JDK中classLoader的分类
(1)bootstrap classLoader:最开始加载的,加载的是jdk核心的类
(2)extesion classLoader:加载jre/lib/ext里的类,像什么jar包里的类
(3)application classLoader:加载我们自己的类,或者是ClassLoader.getSystemClassLoader
(4)other classLoader:URLClassLoader........
五、JDK中classLoader的层次关系(不是继承)
bootstrap<---extesion<--application
application中有指向extesion的引用,classLoader在load class时首先找上一层的loader是不是已经load过了
如果已经load了就不会再次load
安全性好:自己写的String.class永远没机会执行(破坏性的代码)
可以通过getParent()获得上一层的loader
六、反射使用方法
站在classLoader看code segment是一个一个Class对象
class里面有属性对象和方法对象
(1)加载类
Class.forName("");//把该类加载到内存,注意:是该类的全路径(包名+类名)
(2)创建实例对象
Class c = Class.forName("") Object o = c.newInstance();
(3)通过反射获取构造方法并使用
所有公有构造方法:Constructor [] conArray = c.getConstructors();
所有构造方法(私有,默认,受保护,公有)Constructor [] conArray = c.getDeclaredConstructors();
获取公有构造方法:Constructor con = c.getConstructor();
调用:Object o = c.newInstance();
获取私有构造方法:Constructor con = c.getDeclaredConstructor("");//引号里是参数的类型
调用:con.Accessible(true);//暴力访问 Object o = c.newInstance();
(4)获取成员变量并调用
所有公有的字段:Field [] fieldArray = c.getFields();
所有的字段:Field [] fieldArray = c.getDeclaredFields();
获取公有字段:Field f = c.getField("字段名");
调用:f.set(o,"刘德华");//第一个参数:对象 第二个参数:值
获取私有字段:Field f = c.getDeclaredField("字段名");
调用:f.setAccessible(true); f.set(o,"1111");
(5)获取成员方法并调用
所有公有的方法:Method [] methodArray = c.getMethods();
所有的方法:Method [] methodArray = c.getDeclaredMethods();
获取公有方法:Method m = c.getMethod("方法名","参数类型");
调用:m.invoke(o,"刘德华");
获取私有方法:Method m = c.getDeclaredMethod("方法名","参数类型");如int.class,String.class.....
调用:m.setAccessible(true); m.invoke(o,"1111");
(6)反射main方法
Method method = c.getMethod("main", String [].class);
method.invoke(null, (Object)new String[]{"a","b","c"});
(7)通过反射运行配置文件内容
举例:
属性文件:
className = com.\u53CD\u5C04.Student
methodName = show
public class TestReflection {
public static void main(String[] args) throws Exception{
TestReflection t = new TestReflection();
Class c = Class.forName(t.getValue("className"));
Method method = c.getMethod(t.getValue("methodName"));
method.invoke(c.newInstance());
}
public String getValue(String key) throws Exception{
Properties pro = new Properties();
InputStream in = this.getClass().getResourceAsStream("test.properties");//在同一包内
pro.load(in);
in.close();
return pro.getProperty(key);
}
}
class Student {
public void show(){
System.out.println("is show()");
}
}
七、好处和缺点
好处:反射提高了程序的灵活性和扩展性,降低耦合性,提高自适应能力。
它允许程序创建和控制任何类的对象,无需提前硬编码目标类
缺点:性能上慢于直接代码