因为反射是框架设计的灵魂。了解了反射的原理,掌握了反射的用法这对后期学习框架以及手写框架能够起到很好的帮助的作用。
JAVA反射机制
好处:
(1)可以在程序运行的过程中,操作这些对象
(2)可以解耦,提高程序的可扩展性
弊端:
(1)会存在一定的性能问题
(2)在前期的学习中,难以理解
(1)反射通常用于平台或框架编程,例如:
框架中对象的构建.
框架中方法的调用.
(2)框架中反射应用案例分享
对象创建
a) mybatis中的resultType,resultMap
b) spring中的bean
方法调用
a) 对象set方法,get方法,…
b) spring mvc 控制层方法,…
总之:反射不能预知未来,但可驾驭未来,通过反射可以更好构建一些编程框架,以实现通用性编程,从而达到简化代码编写。
在java中可以将对象分为两大体系:字节码对象 和 实例对象。
每个类在加载(将类从硬盘读到内存)时都会创建一个字节码对象,且这个对象在一个JVM内存中是唯一的。此对象中存储的是类的结构信息。
(1)Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象
应用场景:
多用于配置文件。将类名定义在配置文件中。读取文件,加载类。
(2)类名.class:通过类名的属性class获取
应用场景:
多用于参数的传递
(3)对象.getClass():getClass()方法在Object类中定义着
应用场景:
多用于对象获取字节码的方式
public class reflect {
/*
(1)Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
(2)类名.class:通过类名的属性class获取
(3)对象.getClass():getClass()方法在Object类中定义着
*/
public static void main(String[] args) throws Exception {
//(1)Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
Class cls1 = Class.forName("com.itcast.Person");
System.out.println(cls1);
//(2)类名.class:通过类名的属性class获取
Class> cls2 = Person.class;
System.out.println(cls2);
//(3)对象.getClass():getClass()方法在Object类中定义着
Person p = new Person();
Class cls3 = p.getClass();
System.out.println(cls3);
System.out.println(cls1==cls2);
System.out.println(cls1==cls3);
System.out.println(cls2==cls3);
}
}
结论:同一个字节码文件在一次程序运行过程中,只会被加载一次,不论通过哪种方式获取的Class对象都是同一个。
获取功能。
1)获取指定名称的public修饰的成员变量
Field getField(String name)
2)获取指定名称的成员变量,不考虑修饰符
Field getDeclaredField(String name)
3)获取所有public修饰的成员变量
Field[] getFields()
4)获取所有的成员变量,不考虑修饰符
Field[] getDeclaredFields()
@Test
public void test1() throws Exception{
Class> cls1 = Class.forName("com.itcast.Person");
Field[] fields1 = cls1.getDeclaredFields();
for (Field field : fields1) {
System.out.println(field);
}
System.out.println("******************************");
Field[] fields2 = cls1.getFields();
for (Field field : fields2) {
System.out.println(field);
}
}
Field:成员变量
操作:
1.设置值
void set(Object obj,Object value)
2.获取值
get(Object obj)
3.忽略访问权限修饰符的安全检查
setAccessible(true):也叫暴力反射
Constructor:构造方法
创建对象:
如果使用空参数构造方法创建对象,操作可以简化为:
Class对象的newInstance方法
实例对象是基于类的结构信息创建的对象,在内存中可以有多份.
1)编译时借助new关键字构建.(真正创建会发生在运行时)
2)运行时可借助反射API创建.
说明:每个实例对象都会独占堆内存中一块连续的内存空间.且对象的创建和销毁都会占用系统资源.