2011-06-20 122 views
2

假设您必须访问您在代码中某处收到的Java对象的受保护方法。你的解决方案是什么?如何访问第三方库中受保护的Java方法?

我知道一种方法:你可以在Method对象上使用反射并调用setAccessible(true)。

还有其他想法吗?其他

+0

你跟具有公布的API库的工作?如果是这样,请将该信息添加到该问题中;你会得到更好的帮助。 – Atreys

+0

这不是我第一次遇到这个问题,但如果你是好奇:Eclipse的插件调试,JDILocalVariable,getStackFrame。网址:http://www.docjar.com/docs/api/org/eclipse/jdt/internal/debug/core/model/JDILocalVariable.html –

回答

5

根据java access modifiers,除了扩展对象(如果您收到对象,您不能这样做),是要从与您收到的对象相同的包中的对象访问它。所以你的选择是在同一个包中创建一个包装类,它通过受保护的方法为你检索属性。

3

一种选择是创建一个扩展具有保护的方法,你感兴趣的是第三方类的类。

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

public MyClass extends ThirdPartyClass 
{ 

    public void callFoo() 
    { 
      foo(); 
    } 

} 
+1

考虑您收到的对象。你不能投射物体,对吗? –

+0

@salman你有在编译时访问第三方类? –

+0

它已经编译。 –

2

您还可以扩展类,重写该方法,并将重写的方法公开。然后让它只需调用super.method()。

+0

请考虑您收到该对象。你不能投射物体,对吗? –

+0

这是正确的。在这种情况下,反射是您唯一的选择。 –

4

您可以继承该方法,创建一个调用受保护方法并返回结果的公共方法。

如果你不能这样做(如果类是最终的),那么setAccessible几乎是你唯一的方法。

+0

考虑您收到的对象。你不能投射物体,对吗? –

+0

我假设你的意思是将它转换为另一种类型。不,您不能在运行时将对象类型(类)转换为另一种对象类型。你可以将它包装在另一个对象中,但保护访问的问题仍然存在。此外,如果您的对象是使用spring或hibernate或任何其他使用运行时代理的框架生成的,则无法保证反射也可以正常工作。目标代理将不包含代理类中未公开的任何方法。 – pap

3

另一种方法是扩展类(如果可能)并通过继承访问受保护的方法。如果你不创建对象,这是不可能的,因为你在编译时需要它,你需要自己创建对象。

一个可怕的解决方案可能是使用组合。所以你在同一个包里创建一个类,例如OtherObjectWrapper。由于它位于相同的包中,因此可以通过公开的API调用Object的受保护方法。不过,这并不推荐,因为您并不拥有您正在添加Class的软件包,您可能会使代码非常脆弱,例如

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设计者在将方法标记为受保护时的想法?也许他们不知道他们在做什么,应该是公开的,或者更糟的是,它应该是私人包装或私人包装。或者也许他们确实并且只确定了相同包中的代码,或者通过继承应该可以访问受保护的方法。如果它受到保护,它可能是有原因的,所以要保持警惕,因为你可能会将你的代码行为与可能改变和破坏你的代码的行为联系起来。还要看看谁拥有第三方对象以及是否有更好的API来访问受保护方法的功能。

+0

考虑您收到该对象。你不能投射物体,对吗? –

2

如果你可以把调用类放在同一个包中,你将有权访问该方法。 这个和从那个类继承的是访问被保护方法的唯一不反射的方法。

+0

请注意,调用类应该由与第三方类相同的类加载器加载,请参阅http://stackoverflow.com/questions/4060842 – axtavt

0

如前所述,子类化通常是访问该方法的标准方法。 其他方法(包装在同一个包中,反射)通常不应该使用,因为如果你不能扩展类(由于是最终的),通常很难有很好的理由访问这个方法。

如果库是什么像样的质量你绝对不应该使用任何其他手段,除了子类访问受保护的方法或者根本没有访问该方法。