Java:使用枚举的动态类型转换

时间:2010-01-22 01:15:53

标签: java enums casting

我正在努力做一些事情:

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

    ...
}

其中列是内部枚举,如下所示:

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,这应该是不是这样的。

如何解决?

谢谢!

3 个答案:

答案 0 :(得分:4)

C不起作用,因为在编译时无法访问Columns.RANK.type

但是,B可以使用基于自定义泛型的类而不是enum来实现:

class Columns<T>
{
    public static final Columns<String> RANK = new Columns<String>(0, "Rank", String.class);
    public static final Columns<Integer> NUMBER = new Columns<Integer>(1, "Number", Integer.class);

    public final Class<T> type;
    public final String text; 
    public final int index; 

    private Columns(int idx, String text, Class<T> clasz) 
    { 
        this.type = clasz; 
        this.text = text; 
        this.index = idx; 
    } 
}

答案 1 :(得分:2)

简短的回答是,使用枚举没有好办法。 axtavt的答案可能是你最好的选择。 trashgod基本上是正确的,为什么C不起作用,但也许它可以使用更多的解释。

您需要考虑编译器如何解释C。这里重要的是StringString.class之间的区别。你有一个像(String)foo这样的强制转换表达式。在这样的表达式中,您要转换的类型(在该示例中为String)必须是类型的名称。你不会写(String.class)foo,因为没有名为String.class的类。 (相反,String.class只是一个对象,java.lang.Class的一个实例反映了String类型。)

所以,当编译器看到(Columns.RANK.type)(values[Columns.RANK.index])时,它会说“啊,这是一个转换表达式。所以,开头的parens中的位必须是该类型的 name bguiz想要施展。“然后它尽职尽责地寻找名为Columns.RANK.type的类型。因为它是一个类型的名称,所以它期望它的形式为my.package.containing.a.Type.AndMaybe.SomeInnerTypes。因此,它会在.周围将其拆分,找到类型Columns,然后关闭并在RANK中查找名为Columns的内部类型。没有这样的内部类型(常量RANK不计数),因此它会因您引用的错误而失败。

(如果发现它,它将继续寻找另一个名为type的内部类型,并且再次,枚举中的字段将不计算。)

请记住,编译器只是遵循一堆愚蠢的规则。您并不关心RANK枚举中的Columns常数{{1}}。它也不知道类型名称通常是大写的。因此,它的错误信息有时很难解释为一个人在脑海里徘徊所有的背景。 :)

答案 2 :(得分:0)

因为它引用了class literal,所以表达式Columns.RANK.type的类型为Class<String>。它不是cast expression所需的 ReferenceType

附录:编译器认为您打算引用一个嵌套在RANK中的名为Columns的不存在的类。