Если у меня есть класс com.example.test.Enum2.Test
, как в коде ниже, почему getCanonicalName()
возвращает com.example.test.Enum2.Test
, но Class.forName()
требует: "com.example.test.Enum2$Test"
в качестве аргумента?
Есть ли способ, чтобы быть последовательным, так что я могу сериализации/десериализации значение перечисления по его имени, без необходимости проверять каждый $
против .
возможность, когда перечисление является вложенным классом?
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"
и т. д.
b. используйте правильную $ notation, так что Class.forName()
работает правильно в первый раз. Но для этого требуется, чтобы я реализовал альтернативу getCanonicalName(), которая создает строку, которая соответствует Class.forName()
.
Я склоняюсь к подходу (b), частично из чувства кишки, и частично потому, что подход (a) имеет неоднозначность, если есть имена пакетов с прописными буквами: com.example.Test.Enum2 и com.example.Test $ Enum2 может быть допустимым входом для Class.forName()
, если есть com/example/Test/Enum2.java и com/example/Test.java, содержащий внутренний класс Enum2.
... но я не знаю, как его реализовать. Есть идеи?
bummer. поэтому имя языка! = имя виртуальной машины. :-(Есть ли более простой способ преобразовать пунктирную нотацию в правильный $, без необходимости попробовать каждую возможность по очереди? (Например, com.example.test.Enum2.Test, com.example.test.Enum2 $ Test, com .example.test $ Enum2 $ Test и т. д.) –
@Jason S: Нет, к сожалению, это неоднозначно. xyz.ABC может означать 'xyz.ABC', или' xyz.AB $ C', или 'xyz.A $ B $ C' или 'xyz $ A $ B $ C'. Однако« долларовая версия »однозначна. –
ОК, спасибо, вот что я подумал. (+1 для объяснения) –