什么是反射机制
反射机制是Java 5版本提供的高级新特性,这种机制允许Java程序在运行状态中,对任意一个类都能知道该类的所有属性和方法;对任意一个对象,都能调用该对象的属性和方法。这种动态获取信息及动态调用对象的属性和方法的功能称之为Java的反射机制。
在我们编写Java类文件时,真正运行的是编译之后的“.class”文件。而“.class”文件在运行时,被加载到内存后,都是一个Class类的对象。我们可以通过Java 5提供的反射机制获取到该类的构造器、方法及成员变量等。
简单来说,Java的反射机制中提供了Class类、Constructor、Method及Field等,Class类就是类的元神,Constructor就是构造器的元神,Method就是方法的元神,Field就是成员变量的元神。
反射中的Class类
Class类是Java 5提供一个新类型,就叫做类类型。如何可以获取一个Class类型的对象呢?传统方式就是利用new Class()方式,但Java 5提供不同的方式。参看以下代码:
public class Demo {
@Test
public void demo() throws ClassNotFoundException {
Class c1 = int.class;
Class c2 = int[].class;
Class c3 = "hello".getClass();
Class c4 = Class.forName("app.java.reflect.Demo");
}
}
通过以上代码我们可以了解,获取Class实例的方式有三种:
- 类名.class,例如:Class c1 = Object.class;
- 对象.getClass(),例如:Class c2 = “Hello”.getClass();
- Class.forName(“类全名”),例如:Class c1 = Class.forName(“app.java.reflect.Demo”);
获取到Class类实例之后,有什么具体用途呢?第一,我们可以通过Class类实例的getName()和getSimpleName()方法,获取到对应类的全类名或类名。
public class Demo {
@Test
public void demo() throws ClassNotFoundException {
Class c1 = "hello".getClass();
System.out.println(c1.getName());
Class c2 = int[].class;
System.out.println(c2.getName());
System.out.println(c2.getSimpleName());
}
}
第二,我们可以通过Class类实例的getSuperclass()方法,获取到对应类的完整继承链关系。
public class Demo {
@Test
public void demo() throws ClassNotFoundException {
Class c = java.awt.Frame.class;
while (c.getSuperclass() != null) {
System.out.println(c.getSuperclass().getName());
c = c.getSuperclass();
}
}
}
第三,我们可以通过反射机制来创建对象。
public class Demo {
@Test
public void demo() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
String className = "app.java.reflect.User";
Class c = Class.forName(className);
User user = (User) c.newInstance();
user.setUsername("king");
System.out.println(user.getUsername());
}
}
class User{
private String username;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
private String password;
}
反射中的Constructor
传统Java方式获取类的实例,基本都是通过构造器来实现,反射机制中的Class类同样具有构造器。那反射机制中Class类的构造器如何获得呢?我们来看以下代码:
public class Demo {
@Test
public void demo() throws Exception{
Class<User> c = User.class
// 获取c类型中所有public构造器
Constructor[] constructors1 = c.getConstructors()
// 获取c类型中所有构造器
Constructor[] constructors2 = c.getDeclaredConstructors()
System.out.println(constructors1.length)
System.out.println(constructors2.length)
// 获取没有参数的public构造器
Constructor con1 = c.getConstructor()
// 获取参数类型依次为String.class,String.class的public构造器
Constructor con2 = c.getConstructor(String.class,String.class)
// 获取参数类型为String.class的构造器
Constructor con3 = c.getDeclaredConstructor(String.class)
}
}
通过上面的代码,我们可以知道:在获取到Class类实例后,有四种方式可以获取到对应的构造器。
- getConstructors()方法:获取Class类所有的public构造器,其中包含没有参数和有参数的。
- getDeclaredConstructors()方法:获取Class类所有的构造器,其中包含由public、private和protected修饰符的。
- getConstructor()方法:获取具体的public修饰构造器,参数表示是否具有参数的构造器。
- getDeclaredConstructor()方法:获取具体的构造器,其中包含由public、private和protected修饰符的。
我们得到Class类型的构造器之后,又会有什么样的用途呢?第一,可以通过构造器来创建实例对象。
public class Demo {
@Test
public void demo() throws Exception{
Class<User> c = User.class;
Constructor<User> constructor = c.getConstructor(String.class,String.class);
User user = constructor.newInstance("king","123");
System.out.println(user);
}
}
第二,我们可以构造器来打印指定类型的所有构造器,以及参数类型。
public class Demo {
@Test
public void demo() throws Exception{
Class<String> c = String.class;
Constructor[] constructors = c.getDeclaredConstructors();
for (Constructor constructor : constructors) {
System.out.print(constructor.getDeclaringClass().getSimpleName() + "(");
Class[] classes = constructor.getParameterTypes();
for (int i = 0; i < classes.length; i++) {
System.out.print(classes[i].getSimpleName());
if (i < classes.length - 1) {
System.out.print(", ");
}
}
System.out.println(")");
}
}
}
反射中的Method
与Class类的构造器类似的就是方法,我们首先讨论如何获取方法。
public class Demo {
@Test
public void demo() throws Exception{
Class<User> c = User.class;
Method[] ms1 = c.getMethods();
System.out.println(ms1.length);
Method[] ms2 = c.getDeclaredMethods();
System.out.println(ms2.length);
Method m1 = c.getMethod("setUsername", String.class);
Method m2 = c.getDeclaredMethod("toString");
}
}
通过上面的代码,我们可以知道:在获取到Class类实例后,有四种方式可以获取到对应的方法。
- getMethods()方法:获取Class类及父类的所有public方法。
- getDeclaredMethods()方法:获取Class类的所有方法,其中包含由public、private修饰符的。
- getMethod()方法:获取Class类及父类中具体的public方法。
- getDeclaredMethod()方法:获取Class类中具体的方法,其中包含由public、private修饰符的。但不能是父类中的方法。
下面我们来看一个利用Class类实例方法的练习。
public class Demo {
@Test
public void demo() throws Exception{
Class<User> c = User.class;
Method method = c.getMethod("setUsername", String.class);
Object object = c.newInstance();
method.invoke(object, "king");
System.out.println(object);
}
}
反射中的Field
与Class类的构造器和方法类似的就是成员变量,我们首先讨论如何获取成员变量。
public class Demo {
@Test
public void demo() throws Exception{
Class<User> c = User.class;
Field[] fields1 = c.getFields();
System.out.println(fields1.length);
Field[] fields2 = c.getDeclaredFields();
System.out.println(fields2.length);
Field field1 = c.getField("password");
Field field2 = c.getDeclaredField("password");
}
}
通过上面的代码,我们可以知道:在获取到Class类实例后,有四种方式可以获取到对应的成员变量。
- getFields()方法:获取Class类及父类的所有public成员变量。
- getDeclaredFields()方法:获取Class类的所有成员变量,其中包含由public、private修饰符的。
- getField()方法:获取Class类及父类的具体成员变量。
- getDeclaredField()方法:获取Class类的具体成员变量,其中包含由public、private修饰符的。但不能是父类中的方法。
获取到Class类的成员变量之后,我们可以进行设置和获取操作。
public class Demo {
@Test
public void demo() throws Exception{
Class<User> c = User.class;
Field field = c.getField("password");
Object object = c.newInstance();
field.set(object, "123");
System.out.println(field.get(object));
}
}
需要注意的是这里只能设置和获取修饰符为public的成员变量,不能操作修饰符为private的成员变量。
AccessibleObject
AccessibleObject类是Constructor、Method和Field三个类的父类。AccessibleObject类的常用方法有以下几种:
- isAccessible()方法:判断当前成员是否可访问。
- setAccessible()方法:设置当前成员是否可访问。
当Class类中的构造器、方法和成员变量是私有的时候,如果我们想反射操作的话,就必须先调用setAccessible(true)方法。
public class Demo {
@Test
public void demo() throws Exception{
Class<User> c = User.class;
Field field = c.getDeclaredField("username");
Object object = c.newInstance();
field.setAccessible(true);
field.set(object, "king");
System.out.println(field.get(object));
}
}
转载说明:请注明作者及原文链接,谢谢!
<script type="text/javascript">
$(function () {
$('pre.prettyprint code').each(function () {
var lines = $(this).text().split('\n').length;
var $numbering = $('<ul/>').addClass('pre-numbering').hide();
$(this).addClass('has-numbering').parent().append($numbering);
for (i = 1; i <= lines; i++) {
$numbering.append($('<li/>').text(i));
};
$numbering.fadeIn(1700);
});
});
</script>
相关推荐
实现list不同泛型之间实体的互转,基于java8新特性+反射机制实现list不同实体类互转,将jdk8的流处理集合互转抽出来成一个工具类,实现lsit
反射本身并不是一个新概念,它可能会使我们联想到光学中的反射概念,尽管计算机科学赋予了反射概念新的含义,但是,从现象上来说,它们确实有某些相通之处,这些有助于我们的理解。在计算机科学领域,反射是指一类...
Java反射与JDK新特性
java多线程、反射、代理等基础知识详细介绍,通过此文档可快速进阶为中级工程师
该案例实现jdk1.5新特性:java注解和java反射机制加上jdbc API综合运用的一个案例,实现了数据库的简易封装,对想了解jdk的反射机制,注解有帮助
主要介绍了Java高级特性之反射的相关知识,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下
包含java三大高级特性的文档,《Java Reflection in Action》、《JAVA并发编程实战》、《JVM调优总结》、《深入理解Java虚拟机JVM高级特性与最佳实践》、《concurrent programming in java》,适合想深入java技术的...
候捷谈Java反射机制 有助深入理解Java新特性
着力让读者在充分理解Java语言和Java类库的基础上,灵活应用Java提供的高级特性,具体包括面向对象程序设计、反射与代理、接口与内部类、异常处理、泛型程序设计、集合框架、事件监听器模型、图形用户界面设计和...
反射本身是JAVA 语言的特性,使JAVA 语言有一种在运行时态自“自观”的能力。而 其他面向对象的语言却没有类似的功能。
泛型 --- 通用类型 由来 : java语言 开发者 一批C++ 工程师 ,在c++ 语法中 模板...JDK5 之前集合对象使用问题: 1、向集合添加任何类型对象 2、从集合取出对象时,数据类型丢失,使用与类型相关方法,强制类型转换
着力让读者在充分理解Java语言和Java类库的基础上,灵活应用Java提供的高级特性,具体包括面向对象程序设计、反射与代理、接口与内部类、异常处理、泛型程序设计、集合框架、事件监听器模型、图形用户界面设计和并发...
Java 的这一能力在实际应用中也许用得不是很多,但是在其它的程序设计语言中根本就不存在这一特性。例如,Pascal、C 或者 C++ 中就没有办法在程序中获得函数定义相关的信息。 JavaBean 是 reflection 的实际应用之...
以上的一些程序代码均为张老师课堂即兴发挥所写,也可以看出,张老师对JAVA特性的深刻理解能力!现在说说我对这些程序代码的理解,说实话,才开始听张老师讲的时候,我感觉很模糊的,但是当我真正理解了之后,觉得...
Reflection is commonly used by programs which require the ability to examine or modify the runtime behavior of applications running in the Java virtual machine. This is a relatively advanced feature ...
主要介绍了Java高级特性之反射机制,结合实例形式详细分析了Java反射机制原理、功能、使用方法及相关操作注意事项,需要的朋友可以参考下
·基于JDK 11,将Java8、Java9、Java10、Java11新特性一网打尽 ·课程中,Eclipse和IDEA这两种企业一线开发环境都使用到了 3.技术讲解更深入、更全面: ·课程共30天,715个知识视频小节,涉及主流Java使用的...
jdk1.5以上版本中新增加的特性描述,带有代码例子让你很清晰的明白jdk的 常量 、枚举、 for each、反射等各种新的特性,相信需要的你,一定满足。
主要介绍了Java反射技术详解及实例解析,反射可以说是Java中最强大的技术了,它可以做的事情太多太多,很多优秀的开源框架都是通过反射完成的。如果对JAVA感兴趣来可以学习一下
Java SE完整版精品优质课件 自学入门必看的优秀Java基础...第5章 高级类特性2 第6章 异常处理 第7章 Java集合 第8章 泛型 第9章 注解&枚举 第10章 IO 第11章 多线程 第12章 Java常用类 第13章 Java反射 第14章 网络编程