反射(reflect)

1. Class对象

1.1 什么是Class对象

当JVM加载某个class文件的时候,会自动创建一个唯一的Class对象(注意:由同一个类加载器加载的class文件),这个Class对象包含了整个class类的信息(例如:类的名称、访问修饰符、字段、字段描述、方法等等一切信息)。当使用new关键字创建这个类的实例时,jvm都会使用这个Class对象来创建类的实例。

1.1 获取Class对象方式

方式 说明
Test.class 通过类名.class直接获取
t1.getClass() 通过对象的getClass()方法获取
Class.forName("...") 使用Class类的forName静态方法获取,参数给的是完整类名(包名+类名)

2. 反射

2.1 什么是反射

所谓的反射,是在程序运行时动态获得任何一个Class对象的成员信息(类信息、字段、构造方法、成员方法等),并且能在运行时依据某个Class对象创建当前类的实例。

2.2 Class常用API

方法 说明
newInstance() 创建类实例
getName() 获取类的完整类名
getSimpleName() 获取类的简单类名
getPackage() 获取类对应的包信息
getSuperclass() 获取父类的Class对象
getInterfaces() 获取实现的所有接口
getClassLoader() 获取当前类的类加载器
getConstructor(..) 获取公共且明确参数类型的构造方法
getDeclaredConstructor(..) 获取受保护且明确参数类型的构造方法
getConstructors() 获取所有公共的构造方法
getDeclaredConstructors() 获取所有(包括受保护)的构造方法
getField(..) 根据字段名称获取某一个公共的字段
getDeclaredField(..) 根据字段名称获取当前类某一个的字段(包括受保护的)
getFields() 获取所有公共的字段,包括继承自父类的公共字段
getDeclaredFields 获取当前类所有字段,包括受保护的(不包括继承父类的字段)
getMethod(..) 根据方法名以及参数类型获取一个公共的方法
getDeclaredMethod(..) 根据方法名以及参数类型获取当前类的一个受保护的方法
getMethods() 获取所有公共的方法(包括继承自父类的公共方法)
getDeclaredMethods() 获取当前类的所有方法,包括受保护的(不包括继承父类的方法)
isAnnotation() 此Class是否是一个注解
isAnnotationPresent(..) 当前Class时是否定义了某个注解
getAnnotation(..) 获取当前类上定义的某个注解
getAnnotations() 获取当前类上定义的所有注解
isEnum() 此Class是否是一个枚举
isArray() 此Class是否是一个数组类型
isInterface() 此Class是否是一个接口
... 其他API请参照官方文档
public class TestClass {

public static void main(String[] args) throws Exception{
Class<?> clazz = Class.forName("edu.nf.reflect.Users");
//通过Class对象来创建实例,当前类必须提供一个公开并且无参的构造方法
Users user = (Users) clazz.newInstance();
//获取类的完整类名
System.out.println(clazz.getName());
//获取类的简单类名
System.out.println(clazz.getSimpleName());
//获取类所在的包名
System.out.println(clazz.getPackage().getName());
//获取当前类的父类的Class
System.out.println(clazz.getSuperclass());
//获取当前类实现的所有接口
System.out.println(clazz.getInterfaces());
//获取加载这个类的类加载器
System.out.println(clazz.getClassLoader());
//获取公共并且参数类型为String的构造方法
clazz.getConstructor(String.class);
//获取私有并且参数为int类型的构造方法
clazz.getDeclaredConstructor(Integer.TYPE);
//获取所有公共的构造方法
Constructor[] consArray1 = clazz.getConstructors();
//获取所有构造方法,包括公共和是有的
Constructor[] consArray2 = clazz.getDeclaredConstructors();
//获取某一个公共的字段,参数指定字段的名字
Field f1 = clazz.getField("address");
System.out.println(f1.getName());
//获取某一个受保护的字段
Field f2 = clazz.getDeclaredField("tel");
System.out.println(f2.getName());
System.out.println("-----------------------");
//获取所有公共的字段,包括继承自父类的公共字段
Field[] fieldArray1 = clazz.getFields();
for (Field field : fieldArray1) {
System.out.println(field.getName());
}
System.out.println("-----------------------");
//获取所有字段,包括受保护的(不包括继承父类的字段)
Field[] fieldArray2 = clazz.getDeclaredFields();
for (Field field : fieldArray2) {
System.out.println(field.getName());
}
System.out.println("-----------------------");
//获取某一个公共的方法(第一个参数指定方法名,第二个参数指定方法参数的类型,这是一个可变参数,有多少个参数就要指定多少个类型)
Method m1 = clazz.getMethod("say", String.class);
System.out.println(m1.getName());
//获取某一个受保护的方法
Method m2 = clazz.getDeclaredMethod("call");
System.out.println(m2.getName());
System.out.println("-----------------------");
//获取所有公共的方法(包括继承自父类的公共方法)
Method[] methodArray1 = clazz.getMethods();
for (Method method : methodArray1) {
System.out.println(method.getName());
}
System.out.println("-----------------------");
//获取本类的所有方法,包括受保护的(不包括父类的方法)
Method[] methodArray2 = clazz.getDeclaredMethods();
for (Method method : methodArray2) {
System.out.println(method.getName());
}
}
}

2.3 Class对象中的成员

成员 说明
Constructor 用于描述类的构造方法
Field 用于描述类的字段
Method 用于描述类的方法
Parameter 用于描述方法或构造方法的参数信息

2.3.1 Constructor常用API

API 说明
getName() 获取当前构造方法的名称
getParameterCount() 获取构造方法的参数个数
getDeclaringClass() 获取声明此构造方法的Class类
setAccessible(..) 设置访问开关
newInstance(..) 使用当前的Constructor构建实例
... 其他API请参照官方文档
public class TestCons {
public static void main(String[] args) throws Exception{
//加载Users的class信息,并构建Class对象
Class<?> clazz = Class.forName("edu.nf.reflect.Users");
//通过class对象访问构造方法信息,
// 根据构造方法的参数类型获取某一个公共的构造方法
Constructor cons1 = clazz.getConstructor(int.class);
// 访问受保护的构造方法
Constructor cons2 = clazz.getDeclaredConstructor(int.class);
//构造方法的名称
System.out.println(cons1.getName());
//获取构造方法的参数个数
System.out.println(cons1.getParameterCount());
//获取定义这个构造方法的Class类
System.out.println(cons1.getDeclaringClass());
//通过构造方法来创建类的实例
//由于构这个造方法是私有的,因此必须强制打开访问开关
cons1.setAccessible(true);
//然后通过newInstance方法来创建类的实例,并传入构造方法所需的参数
Users user = (Users)cons1.newInstance(21);
//获取所有的构造方法(包括私有和公有的)
Constructor[] cons = clazz.getDeclaredConstructors();
for (Constructor con : cons) {
System.out.println("参数个数: "+con.getParameterCount());
}
}
}
 

2.3.2 Field常用API

API 说明
getType() 获取当前字段类型
getName() 获取当前字段名称
get(..) 获取当前字段的值
set(..) 给当前字段赋值
setAccessible(..) 设置访问开关
... 其他API请参照官方文档
public class TestField {

public static void main(String[] args) throws Exception{
Class<?> clazz = Class.forName("edu.nf.reflect.Users");
//创建类的实例
Object instance = clazz.newInstance();
//获取一个受保护的字段
Field f = clazz.getDeclaredField("tel");
//打开访问开关
f.setAccessible(true);
//给字段赋值(第一个参数指定当前类的实例,第二个参数是具体的值)
f.set(instance, "123456");
//取值(get方法的参数也是指定当前类的实例)
System.out.println(f.get(instance));
//获取字段的类型
System.out.println(f.getType());
//获取字段的名称
System.out.println(f.getName());
}
}

2.3.3 Method常用API

API 说明
getName() 获取当前方法名称
getReturnType() 获取当前方法的返回值
getParameterCount() 获取当前方法参数的个数
getParameters() 获取当前方法的参数对象
getParameterTypes() 获取当前方法的所有参数类型
setAccessible(..) 设置访问开关
invoke(..) 回调当前的method
... 其他API请参照官方文档
public class TestMethod {

public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("edu.nf.reflect.Users");
//构建当前类的实例
Object instance = clazz.newInstance();
//获取受保护的call方法
Method method = clazz.getDeclaredMethod("call", String.class);
//获取方法的名称
System.out.println(method.getName());
//获取方法的返回值类型
System.out.println(method.getReturnType());
//获取方法参数的个数
System.out.println(method.getParameterCount());
//获取方法的所有参数对象
System.out.println(method.getParameters());
//获取方法中所有参数的类型
Class<?>[] paramsType = method.getParameterTypes();
for (Class<?> aClass : paramsType) {
System.out.println(aClass);
}
//调用当前方法(第一个参数是当前类的实例,第二个参数开始是方法所需的参数)
//invoke方法返回的是当前调用的方法的返回值
//这个方法是受保护的,因此需要先打开访问开关
method.setAccessible(true);
Object returnValue = method.invoke(instance, "12345678");
System.out.println(returnValue);
}
}

2.3.4 Parameter常用API

API 说明
getType() 获取参数类型
getName() 获取参数的名称(说明:JDK8默认编译的时候是不会将参数名信息保存在字节码中,如果想要获取参数名,那么在编译时就需要加上编译参数 ,如:javac -parameters Users.java)
... 其他API请参照官方文档
public class TestParameter {

public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("edu.nf.reflect.Users");
//先获取指定的受保护的方法
Method callMethod = clazz.getDeclaredMethod("call", String.class);
//获取该方法的参数信息
Parameter[] params = callMethod.getParameters();
for (Parameter param : params) {
//获取参数的类型
System.out.println(param.getType());
//获取参数的名称(在JDK8之前是没有办法获取参数名的,必须通过第三方字节码工具来获取)
//JDK8默认编译的时候是不会讲参数名信息保存在字节码中
//如果想要获取参数名,那么在编译时就需要加上编译参数
//如:javac -parameters Users.java
System.out.println(param.getName());
}
}
}
 

java反射笔记的更多相关文章

  1. java反射笔记(学习尚硅谷java基础教程)

    反射一.概述:Reflection Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性 ...

  2. Java系列笔记(2) - Java RTTI和反射机制

    目录 前言 传统的RTTI 反射 反射的实现方式 反射的性能 反射与设计模式 前言 并不是所有的Class都能在编译时明确,因此在某些情况下需要在运行时再发现和确定类型信息(比如:基于构建编程,),这 ...

  3. 【设计模式】学习笔记17:代理模式之保护代理与Java反射

    本文出自   http://blog.csdn.net/shuangde800 本笔记内容: 1. Java动态代理,反射机制 2. 保护代理 3. 应用保护代理实现的约会系统 ----------- ...

  4. java反射的理解与应用(某大神博客中看到的博文,写的真的太好了,果断转载作为笔记)

    原文地址:http://www.cnblogs.com/jqyp/archive/2012/03/29/2423112.html#undefined 一.什么是反射机制 简单的来说,反射机制指的是程序 ...

  5. Java开发笔记(七十八)面向对象的后门——反射

    作为一门面向对象的编程语言,Java认为一切皆是对象,每个对象都能归属于某个类,甚至每个类均可提取出一种特殊的类型,即Class类型.早在前面介绍多态的时候,就提到每个类都存在独一无二的基因,通过比较 ...

  6. Java开发笔记(七十九)利用反射技术操作私有属性

    早在介绍多态的时候,曾经提到公鸡实例的性别属性可能被篡改为雌性,不过面向对象的三大特性包含了封装.继承和多态,只要把性别属性设置为private私有级别,也不提供setSex这样的性别修改方法,那么性 ...

  7. Java开发笔记(八十)利用反射技术操作私有方法

    前面介绍了如何利用反射技术读写私有属性,不单是私有属性,就连私有方法也能通过反射技术来调用.为了演示反射的逆天功能,首先给Chicken鸡类增加下列几个私有方法,简单起见弄来了set***/get** ...

  8. JAVA学习笔记—review基本知识[反射与异常]

    JAVA学习笔记—review基本知识[反射与异常] 1.异常: 1.1异常的分类: Java会将所有的异常封装成对象,其根本父类为Throwable. Throwable有两个子类:Error 和E ...

  9. Java注解和反射笔记

    Java注解和反射笔记 1 注解 1.1 定义 Annotation是从JDK1.5开始引入的技术 作用 不是程序本身,可以对程序作出解释 可以被其他程序(编译器等)读取 格式 @注释名,可以添加一些 ...

随机推荐

  1. 【转载】wifi的两种工作模式

    AP:即无线接入点,是一个无线网络的中心节点.通常使用的无线路由器就是一个AP,其它无线终端 可以通过AP相互连接. STA:即无线站点,是一个无线网络的终端.如笔记本电脑.PDA等. 1>工作 ...

  2. 视频人脸检测——Dlib版(六)

    往期目录 视频人脸检测--Dlib版(六) OpenCV添加中文(五) 图片人脸检测--Dlib版(四) 视频人脸检测--OpenCV版(三) 图片人脸检测--OpenCV版(二) OpenCV环境搭 ...

  3. 【前端框架系列】浅谈当前基于bootstrap框架的几种主流前端框架

    一  概述 当新开发一个项目或产品时,技术选型是一个不可缺少的环节,在软件架构中有着举足轻重的作用,可以这么说,技术选型的好坏直接影响项目或产品的成败优劣,因此,在进行软件架构时,一定要想好技术选型. ...

  4. 【SqlServer系列】远程访问

    1   概述 已发布[SqlServer系列]文章如下: [SqlServer系列]SQLSERVER安装教程 [SqlServer系列]数据库三大范式 [SqlServer系列]表单查询 [SqlS ...

  5. 网络协议抓包分析——ARP地址解析协议

    前言 计算机之间可以相互通信的前提是要知道对方的地址,才可以发送信息给其他计算机,就像别人要联系你也得先知道你的电话号码一样.这里的地址因为网络分层的原因就包括IP地址和MAC地址(即网卡地址.硬件地 ...

  6. SpringBoot(8) SpringBoot过滤器Filter

    1.SpringBoot启动默认加载的Filter characterEncodingFilter hiddenHttpMethodFilter httpPutFormContentFilter re ...

  7. 绝对路径的表示方式为什么是"/usr"而不是"//usr"

    今天闲逛贴吧,竟然看到有个人问绝对路径的表示方式为什么不是//usr/local而是/usr/local.原文: 我想99%的人都没想过这个问题,都理所当然的认为:它不就是根"/" ...

  8. TeamViewer 12\13\14 破解版(解决检测为商业用途的方式)

    一.Windows系统下破解TeamViewer的方式 1.用Windows直接卸载本地的TeamViewer软件2.下载一个Everything软件,并安装好它(这是一个搜索本机文件的工具,超级好用 ...

  9. LINUX sed grep awk之间比较整理

    正则表达式基础 在最简单的情况下,一个正则表达式看上去就是一个普通的查找串.例如,正则表达式"testing"中没有包含任何元字符,,它可以匹配"testing" ...

  10. Elasticsearch系列(2):安装Elasticsearch(Linux环境)

    系统环境 操作系统:CentOS 6.9 Elasticsearch:6.2.2 Filebeat:6.2.2(收集IIS日志) Kibana:6.2.2 Java:Java 8 注意:elk最好选择 ...