小编典典

Java Class 中的规范名、简单名和类名有什么区别?

all

在Java中,这些有什么区别:

Object o1 = ....
o1.getClass().getSimpleName();
o1.getClass().getName();
o1.getClass().getCanonicalName();

我已经多次检查了 Javadoc,但这从来没有很好地解释它。我还进行了一个测试,这并没有反映出调用这些方法的方式背后的任何真正含义。


阅读 123

收藏
2022-02-28

共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返回一个空字符串。

看这个的结果是:

  • name
    是您用于动态加载类的名称,例如,使用Class.forNamedefault调用ClassLoader。在一定的范围内ClassLoader,所有的类都有唯一的名字。
  • 规范名称
    是在导入语句中使用的名称。toString在或记录操作期间它可能很有用。当javac编译器拥有类路径的完整视图时,它通过在编译时冲突完全限定的类和包名称来强制其中规范名称的唯一性。但是
    JVM 必须接受这种名称冲突,因此规范名称不能唯一标识ClassLoader. (事后看来,这个 getter
    的一个更好的名字应该是getJavaName;但是这个方法可以追溯到 JVM 仅用于运行 Java 程序的时候。)
  • 简单的 名称 松散地标识类,在或记录操作期间可能很有用,toString但不能保证是唯一的。
  • 类型名称 返回“此类型名称的信息字符串”,“就像toString:它纯粹是信息性的,没有合同价值”。(由 sir4ur0n 撰写)

您还可以通常参考 Java 语言规范文档以了解这些类型的技术 Java API 详细信息:

Example 6.7-2.并分别Example 6.7-2.过去Fully Qualified NamesFully Qualified Names v. Canonical Name

2022-02-28