字节码操作可以在运行时更改Java方法的返回类型吗?

时间:2012-11-15 06:45:57

标签: java proxy javassist cglib bytecode-manipulation

我想知道是否可以通过字节码操作来做这样的事情:

public class Foo {
    public int getBlah() {
       return 1;
    }
}

public void hi(int x) {
    System.out.println("hi: " + x);
}

public void hi(String x) {
    System.out.println("wow: " + x);
}

现在我想打电话:

hi(foo.getBlah());

并为String参数调用重载hi方法。

3 个答案:

答案 0 :(得分:2)

您可以在hi(int x)处理标记值吗?如果是,你可以做这样的事情:

public void hi(int x) {
    if (x == Integer.MIN_VALUE) {
        String newParam = getTheParamFromProxySomehow();
        hi(newParam);
        return;
    }    
    System.out.println("hi: " + x);
}

基本上是:

  • 通过代理拦截getBlah()方法
  • 保存(在ThreadLocal中?)要传递给重载hi方法的任何String参数
  • 返回已标记的值,例如0-1Integer.MIN_VALUE
  • 执行上述技巧

它有点hacky,当你没有原语时看起来最好,所以你可以使用null作为标记值。希望有人有更好的答案。 :)

答案 1 :(得分:0)

即使您可以更改返回类型,也无法解决问题。编译器在编译时决定调用重载方法的实现。更改返回类型不会更改调用的方法。字节码仍会使用hi(int x)调用String方法,并可能导致错误。

答案 2 :(得分:0)

你的问题太宽泛了。但为了让你的想象力继续下去,请在my old blog about operation overload框架的帮助下查看Java中的ASM。这是一个小例子:

  BigInteger val = Evaluator.evaluate(new Evaluation() {
        public int evaluate(int x, int y) {
          return x - y;
        }
      }, new BigInteger("2"), new BigInteger("3"));