反射入门

1、认识反射

“反”,有反就有“正”。正常情况先有类,再产生对象。所谓的反就是可以利用对象找到对象的出处:

在Object类里面提供有一个方法:取得Class对象:

public final Class getClass();

可以输出类的完整名称,就找到了对象的出处。

Class类对象的实例化:

java.lang.Class是一个类。这个类是反射操作的源头,所有的反射都要从此类开始进行。最关键的是这个类有三种实例化方式。

1、调用Object类中的getClass()方法:Class cls = mIntent.getClass();需要实例化对象,需要import导入类

2、使用“类.class”取得:Class cls = Intent.class。不需要实例化对象,需要import导入类

3、调用Class类提供的方法:Class.forName(String className)。不需要import语句导入一个明确的类

反射实例化对象。

当拿到一个类的时候,肯定用关键字new进行对象的实例化操作,但是如果有了Class类对象后,就可以不用New关键字也可以进行对象的实例化操作:

public T newInstance()相当于使用new调用无参构造函数。

有了反射之后,进行实例化的操作不再只是单单依靠关键字new完成了。反射也可以。

所以用反射获取一个对象实例化的步骤为:

1、先获取Class类的实例化对象:Class cls = Class.forName(“xxxxxx”);

2、用Class类的实例化对象获取制定类的实例化对象:Book book=(Book)cls.newInstance();


但是本来用关键字new一行代码就可以完成实例化操作,反射需要两步,这样好吗?


2、理解反射的作用

在任何开发中,一起的耦合都起源于new。

看工程模式。如果想要扩展,就必须改动工厂类中的if else。如果一直扩展,就需要一直修改工厂类。因为工厂类中是通过New产生对象实例的,所以New就是问题的关键。

如果工厂中用反射代替new,就不需要if else和new实例化每个if else中的对象。只需要传入类的完整名称,就可以解耦和。扩展性非常的强!

3、利用反射调用类的结构

a、使用反射调用构造:

之前所说的newInstance()方法实际上等于调用了无参构造函数,但是实际中可能么有无参构造函数,

Class中有方法可以取到构造:public Constructor[]getConstructors():取得全部构造。

和:public Constructor getConstructor(Class… paramterTypes):取得一个指定参数顺序的构造函数。

Constructor类是java.lang.reflect,这时候真正到了反射中。

实例化对象方法public T newInstance(Object… initargs)

所以用反射获取一个没有无参构造函数的类的实例化对象步骤为:

1、先获取Class类对象:Class cls = Class.forName(“xxxxx”);

2、获取指定参数类型顺序的构造函数:Constructor con = cls.getConstructor(Sring.class,double.class);

3、使用获取到的构造函数实例化对象:Object obj = con.newInstance(“第一个参数字符串类型”,10086.8);

所以建议,不管有多少个构造方法,都尽量提供一个无参构造函数,不然太麻烦了。

b、反射调用方法:

Class类中提供了一下方法用来获取类的方法:

public Method[]getMethods()

public Method getMethod(String methodName,Class… paramterTypes)

Method类似java.lang.reflect包下的,其中有个

public Object invoke(Object obj,Object… args)方法。

所以用反射调用方法的步骤为:

1、先获取Class对象:Class cls = Class.forName(“xxxxx”);

并获取对象Object object = cls.newInstance();//必须给出实例化对象

2、获取指定方法:Method setTitleMethod = cls.getMethod(“setTitle”,String.class);

3、调用方法:setTitleMethod.invoke(object,“一本书的标题”);//等价于Book对象.setTitle(“一本书的标题”)

但是这个过程中完全没有出现过Book。也就是说,利用反射可以实现任意类的制定方法的调用。

c、反射调用成员:

类中的属性一定要在本类实例化对象产生后才可以分配内存空间。

Class类中提供了取得成员的方法:

1、取得全部成员:public Field[]getDeclaredFields()

2、取得指定成员:public Field getDeclaredField(String fieldName)

Field是java.lang.reflect包下。其中有:

1、取得属性内容:public Object get(Object obj);

2、设置属性内容:public void set(Object obj,Object value)

所以反射调用成员的步骤为:

假设一个Book类,里面只有一个属性private String title;没有getter/setter方法。

1、先获取Class对象:Class cls = Class.forName(“xxx”);

2、获取对象:Object obj = cls.newInstance();

3、获取指定成员:Field titleField = cls.getDeclaredField(“title”);

4、设置属性内容:titleField.set(obj,“书的名字”);//相当于:Book类对象.title =“书的名字“

但是调用get还是会报错。因为封装性。

这时候需要用到:AccessbleObject

在java.lang.reflect.AccessibleObject类下面(JDK1.8修改):

~ Executable//可执行的

~ Constrictor

~Method

~Field

在这个类中有一个方法:

public void setAccessible(boolean flag)设置是否封装,

设置为false后,就是取消封装,这个时候再调用刚才的get就可以正常调用了。

构造方法和普通方法一样可以取消封装,只不过很少这样去做,而且对属性的访问还是应该是getter和setter方法完成。

学习完这些,反射算是入门了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 5,845评论 0 9
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,486评论 19 139
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,956评论 18 399
  • 学习Android的同学注意了!!!学习过程中遇到什么问题或者想获取学习资源的话,欢迎加入Android学习交流群...
    kingZXY2009阅读 2,578评论 0 0
  • “你说胡离啊,我知道这个人,每天晚上12点准时,他就会出现在这个街角,看起来像刚下班回家。”街角的零售店老板说。 ...
    知鱼君阅读 1,326评论 0 1