java

[b]1.反射的概念[/b]
在原来传统观念里,我们是先创建对象,然后根据对象来调用其方法,但是反射机制颠覆了我们原来的观念,反射能直接对于一个未知的其信息的类(如动态装载进来的类)根据一系列的方法的调用得到该类的属性和方法。
[b]2.反射的具体实现[/b]
反射机制其实是用到了JAVA API中Reflection这个类,通过Reflection APIs我们可以取得任何一个已知名称的class的内部信息,包括限定符,接口,继承类等,因此在获得其方法或者属性也可以通过构造器直接改变它的方法和属性。另外,Java的反射机制的实现要借助于4个类:class,Constructor,Field,Method;其中class代表的是类对象,Constructor-类的构造器对象,Field-类的属性对象,Method-类的方法对象。通过这四个对象我们可以粗略的看到一个类的各个组成部分。具体代码如下:


package 反射代码;
/**
* 机动车接口定义
* @author a
*
*/
public interface IVehicle {

public void startMe();//启动

public int forward(int dins);//前进
//有多少油
public int getEnergy();

}
package 反射代码;

public class BMW implements IVehicle {
public static final String company="宝马公司";
public int energy;//能量

public BMW(){
this.energy=10;
}
public BMW(int energy){
this.energy=energy;
}
//启动
public void startMe() {
System.out.println("BMW启动....");

}
//前进
public int forward(int dins) {
energy-=dins/100;
System.out.println("BMW前进"+dins);
return energy;
}

//有多少能量
public int getEnergy() {

return this.energy;
}


}


package 反射代码;

import java.lang.reflect.Modifier;

public class ReflectionTest {
public static void main(String args[]) {
try {
// 1.载入类对象
Class c = Class.forName("反射代码.BMW");
// 2.调用默认无参构造器生成对象
Object object = c.newInstance();
// 传入对象进行反射操作
ReflectionTest.RegetClass(c);
} catch (Exception e) {
e.printStackTrace();
}
}

public static void RegetClass(Class c) {
String className = c.getName();
System.out.println("类的名字是: " + className);
// 得到类中的方法对象数组
java.lang.reflect.Method[] methods = c.getMethods();
// 得到类定义的构造器对象数组
java.lang.reflect.Constructor[] cons = c.getConstructors();
// 得到类定义的属性对象数组
java.lang.reflect.Field[] fields = c.getFields();
// 得到类的直接父类类对象
Class superClass = c.getSuperclass();
// 得到类所有实现的接口类对象数组
Class[] interfaces = c.getInterfaces();
// 具体得到其属性及方法还有继承类接口等的方法调用
ReflectionTest.printFiledInfo(fields);
ReflectionTest.printInterface(interfaces);
ReflectionTest.printMethodInfo(methods);
ReflectionTest.printSuper(superClass);
}

private static void printFiledInfo(java.lang.reflect.Field[] fields) {
System.out.println("共有属性:" + fields.length);
for (java.lang.reflect.Field f : fields) {
String fName = f.getName();
Class fType = f.getType();
System.out.println("属性类型是:" + fType);
// 得到属性的访问限定符
int mType = f.getModifiers();
// 判断是何种限定符
if (Modifier.isPublic(mType))
System.out.println(" public");
if (Modifier.isAbstract(mType))
System.out.println(" abstract");
if (Modifier.isFinal(mType))
System.out.println(" final");
}
}

private static void printInterface(Class[] interfaces) {
for (Class c : interfaces) {
System.out.println("接口名:" + c.getName());
Class[] cs = c.getInterfaces();
printInterface(cs);
}
}

private static void printSuper(Class superClass) {
System.out.println("接口名: " + superClass.getName());
Class ss = superClass.getSuperclass();
if (null != ss) {
printSuper(ss);
}

}

private static void printMethodInfo(java.lang.reflect.Method[] methods) {
for (java.lang.reflect.Method m : methods) {
int t = m.getModifiers();
System.out.println("限定符是: " + t);
String name = m.getName();
System.out.println("方法名是: " + name);
Class returnType = m.getReturnType();
System.out.println("返回值类型是: " + returnType.getName());
// 参数类型组....
Class ps[] = m.getParameterTypes();
// 异常类型组...
Class es[] = m.getExceptionTypes();
}
}
}




输出结果:
类的名字是: 反射代码.BMW
共有属性:2
属性类型是:class java.lang.String
public
final
属性类型是:int
public
接口名:反射代码.IVehicle
限定符是: 1
方法名是: startMe
返回值类型是: void
限定符是: 1
方法名是: forward
返回值类型是: int
限定符是: 1
方法名是: getEnergy
返回值类型是: int
限定符是: 273
方法名是: wait
返回值类型是: void
限定符是: 17
方法名是: wait
返回值类型是: void
限定符是: 17
方法名是: wait
返回值类型是: void
限定符是: 1
方法名是: equals
返回值类型是: boolean
限定符是: 1
方法名是: toString
返回值类型是: java.lang.String
限定符是: 257
方法名是: hashCode
返回值类型是: int
限定符是: 273
方法名是: getClass
返回值类型是: java.lang.Class
限定符是: 273
方法名是: notify
返回值类型是: void
限定符是: 273
方法名是: notifyAll
返回值类型是: void
接口名: java.lang.Object


利用反射机制,我们还可以实现在对象上调用方法,具体实现代码如下:



/**
* 调用对象的方法
* @param bmw:要调用的对象
* @param destName:要调用的对象的名字
* @param paraType:方法参数类型列表
*/
public static void invokeTest(BMW bmw,String destName,Class ...paraType){
try{
//得到对象所在的类
Class destClass = BMW.class;
//查询要调用的方法对象
Method destM=destClass.getMethod(destName, paraType);
if(null!=destM){
//调用方法,传入参数
Object obj= destM.invoke(destName, paraType);
System.out.println(destM+"调用结果是"+obj);
}
}catch(Exception ef){
ef.printStackTrace();
}
}



这样可以利用方法反过来调用对象.

[b]3.反射的应用范围[/b]
在运行时判定任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判定任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理,便于程序员进行操作。
IOC:
设计模式中IOC就是利用了这个反射机制,可以把IOC模式看做是工厂模式的升华,可以把IOC看作是一个大工厂,只不过这个大工厂里要生成的对象都是在XML文件中给出定义的,然后利用Java 的“反射”编程,根据XML中给出的类名动态装载生成相应的对象。从实现来看,IOC是把以前在工厂方法里写死的对象生成代码,改变为由XML文件来定义,也就是把工厂和对象生成这两者独立分隔开来,目的就是提高灵活性和可维护性。
AOP:
同样,反射机制还可以用于AOP代理模式,就只需修改代理类中的方法,而不必修改对象“原类”中的代码。因此代理类的构造显得尤为重要,InvocationHandler是代理实例的调用处理程序实现的接口每个代理实例都具有一个关联的调用处理程序,对代理实例调用方法时将对方法调用进行编码并将其指派到它的调用处理程序的invoke方法。因此以后客户端只需调用代理类来完成所需的工作,而不用直接接触源代码。
具体代码如下:

package 反射代码;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class DebugVehicleProxy implements InvocationHandler {
// 被代理的对象
private Object obj;

// 得到代理的对象
public static Object getProxy(Object obj) {
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj
.getClass().getInterfaces(), new DebugVehicleProxy(obj));
}

private DebugVehicleProxy(Object obj) {
this.obj = obj;
}

/**
* 实现InvocationHandler中的方法 被代理类调用时,实际上是通过这个方法调用的
*
* @param proxy:被调用方法的对象
* @param m:要调用的方法对象
* @param args:调用方法的参数列表
*/
public Object invoke(Object proxy, Method m, Object[] args)
throws Throwable {
Object result;
try {
System.out.println("debug advice begin:" + m.getName());
result = m.invoke(obj, args);// 调用实际对象的方法
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (Exception e) {
throw new RuntimeException("invocation:" + e.getMessage());
} finally {
System.out.println("debug advice finish:" + m.getName());
}

return result;
}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值