Если у меня есть класс com.example.test.Enum2.Test
, как в приведенном ниже коде, почему getCanonicalName()
return com.example.test.Enum2.Test
, но Class.forName()
требует "com.example.test.Enum2$Test"
в качестве аргумента?
Есть ли способ быть последовательным, чтобы я мог сериализовать/десериализовать значение перечисления по его имени, без необходимости проверять каждую возможность $
vs .
, когда перечисление является вложенным классом?
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());
}
}
пояснение: Я ищу хороший способ справиться с этой проблемой в реальном приложении (а не только на вышеупомянутом опыте):
а. сериализовать/десериализовать с помощью вывода getCanonicalName()
(только для точечного имени), а для Class.forName()
попробовать каждую возможность, в свою очередь, например, сначала "com.example.test.Enum2.Test"
, затем "com.example.test.Enum2$Test"
, затем "com.example.test$Enum2$Test"
и т.д.
б. используйте правильную $нотацию, так что Class.forName()
работает правильно в первый раз. Но для этого требуется, чтобы я реализовал альтернативу getCanonicalName(), которая создает строку, которая согласуется с Class.forName()
.
Я склоняюсь к подходу (б), частично от чувства кишки, и частично потому, что подход (а) имеет двусмысленности, если есть имена пакетов с прописными буквами: com.example.Test.Enum2 и com.example.Test $Enum2 оба могут быть действительными входами в Class.forName()
, если есть com/example/Test/Enum2.java и com/example/Test.java, содержащий внутренний класс Enum2.
... но я не знаю, как его реализовать. Любые идеи?