文档章节

【54】Java反射机制剖析

fengsehng
 fengsehng
发布于 2016/11/09 09:15
字数 1762
阅读 0
收藏 0

java反射机制:

1.指的是可以于运行时加载,探知和使用编译期间完全未知的类.

2.程序在运行状态中, 可以动态加载一个只有名称的类, 对于任意一个已经加载的类,都能够知道这个类的所有属性和方法; 对于任意一个对象,都能调用他的任意一个方法和属性;

3.加载完类之后, 在堆内存中会产生一个Class类型的对象(一个类只有一个Class对象), 这个对象包含了完整的类的结构信息,而且这个Class对象就像一面镜子,透过这个镜子看到类的结构,所以被称之为:反射。

4.每个类被加载进入内存之后,系统就会为该类生成一个对应的java.lang.Class对象,通过该Class对象就可以访问到JVM中的这个类.

静态加载类和动态加载类的概念区分:

这里写图片描述

与反射有关的类包.

java.lang.reflect.*;和java.lang.Class;

Java中所有类型(包括基本类型)都对应一个Class对象,这个Class就是java.lang.Class。即每一个类型,在Class中都有一个Class对象跟它对应.Class 没有公共构造方法。注意不是没有,是没有公共的.

从Class中获取信息

这里写图片描述

如何获得Class对象

1.针对每一个对象.getCalss(),可以得到对应的Class.

2.Class.forName(String),String的写法:包名.类名.就会创建包名.类名对应的那个对象

注:1.2只适用于引用类型

3.对于基本类型:封装类.TYPE代表了对应的基本类型的Class对象.Integer.TYPE对应的是int的Class对象
注:3只适用于基本类型

4.类型,Class。<第4种是通用的.>
上面的4种方法,只有方法2是动态的,只要换一个包就可以了.它具有动态潜质.所以真正意义的想体现动态编程只能使用方法2.

每种类型的Class对象只有一个,即他们的地址只有一个,但是不同类型是不同的.所以下面的打印结果都为true.

//对与引用类型
Class c1 = "".getClass();
Class c2 =     Class.forName("java.lang.String");
Class c3 = String.class;
System.out.println(c1 ==c2);//true
//对于基本类型
Class num1 = Integer.TYPE;
Class num2 = int.class;
System.out.println(num1 == num2);//true

反射获取类中的成员的相关方法

[获取构造<根据参数类型>]使用时一般用不带declared的

Constructor<T> getConstructor(Class<?>... parameterTypes) 
      返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。 
 Constructor<?>[] getConstructors() 
      返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。 
 Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 
      返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。 
 Constructor<?>[] getDeclaredConstructors() 
      返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。

[获取属性<根据属性名>]使用时一般用是带declared的,因为属性一般都是私有的

Field getField(String name) 
      返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。 
 Field[] getFields() 
      返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。 
 Field getDeclaredField(String name) 
      返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。 
 Field[] getDeclaredFields() 
      返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。

[获取方法<方法名加上参数类型>]使用时一般用不带declared的

Method getMethod(String name, Class<?>... parameterTypes) 
      返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。 
 Method[] getMethods() 
      返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。 
 Method getDeclaredMethod(String name, Class<?>... parameterTypes) 
      返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。 
 Method[] getDeclaredMethods() 
      返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。 
 T newInstance() 
      创建此 Class 对象所表示的类的一个新实例。 <new Instance()可以动态的创建对象>
 String toString() 
      将对象转换为字符串。

注意:

new Instance()调用的是无参构造,如果该类没有无参构造方法,则newInstance()会产生异常.有declared的方法是支持私有,但是不支持继承,无declared的方法支持继承,不支持私有,且只能取出public的东西.因此取属性的时候一般来说是带declared的,因为属性一般都是私有的,取方法时一般是不带declared的,取构造时一般也是不带declared的.

实例模拟反射获取类中的相关属性和方法

利用反射对属性赋值

Field中的方法
Object get(Object obj)
返回指定对象上此 Field 表示的字段的值。
Field f = c.getXXField(属性名);
值 = f.get(对象);
void set(Object obj, Object value)
将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
f.set(对象,值);
Class

    Class c = Student.class;
    Object obj  = c.newInstance();            //创建Student类的对象
    Field f = c.getDeclaredField("name");        //获取name属性
    f.setAccessible(true);                    //设置私有可以访问.
    f.set(obj, "zhangsan");
    System.out.println(f.get(obj));             //获取obj的name属性的值.

利用反射调用构造

对于构造真正调用是在调用newInstance()方法时.

Class c = Class.forName("com.clazz.reflect.Student");
    Constructor con = c.getConstructor(); //没有执行构造,
    Object cObj = c.getConstructor().newInstance();//调用无参的构造方法
    Constructor conAll = c.getConstructor(int.class,String.class,int.class);
    Object caobj = conAll.newInstance(1001,"zjamgs",234235);//调用含参的构造方法.
    System.out.println(caobj); //打印输出

利用反射调用方法

对象.方法名(值1,2,3);
Method m = c.getMethoed(方法名,参数类型…);
m.invoke(对象,方法调用的参数 )如果底层方法所需的形参数为 0,则所提供的 args 数组长度可以为 0 或 null。

Class c = Class.forName("com.clazz.reflect.Student");
    Object obj = c.newInstance(); //创建Sutdent对象.
    Method msetName = c.getMethod("setName", String.class);//obj无须转换类型
    msetName.invoke(obj, "zhangsan");//调用方法setName, 并传参.
    Method msetId = c.getMethod("setId", int.class);
    msetId.invoke(obj, 409090202);
    System.out.println(obj);

我的微信二维码如下,欢迎交流讨论

这里写图片描述

欢迎关注《IT面试题汇总》微信订阅号。每天推送经典面试题和面试心得技巧,都是干货!

微信订阅号二维码如下:

这里写图片描述

参考:

http://www.cnblogs.com/dennisit/archive/2013/02/26/2933508.html
http://blog.csdn.net/coder_pig/article/details/44784399
http://www.codeceo.com/article/java-reflector-usage.html

© 著作权归作者所有

共有 人打赏支持
fengsehng
粉丝 4
博文 284
码字总数 214494
作品 0
朝阳
程序员
Android 4.4(KK)中利用APP打开关闭数据流量

在Android 4.4中,在app中打开或关闭数据流量 如果有这方面需求可以参考。 思路 利用JAVA的反射机制(Reflection),来调用CONNECTIVITY_SERVICE完成相关操作。 关于JAVA的反射机制,可以参考...

W_X
2014/12/17
0
4
阿里高级Java面试题(首发,70道,带详细答案)

整理的70道阿里的Java面试题,都来挑战一下,看看自己有多厉害。下面题目都带超详细的解答,详情见底部。 1、java事件机制包括哪三个部分?分别介绍。 2、为什么要使用线程池? 3、线程池有什...

java技术栈
2017/11/11
0
0
最最最常见的Java面试题总结——第二周

String和StringBuffer、StringBuilder的区别是什么?String为什么是不可变的? String和StringBuffer、StringBuilder的区别 可变性   String类中使用字符数组:保存字符串,所以String对象是...

Amsour丶
08/13
0
0
云妹总结了一些最最最常见的Java面试题供大家参考

云妹导读:String和StringBuffer、StringBuilder的区别是什么?String为什么是不可变的? String和StringBuffer、StringBuilder的区别 可变性 String类中使用字符数组:private final cha...

阿里云科技快讯
08/17
0
0
Java反射改变Android属性

Java反射改变Android属性 在某些情况下,Android体系里面的某些对象没有对外提供针对某个属性或者类,方法公开的get或者set方法,但是项目需要对这些需要修改和调整。就需要使用Java的反射机...

zhangphil
04/28
0
0

没有更多内容

加载失败,请刷新页面

加载更多

TypeScript基础入门之高级类型的索引类型(Index types)

转发 TypeScript基础入门之高级类型的索引类型(Index types) 高级类型 索引类型(Index types) 使用索引类型,编译器就能够检查使用了动态属性名的代码。 例如,一个常见的JavaScript模式是从...

durban
17分钟前
0
0
利用碎片化时间Get Linux系统

起初,我做着一份与IT毫无关系的工作,每月领着可怜的工资,一直想改变现状,但无从下手,也就是大家熟知的迷茫。我相信,每一个人都会或多或少的经历过迷茫,迷茫每一个选择,迷茫工作或者生...

Linux就该这么学
52分钟前
0
0
图像显示深入学习一:Activity启动过程

一个月左右写了图像显示深入学习之文章开篇文章表明了自己近期的计划,前半年重新学习了opengl es,c++以及Linux的一些知识,觉得是时候开始看图像这一块的源码了,边看边补缺补漏吧。 作为该...

JerryLin123
今天
2
0
给MySQL授权远程访问

putty登录服务器; 登录MySQL: mysql -u root -p 新建远程用户: CREATE USER 'myusername' IDENTIFIED BY 'mypassword'; 授权: grant all on *.* to john@'101.102.103.104' identified by......

sweethome
今天
2
0
在t-io老巢造谣,不过有造谣的就会有反造谣的!

只发当事人的截图,不发表评论,以免有引导嫌疑 PS: 截图是由不同的人发过来的 本人已经不在此微信群 图3:有造谣的,就有反造谣的 图4是2018-09-23的t-io官方群的一个发言小统计,有助于让...

talent-tan
今天
104
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部