本文主要围绕以下几个点来详解反射:
1、反射机制是什么?
2、反射机制能做什么?
3、Java中反射的API以及应用
1.反射机制是什么?
借用百度百科的定义:
反射机制是在运行状态中:
1、对于任意一个类,都能够知道这个类的所有属性和方法;
2、对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
之所以强调属性、方法,是因为属性、方法是开发者对于一个类最关注的两个部分。实际上通过反射,不仅仅可以获知类的属性、方法,还可以获知类的父类、接口、包等信息
至于反射的原理,不难,Java类加载机制中讲到了,一个类在加载的时候,会在内存中生成一个代表这个.class文件的java.lang.Class对象,.classs文件里面就包含了描述这个类的信息的一切内容。至于.class文件,是由Java编译器(注意是Java编译器,指的不仅仅是Javac)编译而来的,是编译原理的领域。
2. 反射机制能做什么?
下面第二个问题,反射机制能做什么?
反射机制主要提供了以下功能:
1. 在运行时判断任意一个对象所属的类;
2. 在运行时构造任意一个类的对象;
3. 在运行时判断任意一个类所具有的成员变量和方法;
4. 在运行时调用任意一个对象的方法;
5. 生成动态代理。
3.发射机制的API以及应用实例
Class类库与java.lang.reflect类库一起对反射机制提供了支持。
1.通过一个实例对象获取完整的包名和类名
@Test
public void test1(){
ReflectTest reflectTest = new ReflectTest();
System.out.println(reflectTest.getClass().getName());
}
/**output~
test.ReflectTest
*/
2.实例化class类对象
@Test
public void test2() throws ClassNotFoundException {
Class<?> class1 = null;
class1 = Class.forName("test.ReflectTest");
System.out.println("类名称是:"+class1);
}
/**output~
类名称是:class test.ReflectTest
*/
3.获取一个对象的父类与实现的接口
@Test
public void test3() throws ClassNotFoundException {
Class<?> clazz = null;
clazz = Class.forName("test.ReflectTest");
//获取父类
Class<?> parentClass = clazz.getSuperclass();
System.out.println("clazz的父类为:" + parentClass.getName());
// 获取所有的接口
Class<?> intes[] = clazz.getInterfaces();
System.out.println("clazz实现的接口有:");
for (int i = 0; i < intes.length; i++) {
System.out.println((i + 1) + ":" + intes[i].getName());
}
}
/**output~
clazz的父类为:java.lang.Object
clazz实现的接口有:
1:java.io.Serializable
*/
4.获取某一个类中全部构造函数 以及 实例化一个类对象
@Test
public void test4() throws Exception {
Class<?> class1 = null;
class1 = Class.forName("test.User");
// 第一种方法,实例化默认构造方法,调用set赋值
User user = (User) class1.newInstance();
user.setAge(23);
user.setName("LouLou");
System.out.println(user);
// 结果 User [age=20, name=Rollen]
// 第二种方法 取得全部的构造函数 使用构造函数赋值
Constructor<?> cons[] = class1.getConstructors();
// 查看每个构造方法需要的参数
for (int i = 0; i < cons.length; i++) {
Class<?> clazzs[] = cons[i].getParameterTypes();
System.out.print("cons[" + i + "] (");
for (int j = 0; j < clazzs.length; j++) {
if (j == clazzs.length - 1)
System.out.print(clazzs[j].getName());
else
System.out.print(clazzs[j].getName() + ", ");
}
System.out.println(")");
}
// 结果
// cons[0] (int, java.lang.String)
//cons[1] (java.lang.String)
//cons[2] ()
user = (User) cons[0].newInstance(23, "LouLou");
System.out.println(user);
// 结果 User [age=23, name=LouLou]
user = (User) cons[1].newInstance("LouLou");
System.out.println(user);
// 结果 User [age=0, name=LouLou]
}
//实体类
class User {
private int age;
private String name;
public User() {
super();
}
public User(String name) {
super();
this.name = name;
}
public User(int age, String name) {
super();
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User [age=" + age + ", name=" + name + "]";
}
}
5.获取某个类的全部属性
class Parent {
private Integer pf1=1;
protected Integer pf2=2;
public Integer pf3=3;
Integer pf4=4;
}
public class ReflectTest extends Parent implements Serializable{
private String field1="field1";
protected String field2="field2";
public String field3="field3";
String field4="field3";
@Test
public void test5() throws Exception {
Class<?> clazz = null;
clazz = Class.forName("test.ReflectTest");
System.out.println("===============本类属性===============");
Field[] field = clazz.getDeclaredFields();//获取本类的全部属性(不包括父类或则实现的接口)
for (int i = 0; i < field.length; i++) {
// 权限修饰符
int mo = field[i].getModifiers();
String priv = Modifier.toString(mo);
// 属性类型
Class<?> type = field[i].getType();
System.out.println(priv + " " + type.getName() + " " + field[i].getName() + ";");
}
System.out.println("==========本类或则实现的接口或者父类的public的属性==========");
// 取得实现的接口或者父类的属性
Field[] filed1 = clazz.getFields();
for (int j = 0; j < filed1.length; j++) {
// 权限修饰符
int mo = filed1[j].getModifiers();
String priv = Modifier.toString(mo);
// 属性类型
Class<?> type = filed1[j].getType();
System.out.println(priv + " " + type.getName() + " " + filed1[j].getName() + ";");
}
}
}
/**output~
===============本类属性===============
private java.lang.String field1;
protected java.lang.String field2;
public java.lang.String field3;
java.lang.String field4;
==========本类或则实现的接口或者父类的public的属性==========
public java.lang.String field3;
public java.lang.Integer pf3;
*/
从上面的运行结果可知:
Class.getDeclaredFields()方法放回的是当前类里面的所有属性。Class.getFields()返回的是当前类已及父类和实现的接口的所有public修饰的属性。
6.获取某个类的全部方法
private void testtttt(){
}
/**
* 获取某个类的全部方法
* @throws Exception
*/
@Test
public void test6() throws Exception {
Class<?> clazz = Class.forName("test.ReflectTest");
Method[] method = clazz.getMethods();//获取本类以及继承类\实现接口的所有public修饰的方法
//Method[] method = clazz.getDeclaredMethods();//只获取本类的所有方法
for(int i=0; i<method.length; i++){
int mod = method[i].getModifiers();
String modifier = Modifier.toString(mod);//获取方法修饰符
Class<?> returnType = method[i].getReturnType();//获取返回值类型
Class<?> [] para = method[i].getParameterTypes();//获取参数类型
System.out.print(modifier + " ");
System.out.print(returnType.getName() + " ");
System.out.print(method[i].getName() + " ");
System.out.print("(");
for (int j = 0; j < para.length; ++j) {
System.out.print(para[j].getName() + " " + "arg" + j);
if (j < para.length - 1) {
System.out.print(",");
}
}
Class<?> exce[] = method[i].getExceptionTypes();
if (exce.length > 0) {
System.out.print(") throws ");
for (int k = 0; k < exce.length; ++k) {
System.out.print(exce[k].getName() + " ");
if (k < exce.length - 1) {
System.out.print(",");
}
}
} else {
System.out.print(")");
}
System.out.println();
}
}
1)clazz.getMethods();//获取本类以及继承类\实现接口的所有public修饰的方法
//执行结果是:
可知,里面都是public修饰的方法,private修饰的testtttt()并没有打印出来;
2)clazz.getDeclaredMethods();//只获取本类的所有方法
//执行结果是:
本类的所有方法都被获取到了。
7.通过反射机制调用某个类的方法
public void reflect1() {
System.out.println("Java 反射机制 - 调用某个类的方法1.");
}
public void reflect2(int age, String name) {
System.out.println("Java 反射机制 - 调用某个类的方法2.");
System.out.println("age -> " + age + ". name -> " + name);
}
/**
* 通过反射机制调用某个类的方法
*/
@Test
public void test7() throws Exception{
Class<?> clazz = Class.forName("test.ReflectTest");
// 调用TestReflect类中的reflect1方法
Method method = clazz.getMethod("reflect1");
method.invoke(clazz.newInstance());
//output: Java 反射机制 - 调用某个类的方法1.
// 调用TestReflect的reflect2方法
method = clazz.getMethod("reflect2", int.class, String.class);
method.invoke(clazz.newInstance(), 20, "张三");
// Java 反射机制 - 调用某个类的方法2.
//output: age -> 20. name -> 张三
}
8.通过反射机制操作某个类的属性
private String proprety = null;
/**
* 通过反射机制操作某个类的属性
*/
@Test
public void test8() throws Exception{
Class<?> clazz = Class.forName("test.ReflectTest");
Object obj = clazz.newInstance();
// 可以直接对 private 的属性赋值
Field field = clazz.getDeclaredField("proprety");
field.setAccessible(true);
field.set(obj, "Java反射机制");
System.out.println("proprety="+field.get(obj));
}
所有源代码的github地址