如何访问第三方库中受保护的Java方法?
假设您必须访问代码中某处收到的 Java 对象的受保护方法。你的解决方案是什么?
我知道一种方法:您可以使用反射并在 Method 对象上调用 setAccessible(true) 。
还有其他想法吗?
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 one approach: You can employ reflection and call setAccessible(true) on the Method object.
Any other idea?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
根据 Java 访问修饰符,除了扩展对象(如果您收到该对象,则不能)是从与您收到的对象位于同一包中的对象访问它。因此,您的选择是在同一包中创建一个包装类,它通过受保护的方法为您检索属性。
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.
您可以对该方法进行子类化,创建一个调用受保护方法并返回结果的公共方法。
如果你不能这样做(如果类是最终的),那么 setAccessible 几乎是你唯一的方法。
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.
and
您还可以扩展类、重写方法并使重写的方法成为公共方法。然后让它调用 super.method()。
You can also extend the class, override the method, and make the overridden method be public. Then have it just call super.method().
另一种方法是扩展类(如果可能)并通过继承访问受保护的方法。如果您不创建对象,这是不可能的,因为您在编译时需要它,并且需要自己创建对象。
一个狡猾的解决方案可能是使用组合。因此,您在同一包中创建一个类,例如 OtherObjectWrapper。由于它位于同一个包中,因此您可以通过公开的公共 API 调用对象的受保护方法。不过,不建议这样做,因为您也不拥有要添加类的包,并且您的代码可能会变得非常脆弱,例如,
考虑一下 API 设计者将方法标记为受保护时的想法?也许他们不知道自己在做什么,它应该是公开的,或者更糟糕的是,它应该是私有的或完全私有的。或者也许他们确实这样做了,并且他们确定只有同一包中或通过继承的代码才应该有权访问受保护的方法。如果它受到保护,很可能是有原因的,所以要小心,因为您可能会将代码行为与可能更改和破坏代码的行为联系起来。还要查看谁拥有第三方对象以及是否有更好的 API 来访问受保护方法的功能。
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.
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.
如果一个类不是final,你可以使用匿名类来调用它的受保护方法:
注意,没有必要将
method()
设为public(因为新的匿名类位于同一个包中)。If a class is not final, you can use an anonymous class to call its protected method:
Note, making
method()
public is unnecessary (since the new anonymous class is in the same package).