instanceof Vs getClass ()


114

Operatöre göre kullanımda getClass()ve ==operatörde performans artışı görüyorum instanceOf.

Object  str = new Integer("2000");

long starttime = System.nanoTime();

if(str instanceof String) {
    System.out.println("its string");
} else {
    if (str instanceof Integer) {
        System.out.println("its integer");

    }
}

System.out.println((System.nanoTime()-starttime));

starttime = System.nanoTime();

if(str.getClass() == String.class) {
    System.out.println("its string in equals");
} else {
    if(str.getClass() == Integer.class) {
        System.out.println("its integer");
    }
}

System.out.println((System.nanoTime()-starttime));

Hangisini kullanacak getClass()veya kullanacak herhangi bir kılavuz var mı instanceOf?

Verilen senaryoda: Ben eşleştirilecek tam sınıfları biliyorum olduğu String, Integer(bunlar son sınıflardır) vb

instanceOfOperatörü kullanmak kötü bir uygulama mı?


3
Bu, şu adreste açıklanmıştır: stackoverflow.com/questions/596462/… .
Clement P

2
Zamanlama yönteminiz yapay gecikmelere neden oluyor ve yanlış zamanlama sonuçları üretiyor. Kontrolleri yaptığınız sırayı değiştirin ve yaptığınız ilk kontrolün (== veya instanceof) her zaman daha uzun olacağını göreceksiniz. Sanırım bu println () ler. Zamanlama bloğunuza asla bu şeyleri dahil etmemelisiniz.
kurtzmarc

Performansı karşılaştırmak için yalnızca bir yorum ayrı olmak üzere, doğruluğu iyileştirmek için çoklu döngü yinelemeleri (örn. 10000) kullanın. Tek bir çağrı iyi bir ölçü değildir.
martins.tuga

Yanıtlar:


139

Performansının instanceofve getClass() == ...farklı olmasının nedeni, farklı şeyler yapıyor olmalarıdır.

  • instanceofsol taraftaki (LHS) nesne referansının sağ taraftaki (RHS) tipin bir örneği mi yoksa bazı alt tipler mi olduğunu test eder .

  • getClass() == ... türlerin aynı olup olmadığını test eder.

Bu yüzden tavsiye, performans sorununu görmezden gelmek ve size ihtiyacınız olan cevabı veren alternatifi kullanmaktır.

instanceOfOperatörü kullanmak kötü bir uygulama mı?

Şart değil. Birinin aşırı kullanımı "tasarım kokusu" olabilirinstanceOf veya getClass() olabilir . Dikkatli olmazsanız, yeni alt sınıfların eklenmesinin önemli miktarda kod yeniden çalışmasına neden olduğu bir tasarım elde edersiniz. Çoğu durumda, tercih edilen yaklaşım, polimorfizm kullanmaktır.

Ancak, bunların "tasarım kokusu" OLMADIĞI durumlar da vardır. Örneğin equals(Object), argümanın gerçek türünü test etmeniz ve falseeşleşmezse geri dönmeniz gerekir. Bu en iyi kullanılarak yapılır getClass().


"En iyi uygulama", "kötü uygulama", "tasarım kokusu", "antipattern" ve benzeri terimler idareli kullanılmalı ve şüpheyle ele alınmalıdır. Siyah-beyaz düşünmeyi teşvik ederler. Kararlarınızı tamamen dogmaya dayalı olmaktansa bağlam içinde vermek daha iyidir; örneğin, birinin söylediği bir şey "en iyi uygulama" dır.


@StephenC Dediğin gibi, code smellikisini de kullanmak. Bu, her ikisini de kullanmanıza neden olan kötü tasarım (polimorfik olmayan) kodun bir sonucudur. ikisinin de bu şekilde kullanıldığını anlayabilir miyim?
2014

@overexchange - 1) "Aşırı kullanmak" değil, "kullanmak" dedim. 2) Bunun dışında ne sorduğunuzu anlamıyorum. "Kullanımını anlamak ..." ile ne demek istiyorsun ??? Kod ya bunları kullanır ya da kullanmaz.
Stephen C

Anladığım kadarıyla, kodun mevcut kötü tasarımı (polimorfik olmayan) nedeniyle kullanım instanceof& getClass()ortaya çıkıyor. doğrumuyum?
2014

5
@overexchange - Tüm kullanımın instanceof(örneğin) kötü tasarım olduğunu geçerli bir şekilde çıkaramazsınız . En iyi çözüm olabileceği durumlar vardır. Aynı getClass(). "Aşırı kullanım" dediğimi ve "kullan" demediğimi tekrar edeceğim . Her dava, temelden yoksun bir dogmatik kuralı körü körüne uygulayarak değil, kendi yararına göre değerlendirilmelidir.
Stephen C

44

Bir sınıfı tam olarak mı eşleştirmek istiyorsunuz , örneğin FileInputStreamherhangi bir alt sınıf yerine sadece eşleşiyor FileInputStreammu? Eğer öyleyse, getClass()ve kullanın ==. Bunu tipik olarak bir içinde yapardım equals, böylece X'in bir örneği X'in bir alt sınıfının bir örneğine eşit kabul edilmez - aksi takdirde zor simetri problemleriyle karşılaşabilirsiniz. Öte yandan, bu, iki nesnenin belirli bir sınıftan daha aynı sınıfta olduğunu karşılaştırmak için daha kullanışlıdır .

Aksi takdirde kullanın instanceof. O Not getClass()Eğer başlamak boş olmayan bir referansına sahip olmak gerekir, yoksa bir alırsınız NullPointerException, oysa instanceofsadece dönecektir falseilk işlenen boş ise.

Kişisel instanceofolarak daha deyimsel olduğunu söyleyebilirim - ancak ikisini de yoğun olarak kullanmak çoğu durumda bir tasarım kokusu.


18

Bunun sorulmasının üzerinden epey zaman geçtiğini biliyorum ama dün bir alternatif öğrendim

Hepimiz yapabileceğinizi biliyoruz:

if(o instanceof String) {   // etc

ama ya ne tür bir sınıf olması gerektiğini tam olarak bilmiyorsanız? genel olarak şunları yapamazsınız:

if(o instanceof <Class variable>.getClass()) {   

derleme hatası verdiği için.
Bunun yerine, işte bir alternatif - isAssignableFrom ()

Örneğin:

public static boolean isASubClass(Class classTypeWeWant, Object objectWeHave) {

    return classTypeWeWant.isAssignableFrom(objectWeHave.getClass())
}

8
Kullanmayın isAssignableFrom. o instanceof StringYansıma kullanarak yazmanın doğru yolu String.getClass().isInstance(o). Hatta javadoc şöyle diyor: Bu yöntem Java dil instanceofoperatörünün dinamik eşdeğeridir .
Andreas

3

getClass (), aşağıdaki kodun çıktısında gösterildiği gibi, nesnelerin yalnızca aynı sınıftaki diğer nesnelere eşit olmasına, aynı çalışma süresi türüne sahip olma kısıtlamasına sahiptir:

class ParentClass{
}
public class SubClass extends ParentClass{
    public static void main(String []args){
        ParentClass parentClassInstance = new ParentClass();
        SubClass subClassInstance = new SubClass();
        if(subClassInstance instanceof ParentClass){
            System.out.println("SubClass extends ParentClass. subClassInstance is instanceof ParentClass");
        }
        if(subClassInstance.getClass() != parentClassInstance.getClass()){
            System.out.println("Different getClass() return results with subClassInstance and parentClassInstance ");
        }
    }
}

Çıktılar:

SubClass, ParentClass'ı genişletir. subClassInstance, ParentClass'ın örneğidir.

Farklı getClass (), subClassInstance ve parentClassInstance ile sonuçları döndürür.

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.