Java:静态嵌套类和反射:“$”与“。”
如果我有一个 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.使用正确的 $ 符号,以便 Class.forName()
第一次就可以正常工作。但这需要我实现 getCanonicalName() 的替代方案,以生成与 Class.forName() 一致的字符串。
我倾向于方法 (b),部分是出于直觉,部分是因为如果包名称带有大写字母,则方法 (a) 会含糊不清: com.example.Test.Enum2 和 com.example.Test$Enum2 都可以是如果存在 com/example/Test/Enum2.java 和包含 Enum2 内部类的 com/example/Test.java,则为 Class.forName()
的有效输入。
...但我不知道如何实现它。有什么想法吗?
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 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.
...but I don't know how to implement it. Any ideas?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
ARGH:我应该简单地使用
Class.getName()
而不是Class.getCanonicalName()
。ARGH: I should have been simply using
Class.getName()
instead ofClass.getCanonicalName()
.好吧, getCanonicalName 的文档指出:
(强调我的。)
在Java语言中,嵌套用点表示。就库和VM而言,嵌套类只是名称中带有$的类。
您还没有说您正在谈论哪种序列化 - 只要两个方向保持一致,就应该没问题。
Well, the docs for
getCanonicalName
state:(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.
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.