2011-02-09 122 views
11

如果我有一个类com.example.test.Enum2.Test如下面的代码,为什么getCanonicalName()返回com.example.test.Enum2.TestClass.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"

b。使用适当的$符号,以便Class.forName()第一次正常工作。但是这需要我实现getCanonicalName()的替代方法,该方法会生成一个与Class.forName()一致的字符串。

我倾向于方法(b),部分来自直觉,部分原因是方法(a)在包名大写的情况下有歧义:com.example.Test.Enum2和com.example.Test $如果存在com/example/Test/Enum2.java和包含Enum2内部类的com/example/Test.java,则Enum2都可以是有效的输入,即Class.forName()

...但我不知道如何实现它。有任何想法吗?

回答

9

ARGH:我应该只是简单地使用Class.getName()而不是Class.getCanonicalName()

5

那么,对于getCanonicalName状态的文档:

返回由Java语言规范定义基础类的规范名称。

(重点煤矿。)

在Java语言,嵌套表示以点。就图书馆和虚拟机而言,嵌套类只是名称中带有$的类。

你还没有说过你在谈论什么样的序列化 - 只要你对这两个方向一致,它应该没问题。

+0

无赖。所以语言的名字!= VM​​的名字。 :-(是否有一种更简单的方法将虚线符号转换为正确的$,而不必依次尝试每种可能性(例如com.example.test.Enum2.Test,com.example.test.Enum2 $ Test,com .example.test $ Enum2 $ Test等等) – 2011-02-09 18:49:17