Java:使用枚举进行动态类型转换
我正在尝试执行以下操作:
public void setContents(Object[] values)
{
...
//A. this works
mRank =
((String)(values[Columns.RANK.index]));
//B. doesn't work (entire line underlined by netbeans)
mRank =
(Columns.RANK.type.cast(values[Columns.RANK.index]));
//incompatible types: required java,lang.String found: java.lang.Object
//C. doesn't work (first RANK is underlined by netbeans)
mRank =
((Columns.RANK.type)(values[Columns.RANK.index]));
//cannot find symbol symbol: class RANK location: blah.blah.Columns
...
}
其中 columns 是内部枚举,如下所示:
public static enum Columns
{
RANK(0, "Rank", String.class),
NUMBER(1, "Number", Integer.class);
public String text;
public Class type;
public int index;
private Columns(int idx, String text, Class clasz)
{
this.type = clasz;
this.text = text;
this.index = idx;
}
}
我理解为什么行 B
不起作用,但我不明白的是为什么 C 不起作用。如果我在类型转换以外的其他地方使用 Columns.RANK.type ,它工作得很好,但是当我尝试对类进行类型转换时,它编译时说找不到 RANK
在枚举中,情况不应该是这样。
如何解决?
谢谢!
I am trying to do something along the lines of:
public void setContents(Object[] values)
{
...
//A. this works
mRank =
((String)(values[Columns.RANK.index]));
//B. doesn't work (entire line underlined by netbeans)
mRank =
(Columns.RANK.type.cast(values[Columns.RANK.index]));
//incompatible types: required java,lang.String found: java.lang.Object
//C. doesn't work (first RANK is underlined by netbeans)
mRank =
((Columns.RANK.type)(values[Columns.RANK.index]));
//cannot find symbol symbol: class RANK location: blah.blah.Columns
...
}
Where columns is an inner enum, like so:
public static enum Columns
{
RANK(0, "Rank", String.class),
NUMBER(1, "Number", Integer.class);
public String text;
public Class type;
public int index;
private Columns(int idx, String text, Class clasz)
{
this.type = clasz;
this.text = text;
this.index = idx;
}
}
I understand why line B
doesn't work, but what I don't get is why C
doesn't work. If I use Columns.RANK.type
anywhere else other than in a type cast, it works fine, but one I attempt to do a typecast with the class, it compiles saying it cannot find RANK
in the enum, which shouldn't be the case.
How to work around?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
C
不起作用,因为Columns.RANK.type
在编译时无法访问。但是,
B
可以使用自定义的基于泛型的类而不是enum
来实现:C
doesn't work, becauseColumns.RANK.type
is not accessible at compile time.However,
B
can be implemented using a custom generic-based class instead ofenum
:简而言之,没有好的方法可以使用枚举来做到这一点。 axtavt 的答案可能是您最好的选择。关于为什么 C 不起作用的问题,trashgod 基本上是正确的,但也许它需要更多的解释。
您需要考虑编译器如何解释
C
。这里重要的是String
和String.class
之间的区别。您有一个类似于(String)foo
的转换表达式。在这样的表达式中,您要转换为的类型(在该示例中为String
)必须是类型的名称。您不会编写(String.class)foo
,因为没有名为String.class
的类。 (相反,String.class
只是一个对象,是反映String
类型的java.lang.Class
实例。)因此,当编译器看到
(Columns.RANK.type)(values[Columns.RANK.index])
,它说“啊,这是一个转换表达式。所以,开头括号中的位必须是bguiz 想要转换为的类型的名称。”然后它会尽职尽责地查找名为 Columns.RANK.type 的类型。由于它是类型的名称,因此预计其格式为my.package.containing.a.Type.AndMaybe.SomeInnerTypes
。因此,它将其围绕.
进行拆分,找到类型Columns
,然后继续查找名为RANK
的内部类型列
。没有这样的内部类型(常量RANK
不算在内),因此它会因您引用的错误而失败。(如果发现,它将继续寻找另一个名为
type
的内部类型,并且枚举中的字段不会计算在内。)请记住,编译器只是遵循一堆愚蠢的规则。它并不关心您的
Columns
枚举中还有一个常量RANK
。它也不知道类型名称通常是大写的。因此,对于头脑中携带着所有上下文的人来说,它的错误消息有时很难解释。 :)The short answer is that there's no good way to do this with an enum. axtavt's answer is probably your best bet. trashgod is basically right about why
C
doesn't work, but perhaps it could use a bit more explanation.You need to think about how the compiler is interpreting
C
. What's important here is the distinction betweenString
andString.class
. You've got a casting expression like(String)foo
. In such an expression, the type that you're casting to (in that example,String
) has to be the name of a type. You wouldn't write(String.class)foo
, because there is no class calledString.class
. (Instead,String.class
is just an object, an instance ofjava.lang.Class
that reflects the typeString
.)So, when the compiler sees
(Columns.RANK.type)(values[Columns.RANK.index])
, it says "ah, this is a casting expression. So, the bit in parens at the beginning must be the name of the type that bguiz wants to cast to." Then it dutifully goes off and looks for a type namedColumns.RANK.type
. Since it's the name of a type, it's expecting it to be of the formmy.package.containing.a.Type.AndMaybe.SomeInnerTypes
. Thus, it splits it up around the.
s, finds the typeColumns
, and then goes off and looks for an inner type calledRANK
inColumns
. There is no such inner type (the constantRANK
doesn't count), so it fails with the error you quoted.(If it found that, it would continue looking for another inner type called
type
, and again, the field in the enum wouldn't count.)Remember that the compiler is just following a bunch of dumb rules. It doesn't care that you also have a constant
RANK
in yourColumns
enum. It also doesn't know that type names are usually upper-case. As a result its error messages are sometimes hard to interpret for a human who is carrying around all that context in his head. :)