java反射教程
什么是反射,为什么它是有用的,以及如何使用它?
1.什么是反射?
“反射通常是JVM中运行的程序需要检测和修改运行时程序的行为的一种能力。”这个概念通常与内省(Introspection)混淆。以下是这两个术语在维基百科中的定义:
- 内省是指计算机程序在运行时检查对象类型的一种能力,通常也可以称作运行时类型检查。
- 反射是指计算机程序在运行时可以访问、检测和修改它本身状态或行为的一种能力。
从他们的定义可以看出,内省是反射的一个子集。有些语言支持内省,但不支持反射,如C++。

内省例子:instanceof运算符用于确定一个对象是否属于一个特定的类。
Dog d = (Dog)obj;
d.bark();
}
反射例子:Class.forName()方法通过类或接口的名称(一个字符串和完全限定名)来返回对应Class的对象。forName方法会对类初始化。
Class<?> c = Class.forName("classpath.and.classname");
Object dog = c.newInstance();
Method m = c.getDeclaredMethod("bark", new Class<?>[0]);
m.invoke(dog);
在Java中,更关注于反射而非内省,因为你不能改变一个对象的结构。
2.为什么我们需要反射?
反射能够让我们:
- 运行时检测一个对象所属的类;
- 运行时构造一个类的对象;
- 运行时检测一个类的字段和方法;
- 运行时调用一个对象的任意方法;
- 修改构造函数、方法、字段的访问权限,AccessibleObject的setAccessible(boolean flag)方法;
- 等等
反射是框架中常用的方法。
例如,JUnit通过反射来查找标记为 @Test 注解的方法,并在运行单元测试时调用这些方法。
对于Web框架,产品开发人员在配置文件中定义接口和类的实现。通过使用反射,框架可以快速动态地初始化所需要的类。
例如,Spring框架使用bean的配置,如:
<property name="someField" value="someValue" />
</bean>
当Spring上下文处理<bean>元素时,将使用Class.forName(String)与参数"com.programcreek.Foo"来实例化类。然后,它会再次使用反射来得到<property>元素对应的setter方法并设置指定的值。
相同的机制也用于Servlet web applications:
<servlet-name>someServlet</servlet-name>
<servlet-class>com.programcreek.WhyReflectionServlet</servlet-class>
<servlet>
3.如何使用反射?
通过以下几个典型的小例子来学习如何使用反射。
例1:获取对象的类名称。
import java.lang.reflect.Method;
public class ReflectionHelloWorld {
public static void main(String[] args){
Foo f = new Foo();
System.out.println(f.getClass().getName());
}
}
class Foo {
public void print() {
System.out.println("abc");
}
}
输出:
例2:调用未知对象的方法。
对于下面的代码示例,假象一下对象的类型是未知的。通过使用反射,代码可以使用该对象,并找出对象有一个名为“print”的方法,然后调用它。
import java.lang.reflect.Method;
public class ReflectionHelloWorld {
public static void main(String[] args){
Foo f = new Foo();
Method method;
try {
method = f.getClass().getMethod("print", new Class<?>[0]);
method.invoke(f);
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Foo {
public void print() {
System.out.println("abc");
}
}
例3:从Class实例创建对象
public class ReflectionHelloWorld {
public static void main(String[] args){
//create instance of "Class"
Class<?> c = null;
try{
c=Class.forName("myreflection.Foo");
}catch(Exception e){
e.printStackTrace();
}
//create instance of "Foo"
Foo f = null;
try {
f = (Foo) c.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
f.print();
}
}
class Foo {
public void print() {
System.out.println("abc");
}
}
示例4:获取构造函数和创建实例。
import java.lang.reflect.Constructor;
public class ReflectionHelloWorld {
public static void main(String[] args){
//create instance of "Class"
Class<?> c = null;
try{
c=Class.forName("myreflection.Foo");
}catch(Exception e){
e.printStackTrace();
}
//create instance of "Foo"
Foo f1 = null;
Foo f2 = null;
//get all constructors
Constructor<?> cons[] = c.getConstructors();
try {
f1 = (Foo) cons[0].newInstance();
f2 = (Foo) cons[1].newInstance("abc");
} catch (Exception e) {
e.printStackTrace();
}
f1.print();
f2.print();
}
}
class Foo {
String s;
public Foo(){}
public Foo(String s){
this.s=s;
}
public void print() {
System.out.println(s);
}
}
abc
此外,你可以使用Class实例来获取该类实现的接口,父类,声明的字段等。
例5:通过反射来修改数组的大小。
import java.lang.reflect.Array;
public class ReflectionHelloWorld {
public static void main(String[] args) {
int[] intArray = { 1, 2, 3, 4, 5 };
int[] newIntArray = (int[]) changeArraySize(intArray, 10);
print(newIntArray);
String[] atr = { "a", "b", "c", "d", "e" };
String[] str1 = (String[]) changeArraySize(atr, 10);
print(str1);
}
// change array size
public static Object changeArraySize(Object obj, int len) {
Class<?> arr = obj.getClass().getComponentType();
Object newArray = Array.newInstance(arr, len);
//do array copy
int co = Array.getLength(obj);
System.arraycopy(obj, 0, newArray, 0, co);
return newArray;
}
// print
public static void print(Object obj) {
Class<?> c = obj.getClass();
if (!c.isArray()) {
return;
}
System.out.println("\nArray length: " + Array.getLength(obj));
for (int i = 0; i < Array.getLength(obj); i++) {
System.out.print(Array.get(obj, i) + " ");
}
}
}
输出:
1 2 3 4 5 0 0 0 0 0
Array length: 10
a b c d e null null null null null
总结
上面的代码示例仅仅展现了Java反射提供的非常小的一部分功能。阅读这些例子只能让你初识Java反射,你需要在Oracle的官网阅读相关文档来了解更多信息。
java反射教程的更多相关文章
- 超详细的java反射教程
看技术博客时,看到关于java反射的博文,写的非常好.猛击下面的地址,开始java反射之旅 中文翻译地址:http://ifeve.com/java-reflection/ 英文原版地址:http:/ ...
- 转:Java反射教程
原文来自于:http://www.importnew.com/9078.html 什么是反射?反射有什么用处? 1. 什么是反射? “反射(Reflection)能够让运行于JVM中的程序检测和修改运 ...
- 非常easy的JAVA反射教程
原创文章,转载请注明. 反射能够动态载入类,实例化对象,调用方法.如今以下面样例解说. 一.载入类. Class clazz = Class.forName("java.lang.Strin ...
- Java反射——引言
Java反射——引言 原文地址:http://tutorials.jenkov.com/java-reflection/index.html *By Jakob Jenkov Java的反射机制使得它 ...
- 【译】1. Java反射——引言
原文地址:http://tutorials.jenkov.com/java-reflection/index.html *By Jakob Jenkov Java的反射机制使得它可以在运行时检查类.接 ...
- java反射基础知识(三)
原文地址:http://tutorials.jenkov.com/java-reflection/index.html http://www.cnblogs.com/penghongwei/p/329 ...
- Java注解教程:自定义注解示例,利用反射进行解析
Java注解能够提供代码的相关信息,同时对于所注解的代码结构又没有直接影响.在这篇教程中,我们将学习Java注解,如何编写自定义注解,注解的使用,以及如何使用反射解析注解. 注解是Java 1.5引入 ...
- Java基础教程:反射基础
Java基础教程:反射基础 引入反射 反射是什么 能够动态分析类能力的程序称为反射. 反射是一种很强大且复杂的机制. Class类 在程序运行期间,Java运行时系统始终为所有对象维护一个被称为运行时 ...
- 8千字干货教程|java反射精讲
java反射机制精讲 目录 1. 反射机制的概念 2. 反射的基础Class类 3. 反射的用法 4. 反射的应用示例 作者简介:全栈学习笔记,一个正在努力的人 微信公众号:公众号日更,精彩美文每天推 ...
随机推荐
- Oracle下Update语句
Update更新 格式: update table _name(表名) set col_name(列名) =expr(表达式) where conti(条件) 案例1: update 语法可以用新值 ...
- ubuntu16.04下笔记本自带摄像头编译运行PTAM
ubuntu16.04下笔记本自带摄像头编译运行PTAM 转载请注明链接:https://i.cnblogs.com/EditPosts.aspx?postid=9014147 个人邮箱:feifan ...
- Oracle 的闪回技术 --flashback
SQL Fundamentals: 表的创建和管理 如何开启数据库闪回? SQL> shutdown immediate; ORA-01109: database not open Databa ...
- 【Maven学习】Nexus OSS私服仓库的备份与迁移
背景 在上一篇博客 [Maven学习]Nexus OSS私服仓库的安装和配置 中,我们已经在机房搭建好了新的Nexus OSS私服仓库.下面是两个版本的Nexus OSS私服仓库的对比图. 老的Nex ...
- Python isdigit() isalnum()
Python isdigit() 方法检测字符串是否只由数字组成. 返回值 如果字符串只包含数字则返回 True 否则返回 False. >>> choice = input(&qu ...
- centos linux系统日常管理3 服务管理ntsysv,chkconfig,系统日志rsyslog,last ,lastb ,exec,xargs,dmesg,screen,nohup,curl,ping ,telnet,traceroute ,dig ,nc,nmap,host,nethogs 第十六节课
centos linux系统日常管理3 服务管理ntsysv,chkconfig,系统日志rsyslog,last ,lastb ,exec,xargs,dmesg,screen,nohup,cur ...
- C#判断用户是手机访问还是PC访问
今天在做一个wap网站时,需要限制PC用户访问.网上找了很多资料,效果都不怎么理想.其实原理就是根据HTTP_USER_AGENT判断检查用户在用什么浏览器,再根据业务做相应的逻辑处理. 代码如下: ...
- java多线程(五)
Java 多线程同步 锁机制与synchronized 打个比方:一个object就像一个大房子,大门永远打开.房子里有很多房间(也就是方法).这些房间有上锁的(synchronized方法), 和不 ...
- ReactNative生成android平台的bundle文件命令
ReactNative生成android平台的bundle文件命令 2016年11月03日 23:23:28 阅读数:4869 注:如果assets文件没有正确生成,需要手机创建或授权 网上的其它的很 ...
- python: 随机选择
想从一个序列中随机抽取若干元素,或者想生成几个随机数. random 模块有大量的函数用来产生随机数和随机选择元素.比如,要想从一个序列中随机的抽取一个元素,可以使用random.choice() : ...