Java에서 클래스 오브젝트가 다른 클래스 오브젝트의 서브 클래스인지 확인하십시오.


197

Java의 리플렉션 API로 놀고 있고 일부 필드를 처리하려고합니다. 이제 필드 유형을 식별하는 데 어려움을 겪고 있습니다. 문자열은 쉽습니다 myField.getType().equals(String.class). 파생되지 않은 다른 클래스에도 동일하게 적용됩니다. 그러나 파생 클래스를 어떻게 확인합니까? 예를 LinkedList들어의 하위 클래스입니다 List. isSubclassOf(...)extends(...)방법을 찾을 수 없습니다 . 나는 모든 getSuperClass()것을 밟고 혼자서 내 상류층을 찾아야합니까?


11
LinkedList의 하위 클래스가 아닙니다 List. 의 구현 입니다 List.
TJ Crowder

2
하위 유형은 더 나은 용어 수 있습니다
jpaugh

답변:


403

이 방법을 원합니다 :

boolean isList = List.class.isAssignableFrom(myClass);

일반적으로, 여기서, List(전술)로 대체되어야 superclass하고 myClass교체해야subclass

로부터 의 JavaDoc :

Class객체가 나타내는 클래스 또는 인터페이스가 지정된 Class매개 변수가 나타내는 클래스 또는 인터페이스와 동일하거나 수퍼 클래스 또는 수퍼 인터페이스인지 판별합니다 . true그렇다면 반환 합니다. 그렇지 않으면를 반환합니다 false. 이 Class객체가 원시적 형을 나타내는 경우 ,이 메소드는 true지정된 Class파라미터가 정확하게이 Class객체 인 경우를 돌려줍니다 . 그렇지 않으면를 반환합니다 false.

참고:


관련 :

a) 객체가 컴파일 타임에 알고있는 클래스 또는 인터페이스 (하위 클래스 포함)의 인스턴스인지 확인하십시오.

boolean isInstance = someObject instanceof SomeTypeOrInterface;

예:

assertTrue(Arrays.asList("a", "b", "c") instanceof List<?>);

b) 객체가 런타임에만 알고있는 클래스 또는 인터페이스 (하위 클래스 포함)의 인스턴스인지 확인하십시오.

Class<?> typeOrInterface = // acquire class somehow
boolean isInstance = typeOrInterface.isInstance(someObject);

예:

public boolean checkForType(Object candidate, Class<?> type){
    return type.isInstance(candidate);
}

21
체계를 주목하십시오 : SUPERCLASS.isAssignableFrom(SUBCLASS)이것은 이름을 고려할 때 실제로 분명하지만 먼저 나를 혼란스럽게합니다.
codepleb

7
@TrudleR 동의합니다. 같은 뭔가 SUPERCLASS.isExtendedBy(SUBCLASS)이해하기 훨씬 쉬울 것
숀 패트릭 플로이드

실제로 @SeanPatrickFloyd isExtendedBy로 나쁜 이름 CLASS.isAssignableFrom(CLASS)사실 (따라서 것 CLASS.isExtendedBy(CLASS)뿐만 아니라이). 이것은 내가 기대 한 것이 아닙니다.
Qw3ry

@ Qw3ry 예, 나는 그것이 또한 Api 작가들이 생각한 것이라고 가정하고 있습니다 :-)
Sean Patrick Floyd

25

또 다른 옵션은 instanceof입니다.

Object o =...
if (o instanceof Number) {
  double d = ((Number)o).doubleValue(); //this cast is safe
}

통화가 양호합니다 (+1). 그리고 두 가지 메커니즘의 조합도 있습니다 : Class.isInstance(object) download.oracle.com/javase/6/docs/api/java/lang/…
Sean Patrick Floyd

5
이것은 당신이 그것을 밝히는 것을 의미합니다 Field. 그러나 나는 단지 내 수업과 그 분야를 "보고"싶어하고 "그것을 시험해보고"싶지 않습니다.
craesh

객체의 상속 트리를 확인해야하는 경우이 방법이 "isAssignableFrom"방식보다 훨씬 깨끗하고 명확합니다.
cbuchart

명심 instanceof또한 (이 경우 부모 작동 Number자체뿐만 아니라 어린이)
lukaszrys

9

instanceof 는 인스턴스, 즉 객체에서 작동합니다. 때때로 당신은 수업과 직접 일하기를 원합니다. 이 경우 Class 클래스 의 asSubClass 메서드를 사용할 수 있습니다 . 몇 가지 예 :

1)

    Class o=Object.class;
    Class c=Class.forName("javax.swing.JFrame").asSubclass(o);

JFrame은 Object의 하위 클래스이기 때문에 원활하게 진행됩니다. c는 JFrame 클래스를 나타내는 Class 객체를 포함합니다.

2)

    Class o=JButton.class;
    Class c=Class.forName("javax.swing.JFrame").asSubclass(o);

JFrame은 JButton의 하위 클래스가 아니기 때문에 java.lang.ClassCastException 이 시작됩니다 . c는 초기화되지 않습니다.

삼)

    Class o=Serializable.class;
    Class c=Class.forName("javax.swing.JFrame").asSubclass(o);

JFrame은 java.io.Serializable 인터페이스를 구현하기 때문에 순조롭게 진행됩니다. c는 JFrame 클래스를 나타내는 Class 객체를 포함합니다.

물론 필요한 수입품이 포함되어야합니다.


5

이것은 나를 위해 작동합니다 :

protected boolean isTypeOf(String myClass, Class<?> superClass) {
    boolean isSubclassOf = false;
    try {
        Class<?> clazz = Class.forName(myClass);
        if (!clazz.equals(superClass)) {
            clazz = clazz.getSuperclass();
            isSubclassOf = isTypeOf(clazz.getName(), superClass);
        } else {
            isSubclassOf = true;
        }

    } catch(ClassNotFoundException e) {
        /* Ignore */
    }
    return isSubclassOf;
}

1
훌륭하게 작동하지만 수퍼 클래스가없는 java.lang.Object를 누르는 경우 clazz = clazz.getSuperclass () 뒤에 null 검사를 추가해야 할 수도 있습니다.
Jonas Pedersen

4

이것은 @schuttek의 답변의 향상된 버전입니다. 프리미티브에 대해 false를 올바르게 리턴하고 (예 : isSubclassOf (int.class, Object.class) => false) 인터페이스를 올바르게 처리하기 때문에 (예 : isSubclassOf (HashMap.class, Map.class) => true) 개선되었습니다.

static public boolean isSubclassOf(final Class<?> clazz, final Class<?> possibleSuperClass)
{
    if (clazz == null || possibleSuperClass == null)
    {
        return false;
    }
    else if (clazz.equals(possibleSuperClass))
    {
        return true;
    }
    else
    {
        final boolean isSubclass = isSubclassOf(clazz.getSuperclass(), possibleSuperClass);

        if (!isSubclass && clazz.getInterfaces() != null)
        {
            for (final Class<?> inter : clazz.getInterfaces())
            {
                if (isSubclassOf(inter, possibleSuperClass))
                {
                    return true;
                }
            }
        }

        return isSubclass;
    }
}

3

a Class<?>가 다른 클래스의 하위 클래스 인지 확인하는 재귀 적 방법 Class<?>...

@To Kra답변 개선 된 버전 :

protected boolean isSubclassOf(Class<?> clazz, Class<?> superClass) {
    if (superClass.equals(Object.class)) {
        // Every class is an Object.
        return true;
    }
    if (clazz.equals(superClass)) {
        return true;
    } else {
        clazz = clazz.getSuperclass();
        // every class is Object, but superClass is below Object
        if (clazz.equals(Object.class)) {
            // we've reached the top of the hierarchy, but superClass couldn't be found.
            return false;
        }
        // try the next level up the hierarchy.
        return isSubclassOf(clazz, superClass);
    }
}

3

//계승

    class A {
      int i = 10;
      public String getVal() {
        return "I'm 'A'";
      }
    }

    class B extends A {
      int j = 20;
      public String getVal() {
        return "I'm 'B'";
      }
    }

    class C extends B {
        int k = 30;
        public String getVal() {
          return "I'm 'C'";
        }
    }

//행동 양식

    public static boolean isInheritedClass(Object parent, Object child) {
      if (parent == null || child == null) {
        return false;
      } else {
        return isInheritedClass(parent.getClass(), child.getClass());
      }
    }

    public static boolean isInheritedClass(Class<?> parent, Class<?> child) {
      if (parent == null || child == null) {
        return false;
      } else {
        if (parent.isAssignableFrom(child)) {
          // is child or same class
          return parent.isAssignableFrom(child.getSuperclass());
        } else {
          return false;
        }
      }
    }

// 코드 테스트

    System.out.println("isInheritedClass(new A(), new B()):" + isInheritedClass(new A(), new B()));
    System.out.println("isInheritedClass(new A(), new C()):" + isInheritedClass(new A(), new C()));
    System.out.println("isInheritedClass(new A(), new A()):" + isInheritedClass(new A(), new A()));
    System.out.println("isInheritedClass(new B(), new A()):" + isInheritedClass(new B(), new A()));


    System.out.println("isInheritedClass(A.class, B.class):" + isInheritedClass(A.class, B.class));
    System.out.println("isInheritedClass(A.class, C.class):" + isInheritedClass(A.class, C.class));
    System.out.println("isInheritedClass(A.class, A.class):" + isInheritedClass(A.class, A.class));
    System.out.println("isInheritedClass(B.class, A.class):" + isInheritedClass(B.class, A.class));

//결과

    isInheritedClass(new A(), new B()):true
    isInheritedClass(new A(), new C()):true
    isInheritedClass(new A(), new A()):false
    isInheritedClass(new B(), new A()):false
    isInheritedClass(A.class, B.class):true
    isInheritedClass(A.class, C.class):true
    isInheritedClass(A.class, A.class):false
    isInheritedClass(B.class, A.class):false
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.