2011-06-20 120 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

如前所述,子類化通常是訪問該方法的標準方法。 其他方法(包裝在同一個包中,反射)通常不應該使用,因爲如果你不能擴展類(由於是最終的),通常很難有很好的理由訪問這個方法。

如果庫是什麼像樣的質量你絕對不應該使用任何其他手段,除了子類訪問受保護的方法或者根本沒有訪問該方法。