教学视频:https://edu.51cto.com/course/5667.html?source=so
反射reflect
首先介绍 Java 中 Class 类与 Java 反射的基本用法,然后介绍具体的反射应用。为了便于读者理解,在讲解过程中还结合了大量案例
一、认识反射机制
什么是反射,比如这个人吃番薯会放屁,正常情况我们关心他吃和放的过程,反射机制就是屁怎么放出来的。
概念:反射机制是将泛型固定的类所有方法和成员全部显示出来,以供程序员可以确定程序编写是否有错误的机制;
通过反射去实现另外的功能。
有反也有正,我们看看请示正常的例子:
输出就是日期:
所谓反就是通过对象找来源,在程序中,对象要想找到它的来源,就依靠Object类提供的方法:
范例:观察反的操作
输出就是该对象的Date的类名称->java.util.Date:
现象发现通过getClas()取得的Class对象,就可以直接找到对象的来源。这就是反射,反射反射就是从Class开始。
注意:反射中的泛型都用一个标记,就是问号:<?>,如:class<?>
二、实例化Class类对象
输出:
为什么会出现class?这是因为默认调用toString方法,我们改写下(不要小看这两种方法,我们要靠simpleName活呢):
输出:
在实际开发中用getClass实际用的比较少;
死都要记住这种方法,好处就是可以直接使用字符串实例化对象,实例:
死都要记住这种方法:Class.ForName(“字符串”)
三、通过反射实例化对象(核心)
如果要产生实例化对象,就必现有new对象,有了反射后一切都变了。
在class类中提供了一个方法(一推异常抛出,这些异常不要记,可以查的,也不好记):
范例:正常实例化对象
输出:
范例:反射实例化对象(对比上面)
输出,结果都是一样:
这个例子对比不出来?那在看一个自定义的例子
范例:通过反射实例化对象
输出,也是调用了无参构造:
若是有参的情况呢?
这样就是出现实例化异常。所以为什么在类中写无参构造方法,1是给子类调用方便,2是给反射调用方便
写到这里大家会发现,用反射的方法比普通的方法多两行,是不是有病?我们会学习工厂设计模式+反射机制
四、工厂设计模式修正(理解即可)
熟悉的三大设计模式:1.工厂设计模式;2.单例设计模式;3.代理设计模式;
工厂设计模式的本质在于想要取得接口的实例化对象不要直接使用关键字new,而应该通过工厂取得,只要自己写的接口要想实现实例化对象要写工厂99%;
范例:传统工厂设计模式
输出:
如果要增加子类,那意味着工厂也要跟着修改。
比如我们新增一个子类,如下:
这样是能实现,如果增加很多很多子类,源源不断的增加,你改都没有它新增的快呢,怎么解决?关键性就在new上,这是造成本次缺陷最大的元凶,可扩展性很差;这时候可以通过反射来实现工厂类,反射的特点:接收字符串。
注意:
等价于
这样就不会频繁加一个类就改工厂了。
以上的代码只是分析出了关键字new实例化对象与构造方法实例化对象的区别,但是并不是意味着不适用关键字new了
反射适用于可扩充性,比new大,要写过项目后,才反过来看才懂。
反射的三种方法:构造方法、普通方法、成员
五、反射调用的构造方法
这种取得本身是有问题的,因为它本身只能调用无参构造,例如:
这个代码一定报错,没有无参;
如果人不提供无参,那么我们就不能用反射实例化了呢?错!
如果类中没有提供无参构造方法,那么必须明确的调用知道的构造方法实现对象的实例化操作。这个方法是谁?
那么必须要找到类中的构造方法定义:
这个是什么意思?就是要找到参数的类型,比如上面代码的例子,类型是String和int型,
所以我们代码可以这么写:
找到了Constructor能干什么?
找到了java.lang.reflect.Constructor类之中在此类中提供一个实例化对象的方法,从此可以开始真正迈入反射了,
实例化对象:
范例:使用反射调用指定构造实例化对象
输出:
对比使用反射和其他方法,那种方法省事、简单。每个类的参数方法无法统一,反射可以。这就是为什么要有无参构造方法的主要原因。
六、反射调用的普通方法
类中的普通方法是在取得本类的实例化对象置才可以进行调用的操作,所以即便使用了反射进行方法的调用,那么也必现使用newInstance()取得实例化对象,在Class类中定义有如下取得方法对象的操作:取得方法:
范例:给了你类名称(name),给了操作属性(set、get方法),把value=“张三”,普通方法先实例化对象,
因为getMethod的name首字母要大写,哪个方法可以实现大写,如下方法,自己扩充以下(注意行号):
返回值就是方法的返回值,,set有参数,get无参数,看上面
分析:
set没有返回值,所以是get有,所以输出是get
输出:
以后代码中给了属性名称,类的完整名称,而后可以进行自动赋值操作,那么基本上就是反射在起作用。set几乎不会被调用,get方法才会被调用。
七、反射调用的成员
构造方法调完了,普通方法掉完了,就剩下调用成员,这是三大组成部分,需要考虑两种因素(Class类定义的方法),
一种是继承而来,从父类来
二是本类定义的成员
在java中使用java.lang.reflect.Field类描述成员,有两个方法:
1.取得成员内容(相当于对象.属性):
2.设置成员内容:
范例:直接进行属性调用
输出报错,私有属性能访问吗?:
其实它是可以访问的,几乎所有的属性都需要private封装,要想解决封装的困扰,可以利用File父类的方法完成
():
取消封装:
设为true就是取消封装;
这样取消封装后才能运行:“
这就是反射。