클래스가 Java에서 인터페이스를 구현하는지 확인


92

나는 Class물건이있다. Class객체가 나타내는 유형이 특정 인터페이스를 구현 하는지 확인하고 싶습니다 . 이것이 어떻게 성취 될 수 있을지 궁금합니다.

다음 코드가 있습니다. 기본적으로 지정된 패키지의 모든 클래스 배열을 가져옵니다. 그런 다음 배열을 살펴보고 인터페이스를 구현하는 Class 객체를지도에 추가하고 싶습니다. 문제는 isInstance()개체를 매개 변수로 사용하는 것입니다. 인터페이스를 인스턴스화 할 수 없습니다. 그래서 나는 이것에 약간의 손실이 있습니다. 어떤 아이디어?

Class[] classes = ClassUtils.getClasses(handlersPackage);
for(Class clazz : classes)
{
    if(clazz.isInstance(/*Some object*/)) //Need something in this if statement
    {
        retVal.put(clazz.getSimpleName(), clazz);
    }
}

답변:


215

다음을 사용해야합니다 isAssignableFrom.

if (YourInterface.class.isAssignableFrom(clazz)) {
    ...
}

프로젝트가 동일하면 작동합니다. 그러나 인터페이스 코드를 1 : 1로 복사하고 새 프로젝트와 jar를 만든 다음 해당 jar를 플러그인으로로드하려고하면 호출이 false를 반환합니다. Roddy가 게시 한 것처럼 이름을 비교 한 다음 "작동"합니다. 그러나 Java가 결국 호환성을 확인하는 방식으로 이것을 확인하는 방법을 모릅니다. 이름은 더러운 접근 방식입니다. 물론 프로젝트가 동일하다면 당신은 괜찮습니다. ................ 내가 잘못하고있는 것 같습니다. 플러그인 파일에 대한 URLClassLoader 인스턴스를 만들고 그렇게로드합니다. 다른 클래스 로더를 사용 해봐야 할 것 같습니다.
Dreamspace President

4
클래스 로딩 문제가 있습니다. 다른 클래스 로더를 사용하여 동일한 클래스를 두 번로드하면 두 Class인스턴스가 호환되지 않습니다. java.lang.ClassCastException: com.my.CustomClass cannot be cast to com.my.CustomClass유사하게 설명 할 수없는 오류를 볼 수 있습니다 .
Flavio

나는 지금까지 다양한 접근 방식을 시도해 보았고 결국 내가 가진 주요 문제 는 다음과 같았다. 내 플러그인과 메인 프로젝트의 인터페이스는 동일하지만 동일한 위치에 있지 않으므로 네임 스페이스 / 주소 다른 사람이었습니다. Btw., 나는 지금 사용하고있다 : myClassLoader = new URLClassLoader(new URL[] { candidateFile.toURI().toURL() }, LoadedPlugin.class.getClassLoader());and classToLoad = Class.forName("com.blablabla.plugin.Main", true, myClassLoader);and instance = (MyIntf) classToLoad.newInstance();Works like a charm.
Dreamspace President

17

아래 함수를 사용하여 구현 된 모든 인터페이스를 얻을 수 있습니다.

Class[] intfs = clazz.getInterfaces();

10

사용 class.getInterfaces()하고 인터페이스 클래스가 있는지 확인할 수 있습니다 .

Class someInterface; // the interface you want to check for 
Class x; // 
Class[] interfaces = x.getInterfaces();

for (Class i : interfaces) {
    if (i.toString().equals(someInterface.toString()) {
        // if this is true, the class implements the interface you're looking for
    }
}

이 접근 방식은 기술적으로 작동하지만 훨씬 간단하고 깔끔한 접근 방식은 isAssignableFromFlavio가 언급 한대로 사용 하는 것입니다.
jwj

예, 사실입니다. 귀하의 답변이 몇 번 이상 찬성되었으며 컨텍스트를 추가하는 것이 유용 할 것이라고 생각했습니다. 사용하는 isAssignableFrom것이 바람직 할 수 있지만 이름을보고 클래스가 구현하는 인터페이스 목록을 스캔해야하는 인스턴스가있을 수 있습니다.
jwj

이것은 실제로 작동하지 않습니다. getInterfaces ()는 클래스가 인터페이스를 직접 구현하는 경우에만 작동합니다. 수퍼 클래스가 인터페이스를 구현하거나 수퍼 인터페이스가이를 확장하는 경우 해당 인터페이스는 getInterfaces ()에 의해 반환되지 않습니다. 클래스가 구현하는 모든 인터페이스를 가져 오려면 모든 수퍼 클래스 및 인터페이스의 트리를 탐색해야합니다.
제임스 로퍼

하지만 그것은 질문이 아니 었습니다.
냉동 완두콩의 Roddy

1

".class"를 추가하여 인스턴스를 설정할 수도 있습니다.

Class[] classes = ClassUtils.getClasses(handlersPackage);
for(Class clazz : classes)
{
    if(Interface.class.isAssignableFrom(clazz))
    {
        retVal.put(clazz.getSimpleName(), clazz);
    }
}

2
이 접근 방식을 보는 사람은 Flavio의 대답을 고려하십시오. 이 예제의 코드는 즉각적으로 이해되지 않는 몇 가지 작업을 수행합니다. ClassUtilsJava의 일부가 아닙니다 (Guava 또는 Spring 및 기타 프레임 워크에 있음). Interface위에서 사용 된 용어 는 테스트중인 특정 인터페이스를 나타냅니다 ( 즉,이 문맥에서 Java 키워드가 아닙니다.)의 목적은 retVal어디에도 설명되거나 언급되지 않습니다.
jwj
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.