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

发布于 2024-08-18 08:46:08 字数 1213 浏览 2 评论 0原文

我正在尝试执行以下操作:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

末骤雨初歇 2024-08-25 08:46:08

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; 
    } 
}

C doesn't work, because Columns.RANK.type is not accessible at compile time.

However, B can be implemented using a custom generic-based class instead of 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; 
    } 
}
少女的英雄梦 2024-08-25 08:46:08

简而言之,没有好的方法可以使用枚举来做到这一点。 axtavt 的答案可能是您最好的选择。关于为什么 C 不起作用的问题,trashgod 基本上是正确的,但也许它需要更多的解释。

您需要考虑编译器如何解释C。这里重要的是 StringString.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 between String and String.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 called String.class. (Instead, String.class is just an object, an instance of java.lang.Class that reflects the type String.)

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 named Columns.RANK.type. Since it's the name of a type, it's expecting it to be of the form my.package.containing.a.Type.AndMaybe.SomeInnerTypes. Thus, it splits it up around the .s, finds the type Columns, and then goes off and looks for an inner type called RANK in Columns. There is no such inner type (the constant RANK 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 your Columns 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. :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文