【问题标题】:Java Reflect/AOP override supertype private MethodJava Reflect/AOP 覆盖超类型私有方法
【发布时间】:2011-05-25 07:15:35
【问题描述】:

是否有可能在 Java 中“覆盖”超类的私有方法?

我希望覆盖其方法的类是第三方类,因此我无法修改源。如果有某种方法可以反射性地设置类上的方法,那将是理想的。

或者,如果可以拦截第三方类的私有方法,那么这将是合适的。

【问题讨论】:

  • 您可以通过使用字节码(反)汇编程序来更改字节码的可见性来做到这一点。呃,太恶心了!
  • 我认为你应该能够通过使用AOP的方法拦截器而不是将调用委托给普通proceed(),使用反射调用创建方法的方法它的实例并将setAccessible()设置为true

标签: java reflection aop


【解决方案1】:

是的。你可以用aspectj来做。这不是真正的覆盖,但结果会如此。

这里是你的超级类;

public class MySuperClass {

    private void content(String text) {
       System.out.print("I'm super " + text);
    }

    public void echo() {
       content("!");
    }        
}

创建一个包含类似方法的接口;

public interface Content {
    void safeContent(String text);
}

创建一个方面,强制超类实现该接口并添加一个环绕顾问来调用它。

public privileged aspect SuperClassAspect {

    void around(MySuperClass obj)
            : execution(* content(String)) && target(obj) {

        Object[] args = thisJoinPoint.getArgs();
        ((Content) obj).safeContent((String) args[0]);
    }

    // compiler requires
    public void MySuperClass.safeContent(String text) {}


    declare parents :MySuperClass implements Content;
}

创建扩展 super 并实现该接口的子类。

public class Overrider extends MySuperClass implements Content {

    public void safeContent(String text) {
        System.out.print("Not that super " + text);
    }
}

现在,如果您构造一个 Overrider 对象并调用 echo 方法,您将得到 Overriders safeContent 方法的输出。

【讨论】:

  • 该方法可行,但为什么不保持简单,只在MySuperClass+ 上使用around() 建议,拦截所需的调用或执行并返回适当修改的结果?我想这里可能没有必要使用 ITD。
  • 可以这样简化,但我的意思是让这感觉像是一种覆盖。
【解决方案2】:

您没有合法的方式来执行此操作。但我可以建议您以下解决方案。

  1. 您真的希望覆盖此方法吗?尝试考虑其他解决方案。
  2. Java 仅在编译期间检查访问权限。你惊喜吗?得知这个事实,我感到非常惊讶。所以你可以创建第三方类的骨架(即使是空的实现)。有趣的方法应该是protected 而不是private。现在编写您的子类并针对您的存根进行编译。然后只打包您的子类并尝试使用“真实”类运行它。它应该工作。我没有尝试过继承这个技巧,但是当我必须访问私有方法或字段时我已经尝试过了,它对我来说很好用。
  3. 尝试使用包装类并更改其实现的动态代理。我不知道你到底在做什么,所以我不确定你真的可以使用这种方法。但我希望你能。如果没有返回 #1 或 #2。
【解决方案3】:

是否有可能在 Java 中“覆盖”超类的私有方法?

我认为使用反射不会有任何调整,它会破坏OOP 那里

【讨论】:

    【解决方案4】:

    是的,这是可能的,但你不应该这样做,因为它违反了SOLID 原则之一。更确切地说,它与Liskov substitution principle 相矛盾。

    注意: 令 q(x) 是关于类型 T 的对象 x 的可证明性质。那么 q(y) 对于 S 类型的对象 y 应该是可证明的,其中 S 是 T 的子类型。

    也就是说,私有方法是对象的属性,所以你的继承类型的对象必须具有相同的属性。方法的 throws 也是如此。

    Java 因为它而限制它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-01
      • 2021-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-28
      相关资源
      最近更新 更多