Javaのa.getClass()とA.classの違いは何ですか?


101

Javaでは、どのような長所/短所が使用する選択肢を取り巻く存在しますa.getClass()A.class?どちらもa Class<?>が期待されるところならどこでも使用できますが、(Class.forName()やと同じように)異なる状況で両方を使用するとパフォーマンスや他の微妙な利点があると思いClassLoader.loadClass()ます。

回答:


163

賛否両論の観点から比較することはしません。なぜなら、目的が異なり、2つの間に「選択」することはほとんどないためです。

  • a.getClass()ランタイムタイプを返しますa。つまり、あなたが持っている場合A a = new B();、次にa.getClass()返しますBクラスを。

  • A.class評価Aクラス静的に、しばしば反射に関連する他の目的のために使用されます。

パフォーマンスの点では測定可能な違いがあるかもしれませんが、結局それはJVMやコンパイラーに依存しているのでそれについては何も言わないでしょう。


この投稿は、こちらの記事に書き直されました。


2
いかがA.class.getClass()ですか?
user1870400 2017年

5
これClassにより、A.class再びのインスタンスであるオブジェクトを表すクラスのオブジェクトが得られますjava.lang.Class
aioobe 2017年

いかがA.getClass().classですか?
Shikhar Mainalee、

@ShikharMainalee、それがAクラスである場合、それは本当に意味がありません。getClassクラスに静的メソッドはありません。
aioobe

これは、異なるクラスローダーを指すというここでの提案とどのように関連していますか。これは、2つの間の大きな違いかもしれませんか?
ジム、

32

実際に使用できる場所は異なります。タイプのインスタンスA.classa.getClass()必要としながら、コンパイル時に動作しますAとし、実行時に機能します。

パフォーマンスの違いもあるかもしれません。一方でA.class、それは実際のタイプを知っているので、コンパイラによって解決することができAa.getClass()実行時に起こった仮想メソッド呼び出しです。

参考までに、バイトコードをターゲットとするコンパイラは通常、次の命令を発行しますInteger.getClass()

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

と以下のためにInteger.class

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

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

前者は通常、仮想メソッドのディスパッチを伴うため、実行に時間がかかると考えられます。ただし、最終的にはJVMに依存します。


1
[1]技術的には、Java言語仕様では定数プールについてまったく言及されていません...
aioobe

@aioobe:私はあなたが正しいと思います、それがSun JDKによって生成されたバイトコードをチェックした理由です。
Tomasz Nurkiewicz

1
... Java言語仕様では、セマンティクスに関してはバイトコードについても言及されていないため、技術的に言えば、信頼できる回答も提供されません。
aioobe

@aioobe:要点はわかります。私はJLSについて言及したことはありませんが、わからないので、JLSがどのように機能するかを経験的に確認しました。OPはパフォーマンスについて尋ね、バイトコードを調べるのは良い考えのように思えました。私の投稿を編集するか、あいまいなステートメントを削除してください
Tomasz Nurkiewicz

1
気に入らない場合はロールバックしてください;-)
aioobe

8

以下の例を見てください

a.getClass()!= A.classつまり、aはAのインスタンスではなく、Aの匿名サブクラスのインスタンスです。

a.getClass() タイプAのインスタンスが必要


4

a.getClassクラス/タイプのインスタンスがあり、その正確なタイプを取得したい場合に使用します。while a.classは、使用type可能で、そのインスタンスを作成する場合に使用されます。コンパイル時に評価される間、インスタンスのランタイムタイプ
getClass()返します.class
とのパフォーマンスを考慮するgetClass().class、はよりもパフォーマンス.classが優れています getClass()
例:

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

}

出力:

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

1

追加したい違いが1つあります。Classオブジェクトを受け取るスーパークラスを使用して、以下に示すようなコンストラクターのクラスがあるとします。サブクラスオブジェクトが作成されるたびに、サブクラスのクラスオブジェクトをスーパークラスに渡す必要があります。以下のコードは、コンストラクターでインスタンスメソッドを呼び出すことができないため、コンパイルされません。その場合、あなたは交換した場合myObject.getClass()MyClass.class。それは完全に実行されます。

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

2
同じクラスのインスタンス変数と同じクラスのインスタンスがある...オブジェクトを再帰的に作成していると、ヒープ領域が不足します。
Aniket Thakur

1

興味深いことに、上記の例で述べたパフォーマンスの違いは、他の理由に関連しているようです。3つの異なるクラスを使用すると、平均してパフォーマンスはほぼ同じになります。

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

出力は次のようになります。

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

また、呼び出しの順序を切り替えると、さらにgetClass()高速になります。

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

出力:

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

「3つの異なるクラスの使用」。ただし、getClass()セクションでは、3つの異なるクラスを使用していません。これらはすべてStringであるため、getClassはすべてのインスタンスに対してjava.lang.Stringを返します。
キリアン2018年

1

p.getClass()は、がpオブジェクトのインスタンスである場合、このオブジェクトのランタイムクラスを返しますppコンパイル時エラーを引き起こすタイプであってはなりません。それはオブジェクトのインスタンスであるべきです。

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

p.class式です。これ.classはクラス構文と呼ばれます。pタイプです。これは、クラス、インターフェース、または配列の名前、さらにはプリミティブ型にすることもできます。 a.getClass() == B.class

タイプが利用可能でインスタンスがある場合、getClassメソッドを使用してタイプの名前を取得できます。それ以外の場合は、.class構文を使用します

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.