一. 反射机制简介
在Java语言里面之所以会有如此众多的开源技术的支撑,很大一部分是来自于Java最大的特征 —— 反射机制。
如果你现在不能够灵活去使用反射机制进行项目的开发和设计,那么可以说你并未接触到Java的精髓所在。
所有的技术实现的目标只有一点: 重用性。
对于反射技术首先考虑的是 “反” 与 “正” 的操作,所谓的 “正” 操作指的是当我们要使用一个类的时候,要先导入程序所在的包,而后根据类,进行对象的实例化,并且依靠对象调用类中的方法。但是如果说 “反” ,根据实例化对象反推出其类型。
如果要想实现反的处理操作,那么首先要采用的就是 Object类 中所提供的的一个新的方法:
- 获取Class对象信息: public final Class<?>getClass();
范例: 观察Class对象的使用
1 | package cn.ngp.demo; |
getClass()可以帮助使用者找到对象的根源。
二. 反射机制(Class类对象的三种实例化模式)
java.lang.Class
是一个类,这个类是反射操作的源头,即:所有的反射都要从此类开始,而最关键的是这个类有三种实例化方式:
-
第一种: 调用Object类中的getClass()方法
1
2
3
4
5
6
7
8package cn.ngp.demo;
import java.util.Date;//先有类
public class TestDemo {
public static void main(String[] args) throws Exception {
Date date = new Date();
System.out.println(date.getClass());
}
}
-
第二种: 使用"类.class"取得
1
2
3
4
5
6
7
8package cn.ngp.demo;
import java.util.Date;//先有类
public class TestDemo {
public static void main(String[] args) throws Exception {
Class<?> cls = Date.class;
System.out.println(cls);
}
}之前是在产生了类的实例化对象之后取得的Class类对象,但是此时并没有实例化对象的产生。
-
第三种: 调用Class类提供的一个方法
-
-| 实例化Class对象: public static Class<?> forName(String name, boolean initialize,ClassLoader loader) throws ClassNotFoundException
1
2
3
4
5
6
7package cn.ngp.demo;
public class TestDemo {
public static void main(String[] args) throws Exception {
Class<?> cls = Class.forName("java.util.Date");
System.out.println(cls);
}
}
-
此时可以不使用import语句导入一个明确的类,而类名称是采用字符串的形式进行描述的。
初期: Class.forName用得最多
三. 反射机制(反射实例化对象)
当拿到一个类的时候,肯定要直接用关键字new进行对象的实例化操作,这属于习惯性的做法,但是如果有了Class类对象,那么就可以做到,利用反射来实现对象实例化操作:
- 实例化对象方法:public T newInstance() throws InstantiationException, IllegalAccessException
1 | package cn.ngp.demo; |
有了反射之后,以后进行对象实例化的操作不在只是单独的依靠关键字new完成了,反射页也同样可以完成,但是这并不表示new就被完全取代了。
在任何的开发之中,new是造成耦合的最大元凶,一切的耦合都起源于new。
范例: 观察工厂设计模式
1 | package cn.ngp.test; |
如果此时增加了Fruit借口子类,那么就表示程序要修改工厂类。
1 | package cn.ngp.test; |
每增加一个类就要去修改工厂类,那么如果随时都可能增加子类呢?工厂类要一直被修改。
因为现在工厂类中的对象都是通过关键字new直接实例化的,而new就成了所有问题的关键点,要想解决这一问题,我们就能够依靠反射完成。
1 | package cn.ngp.test; |
此时的程序就真正完成了解耦和的目的,而且可扩展性非常的强。
四. 反射机制(调用构造方法)
在之前