Java语言中的反射机制:
在Java 运行时 环境中,对于任意一个类,能否知道这个类有哪些属性和方法?
对于任意一个对象,能否调用他的方法?这些答案是肯定的,这种动态获取类的信息,以及动态调用类的方法的功能来源于JAVA的反射。从而使java具有动态语言的特性。
JAVA反射机制主要提供了以下功能:
1.在运行时判断任意一个对象所属的类
2.在运行时构造任意一个类的对象
3.在运行时判断任意一个类所具有的成员变量和方法(通过反射甚至可以调用private方法)
4.在运行时调用任意一个对象的方法(*****注意:前提都是在运行时,而不是在编译时)
Java 反射相关的API简介:
位于java。lang。reflect包中
--Class类:代表一个类
--Filed类:代表类的成员变量
--Method类:代表类的方法
--Constructor类:代表类的构造方法
--Array类:提供了动态创建数组,以及访问数组的元素的静态方法。该类中的所有方法都是静态方法
反射机制的作用:
1,反编译:.class-->.java
2,通过反射机制访问java对象的属性,方法,构造方法等;
这样好像更容易理解一些,下边我们具体看怎么实现这些功能。
反射机制获取类有三种方法,我们来获取Employee类型:
//第一种方式:
Class c1 = Class.forName("Employee");
//第二种方式:
//java中每个类型都有class 属性.
Class c2 = Employee.class;
//第三种方式:
//java语言中任何一个java对象都有getClass 方法
Employeee = new Employee();
Class c3 = e.getClass(); //c3是运行时类 (e的运行时类是Employee)
创建对象:获取类以后我们来创建它的对象,利用newInstance:
Class c =Class.forName("Employee");
//创建此Class 对象所表示的类的一个新实例
Objecto = c.newInstance(); //调用了Employee的无参数构造方法.
实例:
本篇文章为在工作中使用Java反射的经验总结,也可以说是一些小技巧,以后学会新的小技巧,会不断更新。本文不准备讨论JAVA反射的机制,网上有很多,大家随便google一下就可以了。 在开始之前,我先定义一个测试类:
package com.zhushuai.domain;
public class Car {
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getMaxSpeed() {
return maxSpeed;
}
public void setMaxSpeed(int maxSpeed) {
this.maxSpeed = maxSpeed;
}
private String brand;
private String color;
private int maxSpeed;
public Car(){
}
public Car(String brand, String color, int maxSpeed) {
super();
this.brand = brand;
this.color = color;
this.maxSpeed = maxSpeed;
}
}
实现类:
package com.zhushuai.reflect;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectDemo {
/**
* @param args
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws InstantiationException
* @throws NoSuchMethodException
* @throws SecurityException
* @throws InvocationTargetException
* @throws IllegalArgumentException
*/
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException {
// TODO Auto-generated method stub
Class cl = Class.forName("com.zhushuai.domain.Car");
Object obj = cl.newInstance();
Method mSetBrand = cl.getDeclaredMethod("setBrand", String.class);
Method mGetBrand= cl.getDeclaredMethod("getBrand");
mSetBrand.invoke(obj, "Audi");
String brandStr = (String)mGetBrand.invoke(obj, null);
Method mSetcolor = cl.getDeclaredMethod("setColor", String.class);
Method mGetcolor = cl.getDeclaredMethod("getColor");
mSetcolor.invoke(obj, "red");
String colorStr = (String)mGetcolor.invoke(obj, null);
Method mSetMaxSpeed = cl.getDeclaredMethod("setMaxSpeed", int.class);
Method mGetMaxSpeed = cl.getDeclaredMethod("getMaxSpeed");
mSetMaxSpeed.invoke(obj, 360);
int maxSpeedStr = (Integer)mGetMaxSpeed.invoke(obj, null);
System.out.println("Brand:"+brandStr+"\n"+"Color"+colorStr+"\n"+"MaxSpeed"+maxSpeedStr);
}
}
结果:
总结技巧:
一、JAVA反射的常规使用步骤
反射调用一般分为4个步骤:
-
得到要调用类的class
- 创建要调用类的newinstance
-
得到要调用的类中的方法(Method)
-
方法调用(invoke)
二、方法调用中的参数类型
在方法调用中,参数类型必须正确,这里需要注意的是不能使用包装类替换基本类型,比如不能使用Integer.class代替int.class。
如我要调用Car的setMaxSpeed方法,下面的调用是正确的:
Method mSetMaxSpeed = cl.getDeclaredMethod("setMaxSpeed", int.class);
而如果我们用Integer.class替代int.class就会出错,如:
Method mSetMaxSpeed = cl.getDeclaredMethod("setMaxSpeed", Integer.class);
三、static方法的反射调用
static方法调用时,不必得到对象示例,如下:
Class cls = Class.forName("chb.test.reflect.Student");
Method staticMethod = cls.getDeclaredMethod("hi",int.class,String.class);
staticMethod.invoke(cls,20,"chb");//这里不需要newInstance
//staticMethod.invoke(cls.newInstance(),20,"chb");<pre></pre>
四、private的成员变量赋值
如果直接通过反射给类的private成员变量赋值,是不允许的,这时我们可以通过setAccessible方法解决。代码示例:
Class cls = Class.forName("chb.test.reflect.Student");
Object student = cls.newInstance();//得到一个实例
Field field = cls.getDeclaredField("age");
field.set(student, 10);
System.out.println(field.get(student));
运行如上代码,系统会报出如下异常:
java.lang.IllegalAccessException: Class chb.test.reflect.TestClass can not access a member of class chb.test.reflect.Student with modifiers "private"
解决方法:
Class cls = Class.forName("chb.test.reflect.Student");
Object student = cls.newInstance();
Field field = cls.getDeclaredField("age");
field.setAccessible(true);//设置允许访问
field.set(student, 10);
System.out.println(field.get(student));
其实,在某些场合下(类中有get,set方法),可以先反射调用set方法,再反射调用get方法达到如上效果,代码示例:
Class cls = Class.forName("chb.test.reflect.Student");
Object student = cls.newInstance();
Method setMethod = cls.getDeclaredMethod("setAge",Integer.class);
setMethod.invoke(student, 15);//调用set方法
Method getMethod = cls.getDeclaredMethod("getAge");
System.out.println(getMethod.invoke(student));//再调用get方法
参考文章: http://blog.csdn.net/hbcui1984/article/details/2719089#