假设您必须访问代码中某处的Java对象的受保护方法。你的解决方案是什么?
我知道一种方法:您可以在Method对象上使用反射并调用setAccessible(true)。
还有其他想法吗?
答案 0 :(得分:5)
您可以对方法进行子类化,创建一个调用受保护方法的公共方法并返回结果。
如果你不能这样做(如果课程是最终的),那么setAccessible几乎是你唯一的方法。
答案 1 :(得分:5)
根据java access modifiers,除了扩展对象(如果接收到对象,则无法扩展)是从与您收到的对象相同的包中的对象访问它。所以你的选择是在同一个包中创建一个包装类,它会通过受保护的方法为你检索属性。
答案 2 :(得分:4)
另一个选择是创建一个类,该类扩展具有您感兴趣的受保护方法的第三方类。
public class ThirdPartyClass
{
protected void foo(){}
}
和
public MyClass extends ThirdPartyClass
{
public void callFoo()
{
foo();
}
}
答案 3 :(得分:4)
您还可以扩展类,重写方法,并使重写的方法成为公共方法。然后让它调用super.method()。
答案 4 :(得分:3)
另一种方法是扩展Class(如果可能)并通过继承访问受保护的方法。如果你不创建Object,这是不可能的,因为你需要在编译时需要它,你需要自己创建对象。
狡猾的解决方案可能是使用构图。所以你在同一个包中创建一个类,例如OtherObjectWrapper。因为它位于同一个包中,您可以通过公开的API调用Object的受保护方法。不建议这样做,因为您没有自己添加类的包,并且您可以使代码非常脆弱,例如。
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();
}
}
考虑API设计者在将方法标记为受保护时的想法?也许他们不知道他们在做什么,它应该是公开的,或者更糟糕的是,它应该是包私有或私有的。或者也许他们这样做了,他们确定只有相同包中的代码或通过继承才能访问受保护的方法。如果它受到保护可能是有原因的,所以要小心,因为你可能会将代码行为与可能改变和破坏代码的行为联系起来。另请查看谁拥有第三方Object以及是否有更好的API来访问受保护方法的功能。
答案 5 :(得分:2)
如果您可以将调用类放在同一个包中,则可以访问该方法。 这个和从该类继承是访问受保护方法的唯一非反射方式。
答案 6 :(得分:1)
如前所述,子类化通常是访问该方法的标准方法。 其他方法(同一个包中的包装,反射)通常不应该使用,因为如果你不能扩展类(由于是最终的),通常有很好的理由来访问该方法很难。
如果库具有任何不错的质量,除了子类化之外,您绝对不应该使用任何其他方法来访问受保护的方法或根本不访问该方法。
答案 7 :(得分:0)
如果某个类不是最终类,则可以使用匿名类来调用其受保护的方法:
new ClassWithProtectedMethod() {
@Override
protected void method() {
super.method();
}
}.method();
请注意,不必公开method()
(因为新的匿名类位于同一包中)。