Java:静态嵌套类和反射:“$”vs。

时间:2022-09-04 17:04:05

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?

如果我有一个类com.example.test.Enum2。在下面的代码中测试,为什么getCanonicalName()返回com.example.test.Enum2。forname()要求“com.example.test”。Enum2美元这样测试”作为参数?

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?

是否有一种方法可以保持一致,以便我可以通过枚举值的名称来序列化/反序列化枚举值,而不必检查每个$ 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());
    }
}

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.

使用getCanonicalName()的输出(仅用虚名)和Class.forName()的方式进行序列化/反序列化,并尝试每一种可能性,例如:first“com.example.test.Enum2”。测试”,那么“com.example.test。com . example。Enum2美元这样测试”,那么“测试Enum2测试”美元,这样美元等。

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().

b.使用适当的$表示法,使Class.forName()第一次正确工作。但是这需要我实现一个getCanonicalName()的替代方法,它产生一个与Class.forName()一致的字符串。

I am leaning toward approach (b), partially from gut feel, and partially because approach (a) has ambiguities if there are package names with capital letters: com.example.Test.Enum2 and com.example.Test$Enum2 can both be valid inputs to Class.forName() if there is a com/example/Test/Enum2.java, and a com/example/Test.java containing an Enum2 inner class.

我倾向于方法(b),部分来自于直觉,部分原因是方法(a)如果有大写字母的包名,就有歧义。com . example。Enum2和这样如果有一个com/example/Test/Enum2,那么Test$Enum2都可以是Class.forName()的有效输入。java和com/example/Test。包含枚举2内部类的java。

...but I don't know how to implement it. Any ideas?

…但是我不知道如何实现它。什么好主意吗?

2 个解决方案

#1


9  

ARGH: I should have been simply using Class.getName() instead of Class.getCanonicalName().

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

#2


5  

Well, the docs for getCanonicalName state:

好的,getCanonicalName状态的文档:

Returns the canonical name of the underlying class as defined by the Java Language Specification.

返回Java语言规范定义的底层类的规范名。

(Emphasis mine.)

(强调我的。)

In Java the language, nesting is indicated with a dot. As far as libraries and the VM are concerned, the nested class is just a class with a $ in the name.

在Java语言中,嵌套用点表示。就库和VM而言,嵌套类只是一个名称中有$的类。

You haven't said what kind of serialization you're talking about - so long as you're consistent for both directions, it should be fine.

您还没有说过您正在讨论的是哪种序列化——只要您在两个方向上都是一致的,就应该没问题。

#1


9  

ARGH: I should have been simply using Class.getName() instead of Class.getCanonicalName().

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

#2


5  

Well, the docs for getCanonicalName state:

好的,getCanonicalName状态的文档:

Returns the canonical name of the underlying class as defined by the Java Language Specification.

返回Java语言规范定义的底层类的规范名。

(Emphasis mine.)

(强调我的。)

In Java the language, nesting is indicated with a dot. As far as libraries and the VM are concerned, the nested class is just a class with a $ in the name.

在Java语言中,嵌套用点表示。就库和VM而言,嵌套类只是一个名称中有$的类。

You haven't said what kind of serialization you're talking about - so long as you're consistent for both directions, it should be fine.

您还没有说过您正在讨论的是哪种序列化——只要您在两个方向上都是一致的,就应该没问题。