Java Reflect/AOP 重写超类型私有方法

发布于 2024-10-07 16:35:47 字数 131 浏览 1 评论 0原文

Java 中是否有可能“重写”超类的私有方法?

我希望重写其方法的类是第三方类,因此我无法修改源代码。如果有某种方法可以反射性地在类上设置方法,那就太理想了。

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

Is it at all possible to "override" a private method of a super class in Java?

The class whose method I wish to override is a third party class so I cannot modify the source. It would be ideal if there were some way to reflectively set a method on a class.

Alternatively, if it is possible to intercept a private method of a third party class then this would be suitable.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

英雄似剑 2024-10-14 16:35:47

。您可以使用 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 方法的输出。

YES. You can do it with AspectJ. It is not a true override but result will be so.

Here your super class;

public class MySuperClass {

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

Create an interface which contains similar method;

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

Create an aspect that forces super class to implement that interface and add an around adviser to call it.

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;
}

Create your child class that extends super and implements that interface.

public class Overrider extends MySuperClass implements Content {

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

Now if you construct a Overrider object and invoke echo method, you will have an output of Overriders safeContent's method.

苄①跕圉湢 2024-10-14 16:35:47

是否有可能“重写”Java 中超类的私有方法?

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

Is it at all possible to "override" a private method of a super class in Java?

No

I don't think using Reflection there would be a tweak , it will break OOP there

迷雾森÷林ヴ 2024-10-14 16:35:47

您没有合法的方式来做到这一点。但我可以建议您以下解决方案。

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

You do not have a legal way to do this. But I can suggest you the following solutions.

  1. Do you really wish to override this method? Try to think about other solution.
  2. Java checks access permissions during compilation only. Are you surprised? I was surprised very much to find out this fact. So you can create skeleton of the third party class (even with empty implementations.). The interesting method should be protected instead of private. Now write your subclass and compile it against your stub. Then package only your subclass and try to run it with the "real" class. It should work. I have not tried this trick with inheritance but I have tried it when I had to access private method or field and it worked fine for me.
  3. Try to use dynamic proxy that wraps your class and changes its implementation. I do not know what are you doing exactly, so I am not sure you can really use this method. But I hope you can. If not go back to #1 or #2.
风和你 2024-10-14 16:35:47

是的,这是可能的,但你不应该这样做,因为它与 SOLID 之一相矛盾 原则。更确切地说,它违背了里氏替换原则

注意:
设 q(x) 是关于类型 T 的对象 x 可证明的属性。然后 q(y)
对于 S 类型的对象 y 应该是可证明的,其中 S 是 T 的子类型。

换句话说,私有方法是对象的属性,因此继承类型的对象必须具有相同的属性。方法的 throws 也是如此。

Java因此限制了它。

yes it's possible ,but you should not do it, because it contradicts one of the SOLID principles. More exactly it contradicts Liskov substitution principle.

Note:
Let q(x) be a property provable about objects x of type T. Then q(y)
should be provable for objects y of type S, where S is a subtype of T.

So in other words , private method is property of object, so your object of inherited type must have the same property. The same with throws for methods.

Java restricts it because of it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文