Java Reflect/AOP override supertype private Method

2019-07-19 07:16发布

问题:

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.

回答1:

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



回答2:

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.



回答3:

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.


回答4:

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.