ทดสอบว่าวัตถุใช้ส่วนต่อประสานหรือไม่


149

อาจมีการถามก่อนหน้านี้ แต่การค้นหาอย่างรวดเร็วนำมาซึ่งคำถามเดียวกันที่ถามถึง C # เท่านั้น ดูที่นี่

สิ่งที่ฉันต้องการทำคือการตรวจสอบว่าวัตถุที่กำหนดนั้นใช้ส่วนต่อประสานที่กำหนดหรือไม่

ฉันคิดวิธีแก้ปัญหา แต่มันก็ไม่สะดวกพอที่จะใช้มันบ่อยๆในกรณีที่งบหรือกรณีและฉันสงสัยว่า Java ไม่ได้มีวิธีการแก้ปัญหาในตัว

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


แก้ไข: ตกลงขอบคุณสำหรับคำตอบของคุณ โดยเฉพาะอย่างยิ่งกับ Damien Pollet และ Noldorin คุณทำให้ฉันคิดใหม่เกี่ยวกับการออกแบบดังนั้นฉันจึงไม่ทดสอบอินเทอร์เฟซอีกต่อไป


3
คุณไม่สามารถลองส่งและรับข้อยกเว้นหากมีการโยน (หรือตรวจสอบผลลัพธ์ที่เป็นโมฆะแม้ว่า Java จะมีสิ่งใดที่เทียบเคียงกับโอเปอร์เรเตอร์ C # "เป็น") ฉันเป็น C # coder แทนที่จะเป็น Java ดังนั้นฉันแค่คาดเดาที่นี่เป็นหลัก แต่ฉันคิดว่าวิธีการนี้จะเป็นไปได้ในภาษา OO ใด ๆ
Noldorin

1
ข้อยกเว้นการขว้างปาเป็นวิธีปฏิบัติที่ดีในกรณีนี้เฉพาะในกรณีที่คุณไม่ต้องกังวลเกี่ยวกับประสิทธิภาพ
Rafa

1
ให้อภัยฉัน แต่คำตอบเหล่านั้นทำให้คุณคิดการออกแบบของคุณอีกครั้ง แม้ว่าพวกเขาจะลบไปแล้วพวกมันคืออะไร? คุณช่วยฉันได้ที่ @sebastiangeiger
ozanmuyes

1
@ozanmuyes ฉันขอโทษฉันยังไม่ได้เขียน Java ภายใน 4 ปีและโชคไม่ดีที่ฉันจำสิ่งที่ฉันไม่ได้
sebastiangeiger

คำตอบ:


191

instanceofประกอบการทำงานในNullPointerExceptionวิธีที่ปลอดภัย ตัวอย่างเช่น:

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

ผลผลิตจริง ตั้งแต่:

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

ให้ผลเป็นเท็จตัวinstanceofดำเนินการไม่มีความปลอดภัย (รหัสที่คุณโพสต์ไม่ใช่)

instanceofเป็นทางเลือกที่ปลอดภัยในตัวเวลาคอมไพล์กับClass # isInstance (Object)


5
instanceof ใช้งานได้กับตัวอักษรของคลาสเท่านั้น ดังนั้นจึงไม่สามารถใช้ในกรณีของ OP ได้
LordOfThePigs

แน่นอนว่ามันปลอดภัยในการรวบรวม และมันก็เป็นตัวในทางและมันก็เป็นข้อโต้แย้งของคำถาม imho ()
DFA

@LordOfThePigs ไม่เป็นอย่างนั้น ตรวจสอบว่ามีการใช้อินเทอร์เฟซเช่นกัน
NimChimpsky

5
@NimChimpsky: คุณเข้าใจจุดของฉันผิด ตัวอักษรของคลาสคือเมื่อคุณเขียนสิ่งต่าง ๆ เช่นMyClass.classหรือMyInterface.classในซอร์สโค้ดของคุณ ตัวอักษรของคลาสสามารถอ้างถึงคลาสอินเทอร์เฟซและชนิดดั้งเดิมและจะส่งคืนอินสแตนซ์ที่เกี่ยวข้องของคลาส ประเด็นของฉันคือ OP ไม่ได้ใช้ตัวอักษรคลาส แต่เป็นอินสแตนซ์ของคลาส Class แทนและน่าเสียดายที่ผู้ดำเนินการทางด้านขวามือของinstanceofคำหลักต้องเป็นตัวอักษรของคลาสไม่ใช่อินสแตนซ์ของคลาส Class
LordOfThePigs

@dsdsdsdsd ตั้งแต่โพสต์นี้ฉันไม่เคยได้ยิน / อ่านเกี่ยวกับเรื่องนี้ แต่หลังจากค้นหาใน Google ฉันคิดว่ามันเป็นตัวย่อของ Null Pointer Exception
ozanmuyes


8

ฉันชอบinstanceof:

if (obj instanceof SomeType) { ... }

ซึ่งเป็นเรื่องธรรมดาและสามารถอ่านได้มากกว่า SomeType.isInstance(obj)


5
โปรดจำไว้ว่าif (obj instanceof SomeType) { ... }เป็นแบบคงที่ (นั่นคือ - มันไม่สามารถเปลี่ยนแปลงได้ในขณะทำงาน) และSomeType.isInstance(obj)เป็นแบบไดนามิก
Tomasz Bielaszewski


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

ฉันมีปัญหานี้คืนนี้กับ android และหลังจากดูโซลูชัน 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.