反射(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. Nginx内置模块简介

    经常编译Nginx的时候看到./configure后面跟着很多--with命令,虽然知道是添加模块,但一直也没有仔细去研究这些模块究竟是什么作用.本文会对常用的内置模块做个简单介绍,方便后续检索查看. ...

  2. 设置Firefox(火狐)浏览器的中文菜单/界面

    步骤一: 设置Firefox浏览器的中文菜单/界面.首先需要查一下正在使用的火狐版本号(小生使用的火狐版本是55.0.3).      步骤二: 下载对应版本的xpi中文插件 其次,访问下面的火狐官方 ...

  3. MFC控件第一讲.DC编程

    MFC控件第一讲.DC编程 一丶简介 什么是DC,DC有什么用. DC成为设备描述符表. DC的作用就是可以进行绘制. 比如我们的窗口都是绘制出来的.  DC可以简单理解为.没一个窗口程序都有一块内存 ...

  4. NET Core微服务之路:弹性和瞬态故障处理库Polly的介绍

    前言 上一节中我们介绍了Ocelot的常见使用配置,通过json配置文件,实现API网关的请求处理.和一个使用DownStream扩展下游中间件,来实现Http转RPC的简单实现,功能不算强大,但可以 ...

  5. shell编程基础(七): 处理文件命令sed与awk

    一.sed(以行为单位处理文件) sed意为流编辑器(Stream Editor),在Shell脚本和Makefile中作为过滤器使用非常普遍,也就是把前一个程序的输出引入sed的输入,经过一系列编辑 ...

  6. zepto的ready方法

    zepto中的ready函数是作为$.fn的一个方法,即作为一个zepto对象的方法 readyRE = /complete|loaded|interactive/; ready: function( ...

  7. zepto的构造器$

    在zepto中,通过$来构造对象 $ = function(selector, context){ return zepto.init(selector, context) } 由该函数,实际上,在调 ...

  8. Keras入门(一)搭建深度神经网络(DNN)解决多分类问题

    Keras介绍   Keras是一个开源的高层神经网络API,由纯Python编写而成,其后端可以基于Tensorflow.Theano.MXNet以及CNTK.Keras 为支持快速实验而生,能够把 ...

  9. eclipse项目导入之后,项目内无报错,项目头有红色叉号。

    解决方法:右击项目之后选择properties,先看buildpath是不是有不一样的地方需要改成自己用的jdk与tomcat 之后看是否是项目之前用的tomcat与自己的不一样,如图 再更改过之后问 ...

  10. Python_简单三级菜单制作

    一:制作要求 1.三级菜单 2.可依次选择进入各子菜单 3.所需新知识点:字典,列表 *本文通过三种方法完成,第一种:只使用循环,第二种:使用列表,第三种:使用字典 二:FlowChart流程图 与上 ...