java反射机制:
即通过外部文件配置,不修改文件源码的情况下,来控制程序,也符合设计模式的OCP原则(开闭原则:不修改源码,扩容原则)
Java Reflection
1.反射机制允许程序在执行期间借助于ReflectionAPI取得任何类的内部信息(比如成员变量,构造器,构造方法),并能操作对象的属性及方法。
2.加载完类以后,在堆中就产生了一个class类型的对象,一个类只有一个class对象,这个对象包含类的完整的结构信息,通过对这个对象得到类的结构,所以叫做反射
准确的在计算机内的过程如图所示:
其实java中的每个创建的类都要经过classloder进行类加载,所以每一个类都有对应的Class对象
要点:
反射相关的类:
-
java.lang.Class代表类,Class对象表示某个类加载后在堆的对象
-
java.lang.reflect.Method :代表类的方法,Method表示类的方法
-
java.lang.refect.Field代表类的成员
-
java.lang.reflect.Construtor代表类的构造方法
优缺点:
优点:
可以动态的创建和使用对象,(框架底层核心),使用灵活,没有反射机制,框架技术就失去底层机制
缺点:
使用反射基本是解释执行,对执行速度有影响
这就涉及到如何优化的问题:将安全检查开关关闭
Class类:
-
class类也是类,也继承Object类
-
Class类对象不是new出来的,而是系统创建的
-
对于某个类的Class类对象,在内存中只用一份,因为类只加载一次,当你再次加载时,就会不重新加载
-
每个类的例子都会记得自己是那个Class实例生成的、
-
通过Class对象可以完整的得到了一个类的完整结构
-
Class是在堆里存
得到该类对应的Class类(4种方式)
第一种:已知一个类的全类名,且该类在类路径下,可以通过Class类的静态方法.forName获取
多用于配置文件,读取类全路径,加载类
放的
Class aclass=Class.forName("study.yufa.reflect.co");必须包含所有路径
第二种 :已知具体的类,通过类的class获取,该方式是最为安全可靠的
用于参数传递,比如说通过反射得到对应的构造器对象
Class cdbdb= co.class;
第三种:利用classLoader (有4种类加载器)
co c=new co(); ClassLoader classLoader=c.getClass().getClassLoader(); //先得到类加载器 Class<?> aClass = classLoader.loadClass("study.yufa.reflect.co");
第四种:直接利用类.getclass()
也就是我平时输出的getclass的结果,就该类反射形成的class
-
通过的Class类去的得到原来类的对象
co c = (co) aclass.newInstance(); package study.yufa.reflect; public class co { public String a="78906"; public String y="3445455"; @Override public String toString() { return "co{" + "a='" + a + '\'' + ", y='" + y + '\'' + '}'; } }
通过getField得到类的属性
Field field=aclass.getField("a");//getField(属性名) System.out.println(field.get(c));
getField方法与类的属性的修饰符有关,如果属性修饰符为private和不写(缺省(没有访问控制符):可被该类自身、本包中的类引用),则会爆出异常
-
如果要通过Field 修改类的属性
field.set(c,"4567890");
输出所有属性名
Field []field1=aclass.getFields();
for(Field f:field1){
System.out.println(f.getName());
}
那些对象有class对象
外部类,成员内部类,静态内部类,匿名内部类,interface,数组,枚举类,annotation(注解)
基本数据类型,void