Java では、次の違いは何ですか?
Object o1 = ....
o1.getClass().getSimpleName();
o1.getClass().getName();
o1.getClass().getCanonicalName();
Javadoc を何度も確認しましたが、それでも十分に説明されていません。また、テストも実行しましたが、これらのメソッドの呼び出し方法の背後にある実際の意味は反映されませんでした。
ベストアンサー1
何か不明な点がある場合は、まずテストを書いてみてください。
これは私がしました:
class ClassNameTest {
public static void main(final String... arguments) {
printNamesForClass(
int.class,
"int.class (primitive)");
printNamesForClass(
String.class,
"String.class (ordinary class)");
printNamesForClass(
java.util.HashMap.SimpleEntry.class,
"java.util.HashMap.SimpleEntry.class (nested class)");
printNamesForClass(
new java.io.Serializable(){}.getClass(),
"new java.io.Serializable(){}.getClass() (anonymous inner class)");
}
private static void printNamesForClass(final Class<?> clazz, final String label) {
System.out.println(label + ":");
System.out.println(" getName(): " + clazz.getName());
System.out.println(" getCanonicalName(): " + clazz.getCanonicalName());
System.out.println(" getSimpleName(): " + clazz.getSimpleName());
System.out.println(" getTypeName(): " + clazz.getTypeName()); // added in Java 8
System.out.println();
}
}
プリント:
int.class (primitive):
getName(): int
getCanonicalName(): int
getSimpleName(): int
getTypeName(): int
String.class (ordinary class):
getName(): java.lang.String
getCanonicalName(): java.lang.String
getSimpleName(): String
getTypeName(): java.lang.String
java.util.HashMap.SimpleEntry.class (nested class):
getName(): java.util.AbstractMap$SimpleEntry
getCanonicalName(): java.util.AbstractMap.SimpleEntry
getSimpleName(): SimpleEntry
getTypeName(): java.util.AbstractMap$SimpleEntry
new java.io.Serializable(){}.getClass() (anonymous inner class):
getName(): ClassNameTest$1
getCanonicalName(): null
getSimpleName():
getTypeName(): ClassNameTest$1
最後のブロックには空のエントリがあり、getSimpleName
空の文字列が返されます。
これを見ると、結論は次のようになります。
- 名前は、たとえば、
Class.forName
デフォルトの を使用した の呼び出しなど、を使用してクラスを動的にロードするために使用する名前ですClassLoader
。特定の のスコープ内ではClassLoader
、すべてのクラスに一意の名前が付けられます。- 正規名は、インポート ステートメントで使用される名前です。これは、操作中
toString
またはロギング操作中に役立つ場合があります。javac
コンパイラがクラスパスの完全なビューを持っている場合、コンパイル時に完全修飾クラス名とパッケージ名を衝突させることにより、クラスパス内の正規名の一意性を強制します。ただし、JVM はこのような名前の衝突を受け入れる必要があるため、正規名は 内のクラスを一意に識別しませんClassLoader
。(後から考えると、このゲッターのより適切な名前は でしたがgetJavaName
、このメソッドは、JVM が Java プログラムを実行するためだけに使用されていた時代のものです。)- 単純な名前はクラスを大まかに識別し、
toString
操作中またはログ記録中に役立つ可能性がありますが、一意であることが保証されません。- 型名は「この型の名前に関する情報文字列」を返します。「それは
toString
、純粋に情報提供のみであり、契約値はありません」。(sir4ur0n によって記述)
また、これらのタイプの技術的な Java API の詳細については、Java 言語仕様ドキュメントを参照することもできます。
- この件に関するJava 11仕様は次のとおりです。javase.jls の仕様
Example 6.7-2.
そしてExample 6.7-2.
それぞれFully Qualified Names
Fully Qualified Names v. Canonical Name