2011-06-20 6 views
2

コードのどこかで受け取ったJavaオブジェクトの保護されたメソッドにアクセスする必要があるとします。あなたの解決策は何ですか?Thirdpartyライブラリで保護されたJavaメソッドにどのようにアクセスしますか?

私はリフレクションを採用し、Methodオブジェクトに対してsetAccessible(true)を呼び出すことができます。

他のアイデアはありますか?

+0

公開されたAPIを持つライブラリを使用していますか?もしそうなら、その情報を質問に追加してください。あなたはより良い助けを得るでしょう。 – Atreys

+0

この問題が発生したのは初めてですが、興味深い場合はEclipse Debug Plugin、JDILocalVariable、getStackFrameです。 URL: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

あなたはまた、クラスを拡張することができますメソッドをオーバーライドし、オーバーライドされたメソッドをpublicにします。それから、super.method()を呼び出してください。

+0

オブジェクトを受け取ったとします。あなたはオブジェクトを投げることはできないのですか? –

+0

これは正しいです。その場合、反射があなたの唯一の選択肢です。 –

4

メソッドをサブクラス化し、保護されたメソッドを呼び出すパブリックメソッドを作成し、結果を返すことができます。

もしそれができないなら(クラスが最終的な場合)、setAccessibleはほとんどあなたの唯一の方法です。

+0

オブジェクトを受け取ったとします。あなたはオブジェクトを投げることはできないのですか? –

+0

別のタイプに変換することを意味すると思います。いいえ、実行時にオブジェクトタイプ(クラス)を別のオブジェクトタイプに変換することはできません。それを別のオブジェクトの中にラップすることはできますが、保護されたアクセスの問題は依然として残ります。また、あなたのオブジェクトがSpringやHibernate、またはランタイムプロキシを使用するその他のフレームワークを使って生成されている場合、リフレクションが動作するかどうかは保証されません。ターゲットプロキシには、プロキシされたクラスでは公開されていないメソッドは含まれません。 – pap

3

もう1つの方法は、クラスを拡張し(可能な場合)、継承を介して保護されたメソッドにアクセスすることです。オブジェクトを作成しない場合、これは不可能です。コンパイル時に必要になるため、オブジェクトを自分で作成する必要があります。

ドッジーな解決策は、組成物を使用することができます。たとえば、同じパッケージにクラスを作成します。 OtherObjectWrapper。同じパッケージ内にあるので、公開する公開APIを介してObjectのprotectedメソッドを呼び出すことができます。あなたがクラスを追加しているパッケージを所有しておらず、コードを非常に脆くすることができるので、これはお勧めできません。

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

すでに述べたように、通常、サブクラス化はそのメソッドにアクセスするための標準的な方法です。 クラスを拡張することができない場合(最終的なものであるため)、そのメソッドへのアクセスが困難な理由がよくあるので、他のアプローチ(同じパッケージ内のラッパー、リフレクション)は一般的には使用しないでください。

ライブラリーが適切な品質のものであれば、保護されたメソッドにアクセスするためにサブクラス化するか、まったくそのメソッドにアクセスしない他の手段を使用する必要はありません。

関連する問題