文档章节

【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
朝阳
程序员
私信 提问
加载中

评论(0)

转载 二十篇java技术热文

转自微信公众号:java知音 1,详解java类的生命周期 2,Java反射最佳实践 3,Spring的IOC原理 4,Java并发编程:volatile关键字解析 5,Java Thread 总结 6,面向对象之多态【向上转型与向下...

osc_cyo2dovg
2018/03/04
7
0
阿里高级Java面试题(首发,70道,带详细答案)

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

java技术栈
2017/11/11
0
0
Java学习之反射机制及应用场景

前言: 最近公司正在进行业务组件化进程,其中的路由实现用到了Java的反射机制,既然用到了就想着好好学习总结一下,其实无论是之前的EventBus 2.x版本还是Retrofit、早期的View注解框架都或...

总李写代码
2016/11/10
0
0
ButterKnife源码剖析

转载于:[http://blog.csdn.net/chenkai19920410/article/details/51020151] ButterKnife是Jake Wharton大神写开源框架。 项目托管地址: https://github.com/JakeWharton/butterknife。   ......

双鱼大猫
2016/12/16
0
0
IOC的实现原理—反射与工厂模式的结合

反射机制概念 我们考虑一个场景,如果我们在程序运行时,一个对象想要检视自己所拥有的成员属性,该如何操作?再考虑另一个场景,如果我们想要在运行期获得某个类的Class信息如它的属性、构造...

osc_6y4us9hc
2018/01/19
1
0

没有更多内容

加载失败,请刷新页面

加载更多

基于Centos7系统一键部署EFK服务

最近平台EFK版本均作了升级,平台采用EFK(ElasticSearch-7.6.2 + FileBeat-7.6.2 + Kibana-7.6.2)架构。这里建议三个组件主次版本保持一致。考虑到服务器比较多,所以写成脚本来批量部署。 ...

linuxprobe2020
今天
23
0
检查键是否存在于JavaScript对象中? - Checking if a key exists in a JavaScript object?

问题: How do I check if a particular key exists in a JavaScript object or array? 如何检查JavaScript对象或数组中是否存在特定键? If a key doesn't exist, and I try to access it, ......

fyin1314
今天
27
0
jasypt-spring-boot提示Failed to bind properties

1 问题描述 在Spring Boot中使用jasypt-spring-boot进行加密,但是提示: Description:Failed to bind properties under 'spring.datasource.password' to java.lang.String: Reason:......

氷泠
今天
29
0
在git 2.13之前,只保存多个已更改的文件中的一个文件

问题: 如何在我的分支上只隐藏多个已更改文件中的一个? 解决方案: 参考一: https://stackoom.com/question/Cl3h/在git-之前-只保存多个已更改的文件中的一个文件 参考二: https://oldb...

技术盛宴
今天
30
0
SQL笔记:把Excel的数据导入MySQL中作运算

很多Excel用户都知道,Excel单个工作簿单张表存储的数据量很有限(旧版本月60多万条记录,新版本也才104万条不到),而且Excel中,因为自带各种格式与公式,兼之高度封装性等原因,导致Excel...

tengyulong
今天
15
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部