java反射改变方法的返回值

java能在运行期间通过反射去改变方法的返回值么?

penweizgx
penweizgx 问题虽然没解决,还是结贴了
大约 6 年之前 回复

8个回答

如果这个值是类属性应该是可以改变的 因为反射是可以改变类属性的值 如果这个值是局部变量那应该是改变不了的
下面的是通过改变类属性来间接改变方法的返回值

public static void main(String[] args) throws Exception{
User u=new User();
u.setName("HH");
Class cla=User.class;
Method m=cla.getMethod("setName", String.class);
m.invoke(u, "美女");

    Method md=cla.getDeclaredMethod("getName",null);

    Object t=md.invoke(u, null);
    System.out.println(t);

}
penweizgx
penweizgx return true; 这里的true好像不能修改为我自定义的对象
大约 6 年之前 回复
iteye_11009
iteye_11009 javassist也是可以的 ClassPool cp = ClassPool.getDefault(); //获得类文件名 CtClass cc = cp.get("com.ms.xbox.halo.reach.For_test"); //获得要修改的方法名 CtMethod m = cc.getDeclaredMethod("output"); //这里是将返回结果改成true m.insertBefore("return true;"); cc.writeFile(); }
大约 6 年之前 回复
penweizgx
penweizgx 恰好就是你说的后面一种情况。用javassist有法解决么?
大约 6 年之前 回复

[code="java"]
运行期间改变只能是反射了,

其实你也可以考虑
继承该类通过其他方式改变返回类型


public X get(String property) {
if (allowNestedValues && NestedModelUtil.isNestedProperty(property)) {
return (X)NestedModelUtil.getNestedValue(this, property);
}
return map == null ? null : (X) map.get(property);
}

public Date getExpiredate() {
return get("expiredate");
}

public String getSubject() {
return get("subject");
}

[/code]

楼主,要实现改变方法的返回值,比如有一个方法
[code="java"]XX getXX() {
return XX;
}[/code]
这个时候,通过反射可以把这个XX的值改变了,实现改变返回值的效果。同时,如果你的代码是封闭成MBean的话,也可以通过JConsole,JMX远程连接改变这个MBean中的属性值,实现改变返加值的目的。

penweizgx
penweizgx 返回值是getXX()方法体中生成的。
大约 6 年之前 回复

可以了解一下SPRING的AOP就知道可以在运行时去改变方法的返回值了。

Java的反射机制个人理解,就是相当于通过代码的方式去动态改变一个对象的成员属性等,可能有点绕。

在Java代码中 一般我们可以实现实现一个对象的新建:

A a = new A();
a.setXXXX('asdf');

对于属性XXXX 是这样进行赋值的,那倘若,我们将成员的属性与对应的属性值通过配置的方式进行存储,如:
XXXX:public
YYYY:public2

那么我们对于这样一个对象的创建,赋值那就必须自己编写好多的if else 来操作,如:

if('XXXX'.equals("method")){
a.setXXXX('public');
}

if('YYYY'.equals('method')){
a.setYYYY('public2');
}

但是如果通过反射来实现的话,效果可以同样处理,但是实现起来就相对比较简单了

A a = Class.forName(A.class).netInstance();
field.setvalue(a,'XXXX');

这样就可以实现赋值操作,其中field 是从class A中获取出来的 DeclaredField对象

以上纯属个人理解,如有不正之处 还望多多意见 :D

penweizgx
penweizgx 问了一下好像不得行
大约 6 年之前 回复

返回类型不可以改变。要改变返回值话,如果返回的值可以通过改变对象的状态(代码执行的外部环境,或者对象的成员变量值)的话,如public int a(){return this.a;},直接改变状态即可。
如果不可以通过改变状态来改变,如public int a(){return 1;}只能通过其它办法来做,比如代理或拦截的方式来做。

可以通过动态代理来实现:
[code="java"]class DynamicProxy implements InvocationHandler{

   public Object invoke(Object obj, Method method, Object[] aobj) throws Throwable {  

//在这里改变返回值
}
}[/code]

[code="java"]package com.ljn.base;

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

/**

  • @author lijinnan
  • @date:2014-5-26
    */
    public class ChangeReturnValue {

    /**

    • @param args
      */
      public static void main(String[] args) {

      IOrder order = new Order(1);
      System.out.println(order.getPrice());
      IOrder proxyOrder = ProxyOrder.getProxyOrder(order);
      System.out.println(proxyOrder.getPrice());
      }

    static class ProxyOrder {

    public static IOrder getProxyOrder(final IOrder order) {  
        IOrder iOrder = (IOrder) Proxy.newProxyInstance(order.getClass().getClassLoader(),  
                                                          order.getClass().getInterfaces(),  
    
                                                          new InvocationHandler (){
            @Override
            public Object invoke(Object proxy, Method method, Object[] args)
                    throws Throwable {
    
                        if (method.getName().equals("getPrice")) {
                            return 2;
                        }
                        return method.invoke(order, args);
            }
        });  
       return iOrder;  
    } 
    

    }

    static interface IOrder {

    int getPrice();
    

    }

    static class Order implements IOrder {

    private int price;
    
    public Order(int price) {
        this.price = price;
    }
    
    @Override
    public int getPrice() {
        return price;
    }
    

    }

}
[/code]

bylijinnan
bylijinnan 如果你是面向接口就没问题啊,proxyOrder和order这两个类是实现了同样的接口,你后面的方法接收参数的列表应该是someMethod(IOrder order)
大约 6 年之前 回复
penweizgx
penweizgx 非常感谢你的关注。。如果不用代理能直接改变order.getPrice()方法的返回值么,因为我这是在拦截器中的一个环节,我将他改了之后还要抛给后面继续处理,用了代理后类都改变了后面的就不认识了
大约 6 年之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问