java Reflection(反射)基础知识讲解
原文链接:小ben马的java Reflection(反射)基础知识讲解
1.获取Class对象的方式
1.1)使用 "Class#forName"
public static Class<?> forName(String className) throws ClassNotFoundException;
如果没有获取到Class对象,则抛出异常 ClassNotFoundException;
eg:
Class<?> customerClazz = Class.forName("cn.xiaobenma.demo.core.reflection.VipCustomer");
1.2)使用某个类的 ".class",eg:
Class<?> customerClazz = VipCustomer.class;
1.3)某个对象的 "#getClass()",eg:
VipCustomer customer = new VipCustomer("001", "小ben马", "10086", VipCustomer.VIP_ADVANCED);
Class<?> customerClazz = customer.getClass();
2.判断是否为某个类的实例
我们通常使用 "instanceof" 来判断对象是否为某个类的实例。同样,可以使用 "Class#isInstance()" 来判断
public native boolean isInstance(Object obj);
例子:
boolean isCustomer = customer instanceof VipCustomer;
isCustomer = VipCustomer.class.isInstance(customer);
如果person为null, 上述例子都返回false。
3. 创建实例
3.1)使用 "Class#newInstance()": 要保证能访问类的无参构造方法
public T newInstance() throws InstantiationException, IllegalAccessException;
3.2)通过 "Constructor#newInstance(Object ... initargs)"
public T newInstance(Object ... initargs)
throws InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException
eg:
Constructor<VipCustomer> constructor = getVipCustomerClass().getConstructor(String.class, String.class, String.class, int.class);
VipCustomer customer = constructor.newInstance("001", "小ben马", "10086", VipCustomer.VIP_ADVANCED);
4. 获取方法(类方法、成员方法)
在Class中定义的方法如下:
//a. 获取当前类及其父类,所有`public`类方法和成员方法
public Method[] getMethods() throws SecurityException;
//b. 通过方法名、参数类型,获取单个`public`类方法或者成员方法(当前类或父类定义的)
public Method getMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException;
//c. 获取当前类(不包括超类)定义的所有类方法和成员方法
public Method[] getDeclaredMethods() throws SecurityException;
//d. 通过方法名、参数类型,获取单个当前类(不包括超类)定义的类方法或成员方法
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException;
5. 获取构造方法
在Class中定义的方法如下:
//a. 获取当前类所有`public`构造方法
public Constructor<?>[] getConstructors() throws SecurityException;
//b. 根据参数类型,获取当前类单个`public`构造方法
public Constructor<T> getConstructor(Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException;
//c. 获取当前类所有构造方法
public Constructor<?>[] getDeclaredConstructors() throws SecurityException;
//d. 根据参数类型,获取当前类单个构造方法
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException;
6. 获取变量(类变量、成员变量)
在Class中定义的方法如下:
//a. 获取当前类及其超类,所有`public`类变量和成员变量
public Field[] getFields() throws SecurityException;
//b. 通过名称,获取当前类或超类,单个`public`类变量或者成员变量
public Field getField(String name)
throws NoSuchFieldException, SecurityException;
//c. 获取当前类(不包括超类),所有类变量和成员变量
public Field[] getDeclaredFields() throws SecurityException;
//d. 通过名称,获取当前类(不包括超类),单个类变量或成员变量
public Field getDeclaredField(String name)
throws NoSuchFieldException, SecurityException;
7. 通过inovke,调用对象的方法
eg:
Method setRank = getVipCustomerClass().getDeclaredMethod("setRank", int.class);
setRank.invoke(customer, VipCustomer.VIP_NORMAL);
8.获取和修改类变量或者成员变量的值
8.1) Field#set(Object obj, Object value): 通过对象和变量值,设置变量,eg:
Field field = getVipCustomerClass().getDeclaredField("rank");
field.set(customer, VipCustomer.VIP_ADVANCED);
8.2) Field#get(Object obj): 通过对象获取变量值,eg:
Field field = getVipCustomerClass().getDeclaredField("rank");
int rank = (int) field.get(customer);
9.动态改变方法和变量的可访问性
在使用反射获取被调用类的构造方法、方法或变量,可能对于调用类是不可访问的,如被调用类的"private"构造方法,"private" 方法, "private" 变量,会抛出 IllegalAccessException。
java可以通过使用 "AccessibleObject#setAccessible(boolean flag)" 改变可访问性。
"Constructor"、"Method" 和 "Field" 都是 "AccessibleObject" 的子类。
eg:
//在VipCustomer中定义类静态常量PRI_NO=100
Field field = getVipCustomerClass().getDeclaredField("PRI_NO");
field.setAccessible(true);
Assert.assertEquals(100, field.get(null));
//私有构造方法
Constructor<VipCustomer> constructor = getVipCustomerClass().getDeclaredConstructor();
constructor.setAccessible(true);
VipCustomer customer = constructor.newInstance();
Assert.assertNull(customer.getCustomerNo());
Assert.assertNull(customer.getName());
Assert.assertNull(customer.getMobilePhone());
//调用私有类方法
Method method = getVipCustomerClass().getDeclaredMethod("doNothingByVipCustomer");
method.setAccessible(true);
method.invoke(null);
10.利用反射创建数组
数组是比较特殊的类型。
10.1) Array#newInstance(Class<?> componentType, int length),创建一维数组,eg:
//一维数组
Object array = Array.newInstance(String.class, 2);
Array.set(array, 0, "小ben马");
Array.set(array, 1, "xiaobenma");
Assert.assertEquals("小ben马", Array.get(array, 0));
Assert.assertEquals("xiaobenma", Array.get(array, 1));
10.2) Array#newInstance(Class<?> componentType, int... dimensions),创建多维数组,eg:
//多维数组
//String[2][1]
Object arrays = Array.newInstance(String.class, 2, 1);
Object array0 = Array.newInstance(String.class, 1);
Array.set(array0, 0, "小ben马");
Array.set(arrays, 0, array0);
Object array1 = Array.newInstance(String.class, 1);
Array.set(array1, 0, "xiaobenma");
Array.set(arrays, 1, array1);
Assert.assertEquals("小ben马", Array.get(Array.get(arrays, 0), 0));
Assert.assertEquals("xiaobenma", Array.get(Array.get(arrays, 1), 0));
10.3)Array#get(Object array, int index)
根据数组和相关索引获取对应的值
10.4)Array#set(Object array, int index, Object value)
根据索引和相关索引,设置对应的值
11.Modifier说明
通常在类中
- 定义构造方法格式: [修饰符列表] 类名([参数列表])。
- 定义变量的格式为: [修饰符列表] 返回类型 变量名称。
- 定义方法的格式为: [修饰符列表] 返回类型 方法名([参数列表])。
"Member#getModifiers()" 返回一个int类型,通过解释int的值,能获取定义的修饰符列表。"Constructor"、"Method" 和 "Field" 都是 "Member" 的实现类。
修饰符返回的int值,需要通过 "Modifier" 解析。
其中,
- Modifier#toString(int mod): 打印定义的所有修饰符
- Modifier#isXXX(int mod): 判断修饰符的类型
如果你看过Modifier的源码,你会发现一个有趣的事情,修饰符是按bit位定义的,如:
/**
* The {@code int} value representing the {@code public}
* modifier.
*/
public static final int PUBLIC = 0x00000001;
/**
* The {@code int} value representing the {@code private}
* modifier.
*/
public static final int PRIVATE = 0x00000002;
/**
* The {@code int} value representing the {@code protected}
* modifier.
*/
public static final int PROTECTED = 0x00000004;
ps说明
- 反射相关包
java.lang.reflect Proxy是反射中比较重要的应用,在后续博客单独更新。- 相关demo代码 core-java-learning
java Reflection(反射)基础知识讲解的更多相关文章
- Java Reflection 反射基础
反射基础: package reflection; /** * Created by : Infaraway * DATE : 2017/3/2 * Time : 23:06 * Funtion : ...
- Java的反射基础技术
今天本人给大家讲解一下Java的反射基础技术,如有不对的或者讲的不好的可以多多提出,我会进行相应的更改,先提前感谢提出意见的各位了!!! 什么是反射? 反射它是根据字节码文件可以反射出类的信息.字段. ...
- 第76节:Java中的基础知识
第76节:Java中的基础知识 设置环境,安装操作系统,安装备份,就是镜像,jdk配置环境,eclipse下载解压即可使用,下载tomcat 折佣动态代理解决网站的字符集编码问题 使用request. ...
- Java并发(基础知识)—— Executor框架及线程池
在Java并发(基础知识)—— 创建.运行以及停止一个线程中讲解了两种创建线程的方式:直接继承Thread类以及实现Runnable接口并赋给Thread,这两种创建线程的方式在线程比较少的时候是没有 ...
- Html基础知识讲解
Html基础知识讲解 <title>淄博汉企</title> </head> <body bgcolor="#66FFCC" topmar ...
- 【Java面试】基础知识篇
[Java面试]基础知识篇 Java基础知识总结,主要包括数据类型,string类,集合,线程,时间,正则,流,jdk5--8各个版本的新特性,等等.不足的地方,欢迎大家补充.源码分享见个人公告.Ja ...
- python基础知识讲解——@classmethod和@staticmethod的作用
python基础知识讲解——@classmethod和@staticmethod的作用 在类的成员函数中,可以添加@classmethod和@staticmethod修饰符,这两者有一定的差异,简单来 ...
- Java面试题-基础知识
参考文章:Java面试题-基础知识 基础能力 什么是值传递和引用传递 线程状态有哪些,它们之间是如何转换的 进程与线程的区别,进程间如何通讯,线程间如何通讯? HashMap的数据结构是什么?如何实现 ...
- JAVA核心技术I---JAVA基础知识(工具类Arrays和Collections类)
一:工具类 –不存储数据,而是在数据容器上,实现高效操作 • 排序 • 搜索 –Arrays类 –Collection类 二:Arrays类(处理数组) (一)基本方法 –排序:对数组排序, sort ...
随机推荐
- Unity SurfaceShader详解
声明:文章主要是总结手游开发的经验,只涉及到了前向渲染.未涉及延迟渲染. Unity的Surface Shader本质上就是VS/PS.只不过Unity经过精心设计,将shader划分为了几个关键部分 ...
- 虚拟环境vitualenv的使用
在使用 Python 开发的过程中,工程一多,难免会碰到不同的工程依赖不同版本的库的问题: 亦或者是在开发过程中不想让物理环境里充斥各种各样的库,引发未来的依赖灾难. 此时,我们需要对于不同的工程使用 ...
- UML--->活动图梳理
活动图梳理 活动图 概述 活动图是UML用于对系统的动态行为建模的另一种常用工具,它描述活动的顺序,展现从一个活动到另一个活动的控制流,常常用于描述业务过程和并行处理过程,活动图在本质上是一种流程图. ...
- Docker底层架构之联合文件系统
联合文件系统(UnionFS)是一种分层.轻量级并且高性能的文件系统,它支持对文件系统的 修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several di ...
- shiro中ecache-core版本引起的异常
ecache-core包版本不对引起的错误,将2.5.3换成2.4.5就好了 来源 WARN [RMI TCP Connection(3)-127.0.0.1] - Exception encount ...
- java基础算法(一):最大子序列和问题的多种算法思路
问题: /** * 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和,并顺序打印子序列. * 示例: * 输入: [-2,1,-3,4,-1,2,1 ...
- SpringMVC 参数映射与文件上传
handler参数映射: 接下来就是Spring的各个处理细节了,无论框架如何疯转其实我们处理请求的流程是不变的,设计到的操作也是固定的,举个例子,当我们要实现一个登陆功能时: 创建一个用于处理登录请 ...
- excel 2010 如何设置日期选择器
excel 中想输入很多的日期.如果每个日期都直接手动输入太过于繁琐,而且容易出错.想制作一个日期选择器,直接鼠标点选就可以了. 效果如下: 具体实现参考 http://wenku.baidu.com ...
- 新的起航从这里开始 Encantado!
大家好,我是一名DBA之前也在其它地方写过blog,但是可惜目前在greatwall之内都不能访问了. 如果有小伙伴可以在墙外访问的话 可以尝试着看看这个地址 https://liuleiit.wix ...
- 微信小程序开发技巧总结 (一)-- 数据传递和存储
结合自己在平时的开发中遇到的各种问题,和浏览各种问题的解决方案总结出一些自己在日常开发中常用的技巧和知点,希望各位不吝斧正. 1.短生命周期数据存储 以小程序启动到彻底关闭为周期的的数据建议存储在ap ...