Java a.getClass()
またはA.class
を使用する選択を取り巻く長所/短所は何ですか?Class<?>
が期待されるところならどこでも使用できますが、異なる状況で両方を使用することによる他の微妙な利点(Class.forName()
およびClassLoader.loadClass()
の場合と同様です。
長所/短所の点でそれらを比較することはありません。なぜならそれらには異なる目的があり、2つの間で「選択」することはめったにないからです。
a.getClass()
は、a
のランタイムタイプを返します。つまり、A a = new B();
がある場合、a.getClass()
はB
クラスを返します。
A.class
はA
クラスstaticallyに評価され、反射に関連することが多い他の目的に使用されます。
パフォーマンスの面では、[mayには測定可能な差がありますが、最終的にはJVMやコンパイラに依存するため、それについては何も言いません。
この投稿は記事として書き直されました here 。
実際には、どこで使用できるかによって異なります。 _A.class
_はコンパイル時に機能しますが、a.getClass()
はA
型のインスタンスを必要とし、実行時に機能します。
パフォーマンスの違いもあります。 _A.class
_はA
の実際の型を知っているため、コンパイラによって解決できますが、a.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に依存します。
以下の例をご覧ください
a.getClass()!= A.class
、つまりaはAのインスタンスではなく、Aの匿名サブクラスのインスタンスです
a.getClass()
にはタイプAのインスタンスが必要です
クラス/タイプのインスタンスがあり、その正確なタイプを取得する場合は、a.getClass
を使用します。 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つあります。以下に示すように、Classオブジェクトを受け取るスーパークラスを持つクラスのコンストラクタがあるとします。サブクラスオブジェクトが作成されるたびに、サブクラスのクラスオブジェクトをスーパークラスに渡す必要があります。以下のコードは、コンストラクターでインスタンスメソッドを呼び出すことができないため、コンパイルされません。その場合、myObject.getClass()
をMyClass.class
に置き換えると。完全に実行されます。
Class MyClass
{
private MyClass myObject = new MyClass();
public MyClass()
{
super(myObject.getClass()); //error line compile time error
}
}
p.getClass()
は、p
がオブジェクトのインスタンスである場合、このオブジェクトp
のランタイムクラスを返します。 p
は、コンパイル時エラーを引き起こすタイプにすることはできません。オブジェクトのインスタンスである必要があります。
_// 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
_構文を使用します
興味深いことに、上記の例で述べたパフォーマンスの違いは、他の理由に関連しているようです。 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
_