Sınıf Nesnesinin Java'daki başka bir Sınıf Nesnesinin alt sınıfı olup olmadığını kontrol edin


197

Java'nın yansıma API'sı ile oynuyorum ve bazı alanları ele almaya çalışıyorum. Şimdi tarlalarımın türünü tanımlamakta kaldım. Teller kolaydır, sadece yapın myField.getType().equals(String.class). Aynısı türetilmemiş diğer sınıflar için de geçerlidir. Fakat türetilmiş sınıfları nasıl kontrol ederim? Örneğin LinkedList, alt sınıfı olarak List. Herhangi bir yöntem isSubclassOf(...)veya extends(...)yöntem bulamıyorum . getSuperClass()Herkesin içinden geçip kendi sınıfımı kendim bulmam gerekir mi?


11
LinkedListalt sınıfı değil List. Bu bir var uygulama içinde List.
TJ Crowder

2
Alt tür daha iyi bir terim olabilir
jpaugh

Yanıtlar:


403

Bu yöntemi istiyorsunuz:

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

genel olarak, List(yukarıda) ile değiştirilmeli superclassve myClassile değiştirilmelidirsubclass

Gönderen JavaDoc'u :

Bu Classnesne tarafından temsil edilen sınıfın veya arabirimin, belirtilen Classparametre tarafından temsil edilen sınıf veya arabirim ile aynı mı yoksa üst sınıf mı yoksa üst sınıf mı olduğunu belirler . trueVarsa geri döner ; aksi halde geri döner false. Bu Classnesne ilkel bir türü temsil trueediyorsa, belirtilen Classparametre tam olarak bu Classnesne ise bu yöntem döndürülür ; aksi halde geri döner false.

Referans:


İlişkili:

a) Bir Nesnenin derleme zamanında bildiğiniz bir Sınıf veya Arayüz (alt sınıflar dahil) örneği olup olmadığını kontrol edin:

boolean isInstance = someObject instanceof SomeTypeOrInterface;

Misal:

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

b) Bir Nesnenin yalnızca çalışma zamanında bildiğiniz bir Sınıf veya Arayüz (alt sınıflar dahil) örneği olup olmadığını kontrol edin:

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

Misal:

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

21
Şemaya dikkat edin: SUPERCLASS.isAssignableFrom(SUBCLASS)Bu, adlandırma konusunda aslında açık olsa da, önce beni karıştırdı.
codepleb

7
@ Kabul ediyorum. Gibi bir SUPERCLASS.isExtendedBy(SUBCLASS)şeyi anlamak çok daha kolay olurdu
Sean Patrick Floyd

@SeanPatrickFloyd aslında doğru (ve bu nedenle de) gibi isExtendedBykötü bir isim . Bu beklediğim gibi olmazdı. CLASS.isAssignableFrom(CLASS)CLASS.isExtendedBy(CLASS)
Qw3ry

@ Qw3ry evet, Api yazarlarının da düşündüklerini varsayıyorum :-)
Sean Patrick Floyd

25

Başka bir seçenek de:

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

İyi çağrı (+1). Ve sonra iki mekanizmanın birleşimi de var: Class.isInstance(object) download.oracle.com/javase/6/docs/api/java/lang/…
Sean Patrick Floyd

5
Bu, bunu ima ettiğinizi ima eder Field. Ama sadece dersime ve alanlarına "bakmak" istiyorum, "denemek" istemiyorum.
craesh

Bir nesnenin miras ağacını kontrol etmeniz gerekiyorsa, bu yöntemi "isAssignableFrom" yolundan çok daha temiz ve net görüyorum.
cbuchart

Unutmayın ki sadece çocuk için değil instanceofebeveyn (bu durumda Number) kendisi için de çalışır
lukaszrys

9

instanceof , örnekler üzerinde, yani Nesneler üzerinde çalışır. Bazen doğrudan sınıflarla çalışmak istersiniz. Bu durumda , Class sınıfının asSubClass yöntemini kullanabilirsiniz . Bazı örnekler:

1)

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

JFrame, Object'in alt sınıfı olduğu için bu işlem sorunsuz gerçekleşir. c, JFrame sınıfını temsil eden bir Class nesnesi içerecektir.

2)

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

JFrame JButton alt sınıfı DEĞİLDİR, çünkü bu bir java.lang.ClassCastException başlatır . c başlatılmayacak.

3)

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

JFrame java.io.Serializable arabirimini uyguladığı için bu sorunsuz bir şekilde devam edecektir. c, JFrame sınıfını temsil eden bir Class nesnesi içerecektir.

Elbette ihtiyaç duyulan ithalatın da dahil edilmesi gerekiyor.


5

Bu benim için çalışıyor:

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
Güzel çalışıyor, ancak süper bir sınıfı olmayan java.lang.Object tuşuna basmanız durumunda clazz = clazz.getSuperclass () 'dan sonra bir null kontrol eklemeniz gerekebilir.
Jonas Pedersen

4

Bu @ schuttek'in cevabının geliştirilmiş bir versiyonudur. Temel öğeler (örneğin isSubclassOf (int.class, Object.class) => false) için doğru şekilde yanlış döndürdüğü ve ayrıca arabirimleri doğru bir şekilde işlediği (ör. İsSubclassOf (HashMap.class, Map.class) => true) olduğu için geliştirildi.

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'nın Class<?>bir başkasının alt sınıfı olup olmadığını kontrol etmek için özyinelemeli bir yöntem Class<?>...

Geliştirilmiş versiyonu @Bir Kra bireyin cevabı :

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

// Kalıtım

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

// Yöntemler

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

// Kodu test et

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

//Sonuç

    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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.