Search code examples
javaclassnamescanonical-name

What's the difference between Name and CanonicalName?


What is the difference between Java's Class.getName() and Class.getCanonicalName()?


Solution

  • Consider the following program:

    package org.test.stackoverflow;
    
    public class CanonicalName {
    
      public static void main(String[] args) {
        CanonicalName cn = new CanonicalName();
        cn.printClassNames();
      }
    
      private Anonymous anony;
      private MyAnony myAnony;
    
      public CanonicalName() {
        anony = new Anonymous() {
          public void printInterface() {
            System.out.println("Anony Name: " + getClass().getName());
            System.out.println("Anony CanonicalName: " + getClass().getCanonicalName());
          }
        };
        myAnony = new MyAnony();
      }
    
      public void printClassNames() {
        System.out.println("CanonicalName, Name: " + getClass().getName());
        System.out.println("CanonicalName, CanonicalName: " + getClass().getCanonicalName());
        anony.printInterface();
        myAnony.printInterface();
      }
    
      private static interface Anonymous {
        public void printInterface();
      }
    
      private static class MyAnony implements Anonymous {
        public void printInterface() {
          System.out.println("MyAnony Name: " + getClass().getName());
          System.out.println("MyAnony CanonicalName: " + getClass().getCanonicalName());
        }
      }
    }
    

    Output:

    CanonicalName, Name: org.test.stackoverflow.CanonicalName
    CanonicalName, CanonicalName: org.test.stackoverflow.CanonicalName
    Anony Name: org.test.stackoverflow.CanonicalName$1
    Anony CanonicalName: null
    MyAnony Name: org.test.stackoverflow.CanonicalName$MyAnony
    MyAnony CanonicalName: org.test.stackoverflow.CanonicalName.MyAnony
    

    So it seems that for base classes, they return the same thing. For inner classes, getName() uses the $ naming convention (i.e. what is used for .class files), and getCanonicalName() returns what you would use if you were trying to instantiate the class. You couldn't do that with a (little-a) anonymous class, so that's why getCanonicalName() returns null.