3

So I'm new to Java and would really like some suggestions here.

I have a jar XYZ.jar which I've added to my classpath. This XYZ.jar has some 4 classes namely A,B,C,D. There is a method in CLASS D namely private void METHOD P() which is being called by CLASSES A,B,C.

Now I have a class Main.java in my project which is having a method METHOD R().

Now I would like to override private void METHOD P() with METHOD R() present in my Main.java. One thing I can do is that, I can extend my Main class with CLASS D. But, I would then have to modify the methodnames in CLASSES A,B,C which I don't want to do as the said classes are inside the jar.

So, what I would like to know is whether there's a way to override a private method of a class present inside a jar without making any changes to the rest of the classes calling the method, present inside the jar.

Phillip
  • 437
  • 1
  • 5
  • 16

3 Answers3

1

Assuming your classes A, B and C expect a class D as their construction parameter:

class Main extends D {
    public static void Main(String[] args) {
        Main main = new Main();
        A a = new A(main);
        B b = new B(main);
        C c = new C(main);
    }

    public void R() { ... }

    public void P() {
        R();
    }
}

But this only works if D and it's method P() are not final, and your other classes don't instantiate D themself.

Another but expensive way would be to use PowerMockito to mock your method D.P() to use your Main.R(). But this shouldn't be used for production code

Lino
  • 19,604
  • 6
  • 47
  • 65
  • I made a mistake while writing my post. I forgot to mention that the Method P of the parent class is a private method and not public. Please take a look at my editted post – Phillip Mar 13 '19 at 08:04
1

If you want to override the method of class D in your Main class, there are two things you need to do:

  1. Make sure your Main extends D. If Main doesn't inherit D, it can't override it's methods
  2. Make sure the method in your Main class has the exact same signature as the method you are trying to override.

So, instead of having a method called R in your Main class, you should rename this to a method called P (since this is the one you are trying to override). Just to avoid mistakes, it's recommended to add the @Override. This will show you if you made any errors.

Now, in case you do need it to be called R (because this method has already been called by other methods/classes in your own code, you can do as Lino suggests:

public void R(/* parameters */) {
  P(/* parameters */);
}

@Override
public void P(/* parameters */ ) {
  // the overriden code
}

This mimics R to override P, but any changes in the signature of R, or in the code there-in, will contradict that.

EDIT: Or, a better approach:

public void R(/* parameters */) {
  // the overriden code
}

@Override
public void P(/* parameters */ ) {
  R(/* parameters */);
}
Stultuske
  • 9,296
  • 1
  • 25
  • 37
  • I'm really sorry. But I missed to mention that the `Access Modifier` of `METHOD P` `in CLASS D` is private and not public. Let me edit my post. Again really sorry – Phillip Mar 13 '19 at 08:00
  • OK. In that case, you can't override it at all. – Stultuske Mar 13 '19 at 08:05
  • Are there any other alternatives than actually making changes in the jar? – Phillip Mar 13 '19 at 08:09
  • @Phillip no. but: probably there is a reason why it is declared private, and why it was made impossible to alter/inherit it. – Stultuske Mar 13 '19 at 08:12
0

You can hide any class in your classpath if you provide a class with the same qualified name (package + class name). So if this is your setup:

Project
|- your.own.package
   |- Main.java

Classpath:
|-xjz.jar
    |- some.other.package
       |-A
       |-B
       |-C
       |-D

You can replace the complete class some.other.package.D by adding a class with the same qualified name to your project.

Project
|- your.own.package
   |- Main.java
|- some.other.package
   |- D.java
Classpath:
|-xjz.jar
    |- some.other.package
       |-A
       |-B
       |-C
       |-D

This works because your own code is always added to the begin of your classpath and the java interpreter looks for classes in your classpath in specification order.

The downside of this approach is, that you need to duplicate the code of the original D class that you don't want to modify. In your example, you would copy the code of the D class and make sure all method signatures are identical to avoid NoSuchMethodExceptions. Then you only change the P method like follows:

private void P(){
  Main.R();
}
Michael A. Schaffrath
  • 1,992
  • 1
  • 14
  • 23