Bir nesnenin sınıfı nasıl belirlenir?


510

Sınıf Bve sınıf sınıfı Cgenişletirse Ave bir tür nesnem varsa Bveya Changi türün bir örnek olduğunu nasıl belirleyebilirim?


14
@starblue Döküm akla ilk gelen şey olurdu. Herhangi bir ihtiyaç olmasaydı , instanceof operatörünün var olacağından şüpheliyim .
b1nary.atr0phy

@ b1nary.atr0phy ilk olarak isntanceof operatörünü kullanmak iyi olmaz. Uyumsuz bir türe döküm varsa, bunun ClassCastException ile sonuçlanacağına inanıyorum
committedandroider

Yanıtlar:


801
if (obj instanceof C) {
//your code
}

31
Ters denetimi veya bir nesnenin bir sınıf örneği DEĞİL olup olmadığını nasıl kontrol edeceğinizi not etmekte if(!(obj instanceof C))
fayda vardır

32
GetClass () yönteminin orijinal sorunun cevabı olduğuna inanıyorum. Bu durumda (obj instanceof A) da "true" çıktısı verir, ancak amaç resimdeki nesnenin runtime sınıfını bulmaktır. Üst1, Alt1 ve Alt2 tarafından genişletilirse, aşağıdaki code Alt1 alt1 = yeni Alt1 (); Parent1 parentChild = yeni Child2 (); Child2 child2 = yeni Child2 (); (Çocuk1 Ebeveyn1 örneği); (çocuk1 Çocuk1 örneği); (parentChild Child2 örneği); (parentChild Ebeveyn1 örneği); (parentChild Child1 örneği); code , örnekleme niyetini temizleyebilir.
Bhavesh Agarwal

Kesinlikle bir arabirim oluşturmaya alternatif
JohnMerlino

3
Tek bir arabirimi uygulayan iki sınıfım varsa ne olur? Nesnenin tam sınıfını nasıl ayırt edebilirim?
olyv

3
Ancak bir şey, obj boşsa çalışmaz. Çözüm daha sonra ParentInterface.class.isAssignableFrom (Child.class) olacaktır
alexbt


178

Birden fazla doğru cevap sunuldu, ancak yine de daha fazla yöntem var: Class.isAssignableFrom()ve sadece nesneyi atmaya çalışmak (ki bu da a ClassCastException).

Olası yollar özetlenmiştir

Bir nesnenin objtürün bir örneği olup olmadığını test etmenin olası yollarını özetleyelim C:

// Method #1
if (obj instanceof C)
    ;

// Method #2
if (C.class.isInstance(obj))
    ;

// Method #3
if (C.class.isAssignableFrom(obj.getClass()))
    ;

// Method #4
try {
    C c = (C) obj;
    // No exception: obj is of type C or IT MIGHT BE NULL!
} catch (ClassCastException e) {
}

// Method #5
try {
    C c = C.class.cast(obj);
    // No exception: obj is of type C or IT MIGHT BE NULL!
} catch (ClassCastException e) {
}

nullElleçleme farkları

Bununla birlikte kullanımda bir fark var null:

  • İlk 2 yöntemlerinde ifadeler için değerlendirmek falsedurumunda objolduğunu null( nullbir şey örneği değildir).
  • 3. yöntem NullPointerExceptionaçıkça atar .
  • Aksine 4. ve 5. yöntemler kabul edilir nullçünkü nullher tür için kullanılabilir!

Hatırlamak için: null değil herhangi türde bir örneği ama dökülebilir her tür.

notlar

  • Class.getName()nesne türü değilse ancak alt sınıfı ise "is-instance-of" test becase gerçekleştirmek için kullanılmamalıdır C, tamamen farklı bir isim ve pakete sahip olabilir (bu nedenle sınıf adları açıkça eşleşmeyecektir), ancak hala tip C.
  • Aynı miras nedeni simetrikClass.isAssignableFrom() değildir : türü bir alt sınıf ise dönecekti .
    obj.getClass().isAssignableFrom(C.class)falseobjC

6
Bu, farklı yöntemlerde birçok tuzağın gerçekten harika bir özetidir. Böyle eksiksiz bir yazı için teşekkürler!
Kelsin

32

Kullanabilirsiniz:

Object instance = new SomeClass();
instance.getClass().getName(); //will return the name (as String) (== "SomeClass")
instance.getClass(); //will return the SomeClass' Class object

HTH. Ancak çoğu zaman bunu kontrol akışı veya benzeri bir şey için kullanmak iyi bir uygulama değildir ...


Genel logger oluşturmak için kullandım, bu yüzden logger'a nesne gönderdim ve günlük etiketi veya günlük dizesi vermek yerine nesnenin sınıf adına bağlı olarak günlüğe kaydeder. teşekkür ederim
MBH

24

Önerilen yöntemlerden herhangi birinin kullanılması, kötü bir OO tasarımına dayanan bir kod kokusu olarak kabul edilir.

Tasarımınız iyi ise, kendinizi kullanmanız gerektiğini getClass()veya bulacağınızı görmemelisiniz instanceof.

Önerilen yöntemlerden herhangi biri yapacak, ancak sadece tasarım açısından akılda tutulması gereken bir şey.


3
Evet, muhtemelen getClass ve instanceof kullanımlarının% 99'u polimorfik yöntem çağrılarıyla önlenebilir.
Bill the Lizard

3
bir anlaşmadayım. Bu durumda sahiplik yok kötü tasarlanmış bir şema takip xml oluşturulan nesnelerle çalışıyorum.
taşıyıcı

28
Gerek yok. Bazen arayüzlerin ayrılması iyidir. A'nın bir B olup olmadığını bilmek istediğiniz zamanlar vardır, ancak çoğu işlevsellik için yalnızca A gerektiğinden A'nın bir B olmasını zorunlu kılmak istemezsiniz - B'nin isteğe bağlı işlevselliği vardır.
MetroidFan2002

8
Ayrıca, nesnenin karşılaştırdığınız sınıfta olduğundan emin olmanız gereken zamanlar vardır; örneğin kendi sınıfımı oluşturduğumda Object eşittir yöntemini geçersiz kılmak istiyorum. Gelen nesnenin aynı sınıfta olduğunu her zaman doğrularım.
StackOverflowed

58
Ayrıca, insanlara tam olarak nedenini açıklamadan veya bir kağıda, kitaba veya sorunun açıklandığı diğer herhangi bir kaynağa referans vermeden kötü bir şey söylemenin yapıcı olmadığı düşünülür. Bu nedenle ve StackOverflow'da olduğumu bilerek, insanların neden bu cevabı bu kadar çok oyladığını bilmiyorum. Burada bir şeyler değişiyor ...
Adrián Pérez

15

Bu durumda yansımayı kullanabiliriz

objectName.getClass().getName();

Misal:-

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    String name = request.getClass().getName();
}

Bu durumda, nesnenin HttpServletRequestarabirim referans değişkenine ilettiği sınıfın adını alırsınız .


doğru. yalnızca kullanarak obj.getClass()className, prefixex kelimesini class
döndürür

request.getClass().getName();tüm paketi yazdırır! sınıf adı ile birlikte
shareef

13

.isInstance" Class" Sınıfında da bir yöntem vardır . bir nesnenin sınıfını üzerinden myBanana.getClass()alırsanız, nesnenizin via ile myAppleaynı sınıfın bir örneği olup olmadığını görebilirsiniz.myBanana

myBanana.getClass().isInstance(myApple)

1

isinstance()çalışma zamanında bilmek istiyorsanız ile kontrol yeterli olmaz. kullanın:

if(someObject.getClass().equals(C.class){
    // do something
}

0

GeneralUtils sınıfımda blow işlevini kullanıyorum, yararlı olup olmadığını kontrol edin

    public String getFieldType(Object o) {
    if (o == null) {
        return "Unable to identify the class name";
    }
    return o.getClass().getName();
}

0

Anahtar vakasını kullanmak yerine çalışma zamanında nesne örneğini elde etmek için Java 8 jeneriklerini kullandım

 public <T> void print(T data) {
    System.out.println(data.getClass().getName()+" => The data is " + data);
}

herhangi bir veri türünü ilettiğinizde yöntem, arama sırasında ilettiğiniz veri türünü yazdıracaktır. Örneğin

    String str = "Hello World";
    int number = 10;
    double decimal = 10.0;
    float f = 10F;
    long l = 10L;
    List list = new ArrayList();
    print(str);
    print(number);
    print(decimal);
    print(f);
    print(l);
    print(list);

Aşağıdaki çıktı

java.lang.String => The data is Hello World
java.lang.Integer => The data is 10
java.lang.Double => The data is 10.0
java.lang.Float => The data is 10.0
java.lang.Long => The data is 10
java.util.ArrayList => The data is []
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.