Uji apakah objek mengimplementasikan antarmuka


149

Ini mungkin telah ditanyakan sebelumnya, tetapi pencarian cepat hanya memunculkan pertanyaan yang sama dengan C #. Lihat disini.

Apa yang saya ingin lakukan pada dasarnya adalah untuk memeriksa apakah objek yang diberikan mengimplementasikan antarmuka yang diberikan.

Saya agak menemukan solusi tetapi ini tidak cukup nyaman untuk menggunakannya sering dalam pernyataan if atau case dan saya bertanya-tanya apakah Jawa tidak memiliki solusi bawaan.

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


EDIT: Ok, terima kasih atas jawaban Anda. Khusus untuk Damien Pollet dan Noldorin, Anda membuat saya memikirkan kembali desain saya sehingga saya tidak menguji antarmuka lagi.


3
Tidak bisakah Anda mencoba casting dan menangkap pengecualian jika ada yang dilempar (atau memeriksa hasil nol bahkan, jika Jawa memiliki sesuatu yang analog dengan operator C # "sebagai")? Saya seorang C # coder daripada yang Java, jadi saya terutama hanya menebak-nebak di sini, meskipun saya akan berpikir pendekatan seperti itu akan mungkin dalam bahasa OO.
Noldorin

1
Melempar pengecualian adalah praktik yang baik dalam kasus ini hanya jika Anda tidak perlu peduli dengan kinerja.
Rafa

1
Maafkan saya, tetapi di mana jawaban itu membuat Anda memikirkan kembali desain Anda? Bahkan jika mereka dihapus, apakah itu? Bisakah Anda membantu saya @sebastiangeiger
ozanmuyes

1
@ozanmuyes Maaf, saya belum menulis Java lebih dari 4 tahun dan sayangnya saya tidak ingat apa yang saya lakukan.
sebastiangeiger

Jawaban:


191

The instanceofOperator melakukan pekerjaan dalam NullPointerExceptioncara yang aman. Sebagai contoh:

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

menghasilkan yang benar. Sejak:

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

menghasilkan false, instanceofoperator nol aman (kode yang Anda posting tidak).

instanceof adalah alternatif aman bawaan , waktu kompilasi untuk Kelas # isInstance (Objek)


5
instanceof hanya bekerja pada literal kelas. Jadi itu tidak dapat digunakan dalam kasus OP
LordOfThePigs

tentu, ini adalah waktu kompilasi yang aman; dan itu built-in cara dan itu adalah argumen dari pertanyaan (imho)
DFA

@ LordOfThePigs tidak, tidak. Ia memeriksa apakah suatu antarmuka diimplementasikan juga.
NimChimpsky

5
@NimChimpsky: Anda salah mengerti maksud saya. Literal kelas adalah ketika Anda menulis hal-hal seperti MyClass.classatau MyInterface.classdalam kode sumber Anda. Literal kelas dapat merujuk ke kelas, antarmuka dan tipe primitif, dan akan mengembalikan instance kelas Class yang sesuai. Maksud saya adalah OP tidak menggunakan literal kelas, tetapi turunan dari kelas Class sebagai gantinya, dan sayangnya operator sisi kanan instanceofkata kunci harus menjadi literal kelas, bukan turunan dari kelas Class.
LordOfThePigs

@dsdsdsdsd Sejak posting ini saya bahkan tidak mendengar / membacanya, tetapi setelah melihat ke Google, saya menemukan jawabannya adalah singkatan dari Null Pointer Exception.
ozanmuyes

42

Ini harus dilakukan:

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

Sebagai contoh,

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

mengevaluasi ke true.


8

Saya lebih suka instanceof:

if (obj instanceof SomeType) { ... }

yang jauh lebih umum dan mudah dibaca daripada SomeType.isInstance(obj)


5
Ingat itu if (obj instanceof SomeType) { ... }statis (artinya - tidak dapat berubah saat runtime) dan SomeType.isInstance(obj)dinamis.
Tomasz Bielaszewski


3

Jika Anda ingin menguji antarmuka:

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 adalah sebuah Antarmuka dan myType adalah Jenis yang Anda tetapkan yang dapat mengimplementasikan sejumlah antarmuka. Dengan kode ini Anda hanya mendapatkan tipe yang mengimplementasikan antarmuka yang ditentukan


1

Saya memiliki masalah ini malam ini dengan android dan setelah melihat solusi javadoc saya datang dengan solusi kerja nyata ini hanya untuk orang-orang seperti saya yang membutuhkan sedikit lebih dari penjelasan javadoc.

Berikut ini contoh yang berfungsi dengan antarmuka aktual menggunakan android java. Ia memeriksa aktivitas yang disebut mengimplementasikan antarmuka AboutDialogListener sebelum mencoba untuk melemparkan bidang 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;
        }
}

... Nanti saya periksa apakah field adl! Null sebelum memanggil antarmuka

@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

Dengan Apache commons-lang ArrayUtils, lihat apakah antarmuka yang Anda butuhkan terkandung dalam antarmuka objek Anda

public static Boolean implementsInterface(Object object, Class interf){
    return ArrayUtils.contains(object.getClass().getInterfaces(), interf);
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.