Kiểm tra xem Đối tượng lớp có phải là lớp con của Đối tượng lớp khác trong Java không


196

Tôi đang chơi xung quanh với API phản chiếu của Java và cố gắng xử lý một số trường. Bây giờ tôi bị mắc kẹt với việc xác định loại trường của tôi. Chuỗi là dễ dàng, chỉ cần làm myField.getType().equals(String.class). Điều tương tự áp dụng cho các lớp không dẫn xuất khác. Nhưng làm thế nào để tôi kiểm tra các lớp dẫn xuất? Ví dụ LinkedListnhư là lớp con của List. Tôi không thể tìm thấy bất kỳ isSubclassOf(...)hoặc extends(...)phương pháp. Tôi có cần phải tự mình đi qua tất cả getSuperClass()và tìm siêu lớp của mình không?


11
LinkedListkhông phải là một lớp con của List. Đây là một thực hiện của List.
TJ Crowder

2
Loại phụ có thể là một thuật ngữ tốt hơn
jpaugh

Câu trả lời:


402

Bạn muốn phương pháp này:

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

nơi nói chung, List(ở trên) nên được thay thế bằng superclassmyClassnên được thay thế bằngsubclass

Từ JavaDoc :

Xác định xem lớp hoặc giao diện được đại diện bởi Classđối tượng này giống hoặc là siêu lớp hoặc siêu giao diện của lớp hoặc giao diện được đại diện bởi Classtham số đã chỉ định . Nó trả về truenếu vậy; nếu không thì nó trả về false. Nếu Classđối tượng này đại diện cho một kiểu nguyên thủy, phương thức này trả về truenếu Classtham số đã chỉ định chính xác là Classđối tượng này ; nếu không thì nó trả về false.

Tài liệu tham khảo:


Liên quan:

a) Kiểm tra xem Đối tượng có phải là phiên bản của Lớp hoặc Giao diện (bao gồm các lớp con) mà bạn biết tại thời điểm biên dịch không:

boolean isInstance = someObject instanceof SomeTypeOrInterface;

Thí dụ:

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

b) Kiểm tra xem Đối tượng có phải là phiên bản của Lớp hoặc Giao diện (bao gồm các lớp con) mà bạn chỉ biết khi chạy không:

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

Thí dụ:

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

20
Lưu ý sơ đồ: SUPERCLASS.isAssignableFrom(SUBCLASS)Điều này làm tôi bối rối trước tiên, thực sự rõ ràng khi xem xét việc đặt tên.
codepleb

7
@TrudleR Tôi đồng ý. Một cái gì đó SUPERCLASS.isExtendedBy(SUBCLASS)sẽ dễ hiểu hơn nhiều
Sean Patrick Floyd

@SeanPatrickFloyd thực sự isExtendedBylà một tên xấu là CLASS.isAssignableFrom(CLASS)đúng (và do đó CLASS.isExtendedBy(CLASS)là tốt). Đây không phải là những gì tôi mong đợi.
Qw3ry

@ Qw3ry vâng, tôi cho rằng đó cũng là những gì các tác giả Api nghĩ :-)
Sean Patrick Floyd

24

Một tùy chọn khác là thể hiện:

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

Cuộc gọi tốt (+1). Và sau đó cũng là sự kết hợp của hai cơ chế: Class.isInstance(object) download.oracle.com/javase/6/docs/api/java/lang/
Kẻ

5
Điều này sẽ ngụ ý rằng bạn kích thích điều đó Field. Nhưng tôi chỉ muốn "nhìn" vào lớp của mình và các lĩnh vực của nó, không muốn "thử chúng".
craesh

Tôi thấy phương pháp này sạch sẽ và rõ ràng hơn nhiều so với cách "isAssignableFrom", trong trường hợp bạn cần kiểm tra cây thừa kế của một đối tượng.
cbuchart

Hãy nhớ rằng nó instanceofcũng hoạt động cho cha mẹ (trong trường hợp này Number), không chỉ riêng trẻ em
lukaszrys

9

instanceof hoạt động trên các thể hiện, tức là trên các Đối tượng. Đôi khi bạn muốn làm việc trực tiếp với các lớp học. Trong trường hợp này, bạn có thể sử dụng phương thức asSubClass của lớp Class. Vài ví dụ:

1)

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

điều này sẽ diễn ra suôn sẻ vì JFrame là lớp con của Object. c sẽ chứa một đối tượng Class đại diện cho lớp JFrame.

2)

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

điều này sẽ khởi chạy java.lang.ClassCastException vì JFrame KHÔNG phải là lớp con của JButton. c sẽ không được khởi tạo.

3)

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

điều này sẽ diễn ra suôn sẻ vì JFrame triển khai giao diện java.io.Serializable. c sẽ chứa một đối tượng Class đại diện cho lớp JFrame.

Tất nhiên nhập khẩu cần thiết phải được bao gồm.


5

Điều này làm việc cho tôi:

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
Hoạt động tốt, nhưng bạn có thể phải thêm kiểm tra null sau clazz = clazz.getSuperclass () trong trường hợp bạn nhấn java.lang.Object, người không có siêu hạng.
Jonas Pedersen

4

Đây là phiên bản cải tiến của câu trả lời của @ schuttek. Nó được cải thiện bởi vì nó trả về đúng sai cho các nguyên hàm (ví dụ: isSubgroupOf (int. Class, Object. Class) => false) và cũng xử lý chính xác các giao diện (ví dụ: isSub classOf (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

Một phương thức đệ quy để kiểm tra xem a Class<?>có phải là lớp con của Class<?>...

Phiên bản cải tiến của câu trả lời của @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

//Di sản

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

// Phương thứ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;
        }
      }
    }

// Kiểm tra mã

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

//Kết quả

    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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.