What is the difference between canonical name, simple name and class name in Java Class?

后端 未结 8 1138
感动是毒
感动是毒 2020-11-27 08:58

In Java, what is the difference between these:

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


        
相关标签:
8条回答
  • 2020-11-27 09:27

    If you're unsure about something, try writing a test first.

    I did this:

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

    Prints:

    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
    

    There's an empty entry in the last block where getSimpleName returns an empty string.

    The upshot looking at this is:

    • the name is the name that you'd use to dynamically load the class with, for example, a call to Class.forName with the default ClassLoader. Within the scope of a certain ClassLoader, all classes have unique names.
    • the canonical name is the name that would be used in an import statement. It might be useful during toString or logging operations. When the javac compiler has complete view of a classpath, it enforces uniqueness of canonical names within it by clashing fully qualified class and package names at compile time. However JVMs must accept such name clashes, and thus canonical names do not uniquely identifies classes within a ClassLoader. (In hindsight, a better name for this getter would have been getJavaName; but this method dates from a time when the JVM was used solely to run Java programs.)
    • the simple name loosely identifies the class, again might be useful during toString or logging operations but is not guaranteed to be unique.
    • the type name returns "an informative string for the name of this type", "It's like toString(): it's purely informative and has no contract value" (as written by sir4ur0n)
    0 讨论(0)
  • 2020-11-27 09:27

    In addition to Nick Holt's observations, I ran a few cases for Array data type:

    //primitive Array
    int demo[] = new int[5];
    Class<? extends int[]> clzz = demo.getClass();
    System.out.println(clzz.getName());
    System.out.println(clzz.getCanonicalName());
    System.out.println(clzz.getSimpleName());       
    
    System.out.println();
    
    
    //Object Array
    Integer demo[] = new Integer[5]; 
    Class<? extends Integer[]> clzz = demo.getClass();
    System.out.println(clzz.getName());
    System.out.println(clzz.getCanonicalName());
    System.out.println(clzz.getSimpleName());
    

    Above code snippet prints:

    [I
    int[]
    int[]
    
    [Ljava.lang.Integer;
    java.lang.Integer[]
    Integer[]
    
    0 讨论(0)
提交回复
热议问题