Java'da a.getClass () ve A.class arasındaki fark nedir?


102

Java'da, kullanma a.getClass()veya kullanma seçimini çevreleyen artılar / eksiler A.classnelerdir? Her ikisi de a'nın Class<?>beklendiği yerde kullanılabilir , ancak her ikisini de farklı koşullarda kullanmanın performans veya diğer ince faydaları olacağını hayal ediyorum (tıpkı Class.forName()ve ile olduğu gibi ClassLoader.loadClass().

Yanıtlar:


163

Farklı amaçlara sahip oldukları ve ikisi arasında nadiren "seçim" yapılacağı için bunları artılar / eksiler açısından karşılaştırmam.

  • a.getClass()döndürür zamanı tür bir a. Yani, eğer varsa o A a = new B();zaman sınıfı a.getClass()geri vereceğim B.

  • A.classAsınıfı statik olarak değerlendirir ve genellikle yansıma ile ilgili diğer amaçlar için kullanılır.

Performans açısından, orada olabilecek ölçülebilir bir fark olabilir, ama sonunda buna JVM ve / veya derleyici bağımlı olduğu için bu konuda bir şey söylemeyeceğim.


Bu gönderi burada bir makale olarak yeniden yazılmıştır .


2
Nasıl olur A.class.getClass()?
user1870400

5
Bu size yine bir örneği olan nesneyi Classtemsil eden sınıfın A.classnesnesini verir java.lang.Class.
aioobe

Nasıl olur A.getClass().class?
Shikhar Mainalee

@ShikharMainalee, eğer Abir sınıfsa bu gerçekten mantıklı değil . getClassSınıflarda statik bir yöntem yoktur .
aioobe

nasıl bu öneriye nasıl bir ilişki var burada onlar da farklı sınıf yükleyiciler işaret ettiğinden. Bu aynı zamanda ikisi arasında önemli bir fark olabilir mi?
Jim

32

Nerede kullanabileceğiniz konusunda aslında farklılar. A.classderleme zamanında çalışır, a.getClass()bir tür örneği gerektirir Ave çalışma zamanında çalışır.

Bir performans farkı da olabilir. İken A.classbu fiili tipini bildiği için derleyici tarafından çözülebilir A, a.getClass()zamanında oluyor sanal yöntem çağrıdır.

Referans olarak, bayt kodunu hedefleyen bir derleyici genellikle aşağıdakiler için aşağıdaki talimatları yayınlar Integer.getClass():

aload_1
invokevirtual   #3; //Method java/lang/Object.getClass:()Ljava/lang/Class;

ve aşağıdakiler için Integer.class:

//const #3 = class  #16;    //  java/lang/Integer

ldc_w   #3; //class java/lang/Integer

İlki tipik olarak sanal bir yöntem gönderimini içerecektir ve bu nedenle muhtemelen yürütülmesi daha uzun zaman alacaktır. Ancak bu, sonunda JVM'ye bağımlıdır.


1
[1] teknik olarak Java Dil Spesifikasyonu sabit bir havuzdan hiç bahsetmiyor ...
aioobe

@aioobe: Sanırım haklısın, bu yüzden Sun JDK tarafından oluşturulan bayt kodunu kontrol ettim.
Tomasz Nurkiewicz

1
... teknik olarak konuşursak, bu da güvenilir bir cevap sağlamaz, çünkü Java Dil Spesifikasyonu anlambilim söz konusu olduğunda bayt kodundan bahsetmez bile.
aioobe

@aioobe: Ne demek istediğini anladım. JLS'den hiç bahsetmedim, sadece emin olmadığım için deneysel olarak nasıl çalıştığını kontrol ettim. OP performansı sorar ve bayt kodunu incelemek iyi bir fikir gibi göründü. Kapalı ifadelerden Gönderimimi düzenlemek veya kaldırmak için çekinmeyin
Tomasz Nurkiewicz

1
beğenmediyseniz geri dönün ;-)
aioobe

8

aşağıdaki örneklere bir göz atın

a.getClass()!= A.classyani a, A'nın bir örneği değil, A'nın anonim bir alt sınıfının bir örneğidir

a.getClass() A tipi bir örnek gerektirir


4

Kullanım a.getClasssınıf / türünün bir örneği var ve bunun kesin tipini almak istediğinizde. while a.class, typemüsait olduğunuzda ve bunun bir örneğini oluşturmak istediğinizde kullanılır.
Ayrıca getClass()süre Örneğin çalışma zamanı tür döner .classderleme zamanında değerlendirilmektedir.
Performansını göz önüne alındığında getClass()ve .class, .classdaha iyi bir performansa sahiptir getClass() .
Misal :

public class PerfomanceClass {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        long time=System.nanoTime();
        Class class1="String".getClass();
        class1="String".getClass();
        class1="String".getClass();
        class1="String".getClass();

        System.out.println("time (getClass()) :"+(System.nanoTime()-time)+" ns");     


        long time2=System.nanoTime();
        Class class2=String.class;
        class2=String.class;
        class2=String.class;
        class2=String.class;

        System.out.println("time (.class):"+(System.nanoTime()-time2)+" ns");
    }

}

Çıktı :

time (getClass()) : 79410 ns
time (.class)     : 8032 ns

1

Eklemek istediğim bir fark var. Diyelim ki, aşağıda gösterildiği gibi bir Class nesnesi alan bir süper sınıf ile bir kurucu sınıfınız var. Bir alt sınıf nesnesi oluşturulduğunda, alt sınıfın sınıf nesnesinin süper sınıfa aktarılmasını istiyorsunuz. Bir yapıcıda örnek yöntemi çağıramayacağınız için aşağıdaki kod derlenmeyecektir. Bu durumda myObject.getClass()ile değiştirirseniz MyClass.class. Mükemmel çalışacak.

Class MyClass
{
    private MyClass myObject = new MyClass();
    public MyClass()
    {
        super(myObject.getClass()); //error line compile time error
    }
}

2
Aynı sınıfın örnek değişkenleriyle aynı sınıfın örneğine sahip olmak .... Özyinelemeli olarak nesneler oluştururken yığın alanınız tükenir.
Aniket Thakur

1

İlginç bir şekilde, yukarıdaki örnekte bahsedilen performans farklılıkları başka nedenlerle ilişkili görünmektedir. 3 farklı Sınıf kullanıldığında, ortalama olarak performans neredeyse aynı olacaktır:

import java.util.LinkedHashMap;
public class PerfomanceClass {

public static void main(String[] args) {

    long time = System.nanoTime();
    Class class1 = "String".getClass();
    Class class11 = "Integer".getClass();
    Class class111 = "LinkedHashMap".getClass();

    System.out.println("time (getClass()) :" + (System.nanoTime() - time) + " ns");

    long time2 = System.nanoTime();
    Class class2 = String.class;
    Class class22 = Integer.class;
    Class class222 = LinkedHashMap.class;

    System.out.println("time (.class):" + (System.nanoTime() - time2) + " ns");
} }

Çıktı şu şekilde olacaktır:

time (getClass()) :23506 ns 
time (.class):23838 ns

Ve aramaların sırasını değiştirmek bile getClass()daha hızlı sonuçlanacaktır .

import java.util.LinkedHashMap;

public class PerfomanceClass {

public static void main(String[] args) {
    long time2 = System.nanoTime();
    Class class2 = LinkedHashMap.class;

    System.out.println("time (.class):" + (System.nanoTime() - time2) + " ns");

    long time = System.nanoTime();
    Class class1 = "LinkedHashMap".getClass();

    System.out.println("time (getClass()) :" + (System.nanoTime() - time) + " ns");
}}

Çıktı:

time (.class):33108 ns
time (getClass()) :6622 ns

"3 Farklı Sınıf Kullanmak". Ancak getClass () bölümünde 3 farklı sınıf kullanmıyorsunuz. Bunların hepsi String'dir ve bu nedenle getClass tüm örnekler için java.lang.String'i döndürür.
Kilian

1

p.getClass(), burada pbir nesnenin örneği, bu nesnenin çalışma zamanı sınıfını döndürür p. pderleme zamanı hatasına neden olacak bir tür olamaz, bir nesnenin örneği olmalıdır.

// B extends A
A a = new B();
System.out.println(a.getClass());
//output: class B

p.classbir ifadedir. .classSınıf sözdizimi denir. pbir türdür. Bir sınıfın, arayüzün veya dizinin adı ve hatta ilkel bir tip olabilir. a.getClass() == B.class.

Bir tür mevcutsa ve bir örnek varsa getClass, türün adını almak için yöntemi kullanmak mümkündür . Aksi takdirde .classsözdizimini kullanın

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.