Java 反射的应用
在学习反射之前,让我们先了解“类(Class)”。“方法”、“属性”、“类”都是名词,那么相应的在Java中会有这样一些特殊的类:“方法类(Method类)”、“属性类(Field类)”、“构造器类(Constructor类)”、“类类(Class类)”。

如上所示,任何Java的类或接口都是Class类的一个实例。
反射就是Java自我管理这些(类,对象)的机制。
1) 反射的作用
- 可以通过反射机制发现对象的类型,发现类型的方法/属性/构造器
- 可以创建对象并访问任意对象方法和属性等
2) Class加载
类加载到内存:Java将磁盘类文件加载到内存中吗,为一个对象(实例),这个对象是Class的实例。
3) Class实例代表Java中类型
- 获得基本类型实例
- int.class
- long.class
- ...
- 获得类类型(Class)实例:
- 获得基本类型实例
Class cls = String.class;
Class cls = Class.forName("java.lang.String");
Class cls = "abc".getClass();
1.通过放射获得队形的类/属性/方法/构造器
【案例】反射演示_“发现”对象的类/属性/方法/构造器
- 版本01
package reflect; import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays; /**
* 反射演示
*/
public class Demo1 {
public static void main(String[] args) throws ClassNotFoundException {
reflect("s"); //java.lang.String
reflect(1); //java.lang.Integer
} /**
* 反射方法,用于发现
* obj 的类型是什么
* obj 有哪些属性
* obj 有哪些方法
* obj 有哪些构造器
* @param obj 表示被“反射”的对象,被用于“发现”的对象
*/
public static void reflect(Object obj) {
//1. getClass()
// 返回对象的类型,是Object类的方法
Class<?> cls = obj.getClass();
System.out.println("类:" + cls.getName());
//2. getDeclaredFields();
// 返回在类上获得声明的所有属性(字段)
Field[] fields = cls.getDeclaredFields();
System.out.println("属性:");
for(Field field : fields) {
System.out.println(
field.getType()+" :" + //属性类型
field.getName()); //属性名称
}
//3. getDeclaredMethods
// 返回在类上获得声明的所有方法
Method[] methods = cls.getDeclaredMethods();
System.out.println("方法:");
for(Method method : methods) {
System.out.print(method.getReturnType()+" ");
System.out.print(method.getName()+" ");
System.out.println(
Arrays.toString(method.getParameterTypes()));
}
//4. getDeclaredConstructors
// 返回在类上获得声明的所有构造器
Constructor[] constructors = cls.getDeclaredConstructors();
System.out.println("构造器:");
for(Constructor c : constructors) {
System.out.print(c.getName() + " ");
System.out.println(
Arrays.toString(c.getParameterTypes()));
}
} }
- 版本02
package reflect; import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays; /**
*反射演示
*/
public class Demo2 {
public static void main(String[] args) throws ClassNotFoundException {
reflect(new Foo()); //reflect.Foo
} /**
* 反射方法,用于发现
* obj 的类型是什么
* obj 有哪些属性
* obj 有哪些方法
* obj 有哪些构造器
* @param obj 表示被“反射”的对象,被用于“发现”的对象
*/
public static void reflect(Object obj) {
//1. getClass()
// 返回对象的类型,是Object类的方法
Class<?> cls = obj.getClass();
System.out.println("类:" + cls.getName());
//2. getDeclaredFields();
// 返回在类上获得声明的所有属性(字段)
Field[] fields = cls.getDeclaredFields();
System.out.println("属性:");
for(Field field : fields) {
System.out.println(
field.getType()+" :" + //属性类型
field.getName()); //属性名称
}
//3. getDeclaredMethods
// 返回在类上获得声明的所有方法
Method[] methods = cls.getDeclaredMethods();
System.out.println("方法:");
for(Method method : methods) {
System.out.print(method.getReturnType()+" ");
System.out.print(method.getName()+" ");
System.out.println(
Arrays.toString(method.getParameterTypes()));
}
//4. getDeclaredConstructors
// 返回在类上获得声明的所有构造器
Constructor[] constructors = cls.getDeclaredConstructors();
System.out.println("构造器:");
for(Constructor c : constructors) {
System.out.print(c.getName() + " ");
System.out.println(
Arrays.toString(c.getParameterTypes()));
}
} }
class Foo {
int a = 3;
public double add(int b, Double d) {
return a+b+d;
} }
结果:

Java是如何知道程序员开发程序的类、属性、方法的?通过反射技术(反射技术是Java底层JVM运行程序的机制)
如下所示,Eclipse开发工具的“代码提示”功能就是利用反射写的。

2.通过发射创建对象实例
【案例】反射演示_根据类名创建对象实例
package reflect; import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays; /**
*反射演示
*/
public class Demo3 {
public static void main(String[] args) throws Exception {
//执行create()方法前提是参数类有无参构造器
Object obj = create("reflect.Foo3");
reflect(obj);
reflect(create("java.lang.String"));
}
/**
* 任务1:根据“类名”创建对象实例
* @param className
* @return
*/
public static Object create(String className) {
try {
//1 加载类
//1.1 在classpath中查找对应的类
//1.2 采用“懒加载”方式装载到内存
Class cls = Class.forName(className);
//2 创建类实例
Object obj = cls.newInstance();
return obj;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("没搞定!", e);
}
} /**
* 反射方法,用于发现
* obj 的类型是什么
* obj 有哪些属性
* obj 有哪些方法
* obj 有哪些构造器
* @param obj 表示被“反射”的对象,被用于“发现”的对象
* @throws Exception
*/
public static void reflect(Object obj) throws Exception {
//1. getClass()
// 返回对象的类型,是Object类的方法
Class<?> cls = obj.getClass();
System.out.println("类:" + cls.getName());
//2. getDeclaredFields();
// 返回在类上获得声明的所有属性(字段)
Field[] fields = cls.getDeclaredFields();
System.out.println("属性:");
for(Field field : fields) {
System.out.println(
field.getType()+" :" + //属性类型
field.getName()); //属性名称
}
//3. getDeclaredMethods
// 返回在类上获得声明的所有方法
Method[] methods = cls.getDeclaredMethods();
for(Method method : methods) {
System.out.print(method.getReturnType()+" ");
System.out.print(method.getName()+" ");
System.out.println(
Arrays.toString(method.getParameterTypes()));
}
//4. getDeclaredConstructors
// 返回在类上获得声明的所有构造器
Constructor[] constructors = cls.getDeclaredConstructors();
System.out.println("构造器:");
for(Constructor c : constructors) {
System.out.print(c.getName() + " ");
System.out.println(
Arrays.toString(c.getParameterTypes()));
}
}
} class Foo3 {
int a = 3;
public double add(int b, Double d) {
return a+b+d;
}
}
注:
- Class.forName() 静态方法,可以利用类名在CLASSPATH中查找对应的类,并且装载到内存,返回这个“class”
- Class.forName() 加载类的过程采用“懒惰方式”
- “懒惰方式”,即检查发现如果已经加载了(内存中存在)就不再加载,直接返回已经加载的类,相当于“手工”去检查内存在是否已经加载某个类
- newInstance() 方法,会利用默认(无参数)构造器创建类实例(实例对象)
3.通过反射访问某对象的某属性
【案例】反射演示_访问某对象的某属性
package reflect; import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays; /**
*反射演示
*/
public class Demo4 {
public static void main(String[] args) throws Exception {
//执行create()方法前提是参数类有无参构造器
Object obj = create("reflect.Foo4");
System.out.println(getFieldValue(obj, "a"));
}
/**
* 任务1:根据“类名”创建对象实例
* @param className
* @return
*/
public static Object create(String className) {
try {
//1 加载类
//1.1 在classpath中查找对应的类
//1.2 采用“懒加载”方式装载到内存
Class cls = Class.forName(className);
//2 创建类实例
Object obj = cls.newInstance();
return obj;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("没搞定!", e);
}
}
/**
* 任务2:访问某对象的某属性
* @param obj
* @param fieldName
* @return
*/
public static Object getFieldValue(
Object obj, String fieldName) {
try {
//1. 反射出类型
Class cls = obj.getClass();
//2. 反射出类型字段
Field field = cls.getDeclaredField(fieldName);
//3. 在对象obj上读取field属性值
Object val = field.get(obj);
return val;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("没搞定!", e);
}
}
/**
* 反射方法,用于发现
* obj 的类型是什么
* obj 有哪些属性
* obj 有哪些方法
* obj 有哪些构造器
* @param obj 表示被“反射”的对象,被用于“发现”的对象
* @throws Exception
*/
public static void reflect(Object obj) throws Exception {
//1. getClass()
// 返回对象的类型,是Object类的方法
Class<?> cls = obj.getClass();
System.out.println("类:" + cls.getName());
//2. getDeclaredFields();
// 返回在类上获得声明的所有属性(字段)
Field[] fields = cls.getDeclaredFields();
System.out.println("属性:");
for(Field field : fields) {
System.out.println(
field.getType()+" :" + //属性类型
field.getName()); //属性名称
}
//3. getDeclaredMethods
// 返回在类上获得声明的所有方法
Method[] methods = cls.getDeclaredMethods();
for(Method method : methods) {
System.out.print(method.getReturnType()+" ");
System.out.print(method.getName()+" ");
System.out.println(
Arrays.toString(method.getParameterTypes()));
}
//4. getDeclaredConstructors
// 返回在类上获得声明的所有构造器
Constructor[] constructors = cls.getDeclaredConstructors();
System.out.println("构造器:");
for(Constructor c : constructors) {
System.out.print(c.getName() + " ");
System.out.println(
Arrays.toString(c.getParameterTypes()));
}
}
} class Foo4 {
int a = 3;
public double add(int b, Double d) {
return a+b+d;
}
}
注:
field.get(obj) 可以获得对象属性值
field.set(Object obj, Object value) 可以设置对象属性值
4.通过反射方位某对象的方法
【案例】反射演示_访问某对象的某方法
package reflect; import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays; /**
*反射演示
*/
public class Demo5 {
public static void main(String[] args) throws Exception {
//执行create()方法前提是参数类有无参构造器
Object obj = create("reflect.Foo5");
Object mObj = call(
obj, //obj
"add", //方法名
new Class[]{int.class, Double.class}, //参数类型
new Object[]{2, 3.5}); //参数
System.out.println(mObj);
}
/**
* 任务1:根据“类名”创建对象实例
* @param className
* @return
*/
public static Object create(String className) {
try {
//1 加载类
//1.1 在classpath中查找对应的类
//1.2 采用“懒加载”方式装载到内存
Class cls = Class.forName(className);
//2 创建类实例
Object obj = cls.newInstance();
return obj;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("没搞定!", e);
}
}
/**
* 任务2:访问某对象的某属性
* @param obj
* @param fieldName
* @return
*/
public static Object getFieldValue(
Object obj, String fieldName) {
try {
//1. 反射出类型
Class cls = obj.getClass();
//2. 反射出类型字段
Field field = cls.getDeclaredField(fieldName);
//3. 在对象obj上读取field属性值
Object val = field.get(obj);
return val;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("没搞定!", e);
}
} /**
* 任务3:访问某对象的某方法
* @param obj 被调用对象
* @param method 方法名
* @param paramTypes 方法参数类型列表
* @param params 方法调用参数列表
* @return 在对象obj上调用方法签名是(method,paramTypes)的方法,
* params是传递的参数,返回的是方法的结果,
* 如果无返回值,返回null
*/
public static Object call(
Object obj,
String method,
Class[] paramTypes,
Object[] params) {
try {
//1. 发现类型
Class cls = obj.getClass();
//2. 发现方法
Method m = cls.getDeclaredMethod(method, paramTypes);
//3. 在对象obj调用方法m,传递参数类别params
Object val = m.invoke(obj, params);
return val;
} catch(Exception e) {
throw new RuntimeException("错误了!", e);
}
} /**
* 反射方法,用于发现
* obj 的类型是什么
* obj 有哪些属性
* obj 有哪些方法
* obj 有哪些构造器
* @param obj 表示被“反射”的对象,被用于“发现”的对象
* @throws Exception
*/
public static void reflect(Object obj) throws Exception {
//1. getClass()
// 返回对象的类型,是Object类的方法
Class<?> cls = obj.getClass();
System.out.println("类:" + cls.getName());
//2. getDeclaredFields();
// 返回在类上获得声明的所有属性(字段)
Field[] fields = cls.getDeclaredFields();
System.out.println("属性:");
for(Field field : fields) {
System.out.println(
field.getType()+" :" + //属性类型
field.getName()); //属性名称
}
//3. getDeclaredMethods
// 返回在类上获得声明的所有方法
Method[] methods = cls.getDeclaredMethods();
for(Method method : methods) {
System.out.print(method.getReturnType()+" ");
System.out.print(method.getName()+" ");
System.out.println(
Arrays.toString(method.getParameterTypes()));
}
//4. getDeclaredConstructors
// 返回在类上获得声明的所有构造器
Constructor[] constructors = cls.getDeclaredConstructors();
System.out.println("构造器:");
for(Constructor c : constructors) {
System.out.print(c.getName() + " ");
System.out.println(
Arrays.toString(c.getParameterTypes()));
}
}
} class Foo5 {
int a = 3;
public double add(int b, Double d) {
return a+b+d;
}
}
注:
- 方法签名由方法名称与参数列表组成(没有返回值和访问控制符),被成为方法签名
- call 方法标识,调用任意对象的任意方法
- 调用无参方法时这样写:

PS:
getDeclaredMethod*()获取的是类自身声明的所有方法,包含public、protected和private方法。
getMethod*()获取的是类的所有共有方法,这就包括自身的所有public方法,和从基类继承的、从接口实现的所有public方法。
java.lang.reflect.Method.invoke(Object obj, Object... args) invoke第一个参数obj,如果电泳的方法是static方法,obj参数可以传null。
Java 反射的应用的更多相关文章
- 第28章 java反射机制
java反射机制 1.类加载机制 1.1.jvm和类 运行Java程序:java 带有main方法的类名 之后java会启动jvm,并加载字节码(字节码就是一个类在内存空间的状态) 当调用java命令 ...
- Java反射机制
Java反射机制 一:什么事反射机制 简单地说,就是程序运行时能够通过反射的到类的所有信息,只需要获得类名,方法名,属性名. 二:为什么要用反射: 静态编译:在编译时确定类型,绑定对象,即通过 ...
- java反射(基础了解)
package cn.itcast_01; /** *Person类 */ public class Person { /** 姓名 */ private String name; ...
- java基础知识(十一)java反射机制(上)
java.lang.Class类详解 java Class类详解 一.class类 Class类是java语言定义的特定类的实现,在java中每个类都有一个相应的Class对象,以便java程序运行时 ...
- java基础知识(十一)java反射机制(下)
1.什么是反射机制? java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象都能够调用他的属性和方法,这种动态获取属性和方法的功能称为java的反射机制. ...
- java反射学习之二万能EXCEL导出
一.EXCEL导出的实现过程 假设有一个对象的集合,现在需要将此集合内的所有对象导出到EXCEL中,对象有N个属性:那么我们实现的方式是这样的: 循环这个集合,在循环集合中某个对象的所有属性,将这个对 ...
- java反射学习之一反射机制概述
一.反射机制背景概述 1.反射(reflection)是java被视为动态语言的一个关键性质 2.反射机制指的是程序在运行时能获取任何类的内部所有信息 二.反射机制实现功能概述 1.只要给定类的全名, ...
- java反射 之 反射基础
一.反射 反射:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为 ...
- java反射 cglib asm相关资料
有篇文章对java反射的调用的效率做了测试,写的比较好.猛击下面地址 http://www.blogjava.net/stone2083/archive/2010/09/15/332065.html ...
- 超详细的java反射教程
看技术博客时,看到关于java反射的博文,写的非常好.猛击下面的地址,开始java反射之旅 中文翻译地址:http://ifeve.com/java-reflection/ 英文原版地址:http:/ ...
随机推荐
- 图解HTTPS协议加密解密全过程
我们都知道HTTPS能够加密信息,以免敏感信息被第三方获取.所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议. HTTPS简介 HTTPS其实是有两部分组成:HTTP + SSL ...
- _mysql.c(42) : fatal error C1083: Cannot open include file: 'config-win.h':问题的解决 mysql安装python
在win7下安装了Python后,想安装python-MySQL,使用pip安装出现如下问题: >pip install MySQL-python _mysql.c(42) : fatal er ...
- 20145212 《Java程序设计》第6周学习总结
20145212 <Java程序设计>第6周学习总结 学习内容总结 第十章 1.Java将输入/输出抽象化为串流.读取数据对象成为输入流,能向其写入的对象叫输出流. 我从网上找到了一个可以 ...
- Wget命令下载、备份博客
-np http://www.cnblogs.com/memory4young/p/ 参考资料: http://www.cnblogs.com/memory4young/p/wget-backup-b ...
- IM即时通讯
即时通讯,由于项目需求和不可抗力因素用的融云 当然我更倾向于用环信亲加等 使用融云遇到的那些坑: 1.集成时的坑: ,编译环境要求太高 项目中有很多旧的东西 达不到其标准 直接用最新版,出错, ...
- OpenGL瓶颈
在优化Erya3D引擎的过程中,遇到的瓶颈: 1. 字符串操作,避免逐个字符的比较,使用哈希码比较2. 贴图操作:切换绑定贴图.更改贴图参数3. 切换绑定GLSL程序4. Draw Call:http ...
- 在 Mac OS X 终端里使用 Solarized 配色方案
MacOS X 终端solarized配色 相信长期浸泡在终端和代码的小伙伴们都有一套自己喜爱的配色方案.以前一直在用简单.适合阅读的 Terminal.app 配色方案,换到 MacBook Pro ...
- 使用Xunit来进行单元测试
不管你爱与不爱,单元测试对于一个软件的长治久安还是必不可少的一环.在Visual Studio 2012后,VS中的测试浏览器也能与第三方的集成了,用起来还是非常方便的.目前在.Net框架下的测试工具 ...
- xml基础总结
可扩展的标记语言(eXtensible Markup Language) 优点:容易读懂:格式标准任何语言都内置了XML分析引擎,不用单独进行文件分析引擎的编写. 用普通二进制传输数据的缺点,解析方式 ...
- ubuntu系统下使用锐捷上网的方法——特快
1.点击右上方的有线连接: 2.点击编辑连接: 3.选择802.x的安全性分页: 4.勾选下面的单选框: 5.输入登陆账号(通常就是学号),密码(通常是身份证后六位),如果出现了一个“解锁密码环”的对 ...