开发者

How do you access protected Java method in thirdparty library?

Assume that you must access a protected method of a Java object that you receive somewhere in your code. What is your solution?

I know o开发者_如何学Pythonne approach: You can employ reflection and call setAccessible(true) on the Method object.

Any other idea?


As per the Java access modifiers, besides extending the object (which you can't if you receive the object) is to access it from an object in the same package as the object you received. So your option is to create a wrapper class in the same package which retrieves the attribute via the protected method for you.


You can subclass the method, create a public method that calls the protected method and returns the result.

If you can't do that (if the class is final), then setAccessible is pretty much your only way.


One other option is to create a class that extends that 3rd party class that has the protected method that you are interested in.

public class ThirdPartyClass
{
   protected void foo(){}
}

and

public MyClass extends ThirdPartyClass
{

     public void callFoo()
     {
           foo();
     }

}


You can also extend the class, override the method, and make the overridden method be public. Then have it just call super.method().


The other way is to extend the Class (if possible) and get access to the protected method via inheritance. If you do not create the Object this is not possible, as you would need it at compile time and you would need to create the Object yourself.

A dodgy solution could be to use composition. So you create a class in the same package e.g. OtherObjectWrapper. As it's in the same package you could call the Object's protected method through a public API you expose. This is not recommended though, as you don't own the package which you are adding a Class too and you can make your code very brittle e.g.

package com.foo;

public class OtherObjectWrapper {
   private com.foo.OtherObject wrappedObject;

   public OtherObjectWrapper(com.foo.OtherObject wrappedObject) {
     this.wrappedObject = wrappedObject;
   }

   public void callTheProtectedMethod() {
     wrappedObject.callTheProtectedMethod();
   }
}

Consider what the the API designer thinking when they marked the method as protected? Maybe they didn't have a clue what they were doing and it should be public, or worse still, it should be package private or private outright. Or maybe they did and they determined only code in the same package or through inheritance should have access to the protected method. If it's protected it may well be for a reason, so be wary as you may tie your codes behaviour to behaviours which may change and break your code. Also look at who owns the third party Object and whether there is a better API for accessing the protected method's functionality.


If you can put the calling class in the same package you will have access to the method. This and inheriting from that class are the only non-reflective ways to access a protected method.


As already said, subclassing is normally the standard way to access that method. Other approaches (wrapper in same package, reflection) should generally not used, since if you can't extend the class (due to being final) there often are good reasons accessing that method is made hard.

If the library is of any decent quality you definitely shouldn't have to use any other means besides subclassing to access a protected method or not access that method at all.


If a class is not final, you can use an anonymous class to call its protected method:

new ClassWithProtectedMethod() {
    @Override
    protected void method() {
        super.method();
    }
}.method();

Note, making method() public is unnecessary (since the new anonymous class is in the same package).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜