一.什么是java反射机制
了解什么是java反射机制,首选我们先了解一下动态语言这个概念,那么什么是动态语言呢?动态语言的定义“程序运行时,允许改变程序结构或者变量类型,这种语言称为动态语言”。
从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。
尽管在这样的定义与分类下Java不是动态语言,它却有着一个非常突出的动态相关机制:Reflection。这个字的意思是:反射、映像、倒影,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。
换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。
这种“看透”class的能力(the ability of the program to examine itself)被称为introspection(内省、内观、反省)。Reflection和introspection是常被并提的两个术语。
而JAVA反射机制就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。二.java反射机制的作用
每个java类运行时都在JVM里表现为一个class对象,可通过类名.class,类型.getClass(),Class.forName("类名")等方法获取class对象,通过反编译,将.class->.java.,并且通过反射机制访问java对象的属性,方法,构造方法等。
有时候换取一个类的属性,方法,构造方法不一定非要通过feflection,直接通过最原始的创建对象,获取属性,但是反射机制的存在大大增加了我们代码的灵活性。
三.反射机制的api
1.反射机制获取类有三种方法
//第一种方式:
Classc1 = Class.forName("Employee");
//第二种方式:
//java中每个类型都有class 属性.
Classc2 = Employee.class;
//第三种方式:
//java语言中任何一个java对象都有getClass 方法
Employeee = new Employee();
Classc3 = e.getClass(); //c3是运行时类 (e的运行时类是Employee)
2.获取类之后,创建对象
Class c =Class.forName("Employee");
//创建此Class 对象所表示的类的一个新实例
Objecto = c.newInstance(); //调用了Employee的无参数构造方法.
3.获取类中所有的构造方法,属性,方法
Class<?> classType = Class.forName("java.lang.String");
//返回class对象所对应的类或接口中,所声明的所有方法的数组(包括私有方法)
Method[] methods = classType.getDeclaredMethods();
//返回class对象所对应的类或接口中,所声明的所有属性(包括私有属性)
Field[] fields = classType.getDeclaredFields();
//返回class对象获得所有构造方法
Constructor[] constructors=classType.getConstructors();
方法关键字
含义 | |
getDeclaredMethods() | 获取所有的方法 |
getReturnType() | 获得方法的放回类型 |
getParameterTypes() | 获得方法的传入参数类型 |
getDeclaredMethod("方法名",参数类型.class,……) | 获得特定的方法 |
|
|
构造方法关键字 | 含义 |
getDeclaredConstructors() | 获取所有的构造方法 |
getDeclaredConstructor(参数类型.class,……) | 获取特定的构造方法 |
|
|
父类和父接口 | 含义 |
getSuperclass() | 获取某类的父类 |
getInterfaces() | 获取某类实现的接口 |
4.api测试
user类:
package com.tl.skyLine.model;
public class User{
private String id;
private String username;
private String password;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
测试类:
@Test
public void testReflecion() throws ClassNotFoundException {
// Class c1 = Class.forName("com.tl.skyLine.model.User");
// logger.info("-----c1-----" + c1);
Class c2 = User.class;
logger.info("-----c2-----" + c2);
//
// User u=new User();
// Class c3 = u.getClass();
// logger.info("-----u-----"+u);
// logger.info("-----c3-----"+c3);
//建议使用第二种方法
c2.getDeclaredMethods();
Method[] methods = c2.getDeclaredMethods();
Field[] fields = c2.getDeclaredFields();
Constructor[] constructors = c2.getConstructors();
for (Method m : methods) {
logger.info("-----methods-----" + m);
}
for (Field f : fields) {
logger.info("-----fields-----" + f);
}
for (Constructor c : constructors) {
logger.info("-----constructors-----" + c);
}
}
打印结果:
[INFO][2016-02-27 14:48:53] -----c2-----class com.tl.skyLine.model.User
[INFO][2016-02-27 14:48:53] -----methods-----public java.lang.String com.tl.skyLine.model.User.getId()
[INFO][2016-02-27 14:48:53] -----methods-----public void com.tl.skyLine.model.User.setUsername(java.lang.String)
[INFO][2016-02-27 14:48:53] -----methods-----public void com.tl.skyLine.model.User.setPassword(java.lang.String)
[INFO][2016-02-27 14:48:53] -----methods-----public java.lang.String com.tl.skyLine.model.User.getUsername()
[INFO][2016-02-27 14:48:53] -----methods-----public void com.tl.skyLine.model.User.setId(java.lang.String)
[INFO][2016-02-27 14:48:53] -----methods-----public java.lang.String com.tl.skyLine.model.User.getPassword()
[INFO][2016-02-27 14:48:53] -----fields-----private static final long com.tl.skyLine.model.User.serialVersionUID
[INFO][2016-02-27 14:48:53] -----fields-----private java.lang.String com.tl.skyLine.model.User.id
[INFO][2016-02-27 14:48:53] -----fields-----private java.lang.String com.tl.skyLine.model.User.username
[INFO][2016-02-27 14:48:53] -----fields-----private java.lang.String com.tl.skyLine.model.User.password
[INFO][2016-02-27 14:48:53] -----constructors-----public com.tl.skyLine.model.User()
Process finished with exit code 0
四.具体代码实例
package com.tl.skyLine.aspect;
import java.lang.reflect.Method;
/**
* Created by tl on 16/2/27.
*/
public class Temp {
public int add(int param1, int param2) {
return param1 + param2;
}
public String echo(String message) {
return "Hello: " + message;
}
public static void main(String[] args) throws Exception {
// 以前的常规执行手段
Temp temp = new Temp();
System.out.println("执行temp的add方法:" + temp.add(1, 2));
System.out.println("执行temp的echo方法:" + temp.echo("Tom"));
System.out.println("---------------------------");
// 通过反射的方式
// 第一步,获取Class对象
// 前面用的方法是:Class.forName()方法获取
// 这里用第二种方法,类名.class
Class<?> classType = Temp.class;
// 生成新的对象:用newInstance()方法
Object tobject = classType.newInstance();
System.out.println("tobject是Temp对象的实例吗:" + (tobject instanceof Temp)); // 输出true
// 通过反射调用方法
// 首先需要获得与该方法对应的Method对象
// 第一个参数是方法名,第二个参数是这个方法所需要的参数的Class对象的数组(也就是方法参数)
Method addMethod = classType.getMethod("add", new Class[]{int.class, int.class});
// 等同于:
// Method addMethod = classType.getMethod("add", int.class, int.class);
// 调用目标方法
Object result = addMethod.invoke(tobject, new Object[]{1, 2});
System.out.println("反射调用temp的add方法:" + result); // 此时result是Integer类型
//调用第二个方法
Method echoMethod = classType.getDeclaredMethod("echo", new Class[]{String.class});
Object result2 = echoMethod.invoke(tobject, new Object[]{"Tom"});
System.out.println("反射调用temp的echo方法:" + result2);
}
}
打印结果:
Connected to the target VM, address: '127.0.0.1:63034', transport: 'socket'
执行temp的add方法:3
执行temp的echo方法:Hello: Tom
---------------------------
tobject是Temp对象的实例吗:true
Disconnected from the target VM, address: '127.0.0.1:63034', transport: 'socket'
反射调用temp的add方法:3
反射调用temp的echo方法:Hello: Tom
Process finished with exit code 0