If I have a class com.example.test.Enum2.Test as in the code below, why does getCanonicalName() return com.example.test.Enum2.Test but Class.forName() requires "com.example.test.Enum2$Test" as an argument?
Is there a way to be consistent, so that I can serialize/deserialize an enum value by its name, without having to check each $ vs . possibility, when the enum is a nested class?
package com.example.test;
import java.util.Arrays;
public class Enum2 {
enum Test {
FOO, BAR, BAZ;
}
public static void main(String[] args) {
for (String className : Arrays.asList(
"com.example.test.Enum2.Test",
"com.example.test.Enum2$Test"))
{
try {
Class<?> cl = Class.forName(className);
System.out.println(className+" found: "+cl.getCanonicalName());
}
catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
System.out.println(Test.FOO.getDeclaringClass().getCanonicalName());
}
}
clarification: I'm looking for a good way to deal with this problem in a real application (not just the above contrived test case), either:
a. serialize/deserialize using getCanonicalName()'s output (dotted name only), and for Class.forName() try each possibility in turn e.g. first "com.example.test.Enum2.Test", then "com.example.test.Enum2$Test", then "com.example.test$Enum2$Test", etc.
b. use proper $ notation, so that Class.forName() works right the first time. But this requires me to implement an alternative to getCanonicalName() that produces a string that is consistent with Class.forName().
I am leaning toward approach (b), partially from gut