オブジェクトがインターフェイスを実装しているかどうかをテストする


149

これはおそらく以前に尋ねられた可能性がありますが、クイック検索ではC#について尋ねられた同じ質問のみが表示されました。こちらをご覧ください。

基本的に私がやりたいことは、特定のオブジェクトが特定のインターフェースを実装しているかどうかを確認することです。

私は一種の解決策を見つけましたが、これはifまたはcaseステートメントで頻繁に使用するには十分ではなく、Javaに組み込みの解決策がないのではないかと思っていました。

public static Boolean implementsInterface(Object object, Class interf){
    for (Class c : object.getClass().getInterfaces()) {
        if (c.equals(interf)) {
            return true;
        }
    }
    return false;
}


編集:さて、あなたの答えをありがとう。特にダミアン・ポレットとノルドリンに対して、あなたは私にデザインを再考させたので、インターフェースのテストはもうしません。


3
キャストして、例外がスローされた場合は例外をキャッチしてみませんか(または、JavaにC#の "as"演算子に類似したものがある場合でも、nullの結果を確認してください)。私はJavaではなくC#コーダーなので、主にここで推測していますが、そのようなアプローチはどのOO言語でも可能だと思います。
ノルドリン2009

1
この場合、例外をスローすることは、パフォーマンスを気にする必要がない場合にのみ有効です。
Rafa

1
失礼ですが、デザインを再考するためのこれらの答えはどこにありますか?削除しても何だったの?@sebastiangeiger
ozanmuyes

1
@ozanmuyes申し訳ありません。4年以上Javaを書いていないので、残念ながら何をしたか思い出せません。
sebastiangeiger 2016年

回答:


191

instanceofオペレータはで仕事をするNullPointerException安全な方法。例えば:

 if ("" instanceof java.io.Serializable) {
     // it's true
 }

真をもたらす。以降:

 if (null instanceof AnyType) {
     // never reached
 }

はfalseを返します。instanceof演算子はnullセーフです(投稿したコードは安全ではありません)。

instanceofは、Class#isInstance(Object)の組み込みのコンパイル時安全な代替手段です。


5
ただし、instanceofはクラスリテラルでのみ機能します。したがって、OPの場合は使用できません
LordOfThePigs 2009

確かに、コンパイル時に安全です。そしてそれは組み込みの方法であり、それは質問(imho)の議論です
dfa '20 / 04/20

@LordOfThePigsいいえ、ありません。インターフェイスが実装されているかどうかもチェックします。
NimChimpsky 2014年

5
@NimChimpsky:あなたは私のポイントを誤解しました。クラスリテラルとは、ソースコード内MyClass.classなどMyInterface.classで何かを書く場合です。クラスリテラルは、クラス、インターフェイス、およびプリミティブ型を参照でき、対応するインスタンスをクラスクラスに返します。私のポイントは、OPがクラスリテラルを使用せず、代わりにClassクラスのインスタンスを使用していることです。残念ながら、instanceofキーワードの右側の演算子はClassクラスのインスタンスではなく、クラスリテラルでなければなりません。
LordOfThePigs 2014年

@dsdsdsdsdこの投稿以来、私はそれについて聞いたことも読んだこともありませんでしたが、Googleを調べたところ、Null Pointer Exceptionの略であることがわかりました。
ozanmuyes 2016年

42

これは行う必要があります:

public static boolean implementsInterface(Object object, Class interf){
    return interf.isInstance(object);
}

例えば、

 java.io.Serializable.class.isInstance("a test string")

はに評価されtrueます。


8

私は好むinstanceof

if (obj instanceof SomeType) { ... }

これはより一般的で読みやすいです SomeType.isInstance(obj)


5
これif (obj instanceof SomeType) { ... }は静的であり(つまり、実行時に変更できない)、SomeType.isInstance(obj)動的であることに注意してください。
Tomasz Bielaszewski 2013年


3

インターフェースをテストしたい場合:

public List<myType> getElement(Class<?> clazz) {
    List<myType> els = new ArrayList<myType>();
    for (myType e: this.elements.values()) {
        if (clazz.isAssignableFrom(e.getClass())) {
            els.add(e);
        }
    }
    return els;

}

clazzはインターフェースであり、myTypeはユーザーが定義したタイプであり、いくつかのインターフェースを実装できます。このコードでは、定義されたインターフェースを実装するタイプのみを取得します


1

私は今夜​​アンドロイドでこの問題を抱えていて、javadocソリューションを調べた後、javadocの説明だけでは足りない私のような人々のために、この実際に機能するソリューションを思いつきました。

これは、Android Javaを使用した実際のインターフェースを使用した実際の例です。AboutDialogListenerフィールドをキャストする前に、呼び出されたアクティビティがAboutDialogListenerインターフェースを実装しているかどうかを確認します。

public class About extends DialogFragment implements OnClickListener,
    OnCheckedChangeListener {

public static final String FIRST_RUN_ABOUT = "com.gosylvester.bestrides.firstrunabout";


public interface AboutDialogListener {
    void onFinishEditDialog(Boolean _Checked);
}

private AboutDialogListener adl;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    Activity a = this.getActivity();
    if (AboutDialogListener.class.isInstance(a)) {
        adl = (AboutDialogListener) a;
        }
}

...後で、インターフェイスを呼び出す前に、フィールドadlが!nullかどうかを確認します

@Override
public void onStop() {
    super.onStop();
    sharedPref.edit().putBoolean(About.FIRST_RUN_ABOUT, _Checked).commit();
    // if there is an interface call it.
    if (adl != null) {
        adl.onFinishEditDialog(is_Checked());
    }
}

0

Apache commons-lang ArrayUtilsを使用して、必要なインターフェースがオブジェクトのインターフェースに含まれているかどうかを確認します

public static Boolean implementsInterface(Object object, Class interf){
    return ArrayUtils.contains(object.getClass().getInterfaces(), interf);
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.