객체가 인터페이스를 구현하는지 테스트


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;
}


편집 : 좋아, 답변 주셔서 감사합니다. 특히 Damien Pollet과 Noldorin에게는 더 이상 인터페이스를 테스트하지 않도록 디자인을 다시 생각하게 만들었습니다.


3
예외가 발생하면 캐스팅을 시도하고 예외를 포착 할 수 있습니까 (또는 Java에 C # "as"연산자에 대한 분석이있는 경우에도 null 결과를 확인하십시오)? 저는 Java가 아닌 C # 코더이므로 주로 여기에서 추측하고 있지만 그러한 접근 방식은 모든 OO 언어에서 가능할 것이라고 생각합니다.
Noldorin

1
이 경우 성능에 신경 쓸 필요가없는 경우에만 예외를 던지는 것이 좋습니다.
라파

1
용서해주십시오.하지만 그 대답은 어디에서 디자인을 다시 생각하게합니까? 삭제 한 경우에도 무엇입니까? @sebastiangeiger
ozanmuyes

1
@ozanmuyes 죄송합니다. 4 년 이상 Java를 작성하지 않았으며 불행히도 내가 한 일을 기억할 수 없습니다.
sebastiangeiger

답변:


191

instanceof연산자는에서 작동합니까 NullPointerException안전한 방법입니다. 예를 들면 다음과 같습니다.

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

결과를 얻습니다. 이후:

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

결과는 false이며 instanceof연산자는 null 안전합니다 (게시 한 코드는 안전하지 않습니다).

instanceofClass # isInstance (Object)에 대한 내장 된 컴파일 타임 안전 대안입니다


5
instanceof는 클래스 리터럴에서만 작동합니다. 따라서 OP의 경우에는 사용할 수 없습니다
LordOfThePigs

물론 컴파일 타임 안전합니다. 그리고 그것은 빌트인 방식이며 질문 (imho)의 논쟁입니다
dfa

@LordOfThePigs 아닙니다. 인터페이스가 구현되었는지 확인합니다.
NimChimpsky

5
@ NimChimpsky : 당신은 내 요점을 오해했습니다. 클래스 리터럴은 소스 코드 와 같이 MyClass.class또는 MyInterface.class소스 코드로 물건을 쓸 때 입니다. 클래스 리터럴은 클래스, 인터페이스 및 기본 유형을 참조 할 수 있으며 해당 클래스의 클래스 클래스를 리턴합니다. 내 요점은 OP가 클래스 리터럴을 사용하지 않고 대신 클래스 클래스의 인스턴스를 사용한다는 것입니다. 불행히도 instanceof키워드 의 오른쪽 연산자 는 클래스 클래스의 인스턴스가 아닌 클래스 리터럴이어야합니다.
LordOfThePigs

@dsdsdsdsd이 포스트 이후로 나는 그것에 대해 듣거나 읽지 못했지만 Google을 찾은 후 Null Pointer Exception의 약어임을 알았습니다.
ozanmuyes

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


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.