【问题标题】:Getting the class of List<T>获取 List<T> 的类
【发布时间】:2014-05-07 19:30:34
【问题描述】:

请考虑以下 3 个 Java 类:

超类:

public abstract class Column<T>
{

    private final Class<T> type;
    private final String name;


    public Column(Class<T> type, String name)
    {
        this.type = type;
        this.name = name;
    }

    public Class<T> getType()
    {
        return type;
    }

    // ...

}

工作子类:

public class FloatColumn extends Column<Float>
{   

    public FloatColumn(String name)
    {
        super(Float.class, name);
    }

    // ...

}

有问题的子类:

public class ListColumn<L extends List<T>, T> extends Column<L>
{   

    public ListColumn(String name)
    {
        super((Class<L>) List.class, name);
    }

    // ...

}

有问题的子类 (ListColumn) 在 Eclipse 中编译良好,Java 编译器合规性设置为 1.6。但是,当通过 Maven 编译时(使用 JDK 编译器,源和目标设置为 1.6),我在 super() 构造函数中的 super() 调用处收到 Inconvertible types 错误。

编辑: Eclipse 确实警告了这一行 (Type safety: Unchecked cast from Class&lt;List&gt; to Class&lt;L&gt;)。

我知道 Eclipse 不使用 JDL 编译器,显然它使用的编译器没有 JDK 严格。

但是,我的问题是如何使这段代码在 1.6 JDK 编译器上工作。

换句话说,我如何使用符合预期Class&lt;L&gt; 类型的参数调用超级构造函数,其中L 被限制为extends List&lt;T&gt;

最好我只想在 ListColumn 构造函数中进行更改,而不是在 Column 类中进行更改。

【问题讨论】:

  • 查看这一行的警告super((Class&lt;L&gt;) List.class, name);
  • 我在该行没有收到警告(至少在 Eclipse 中没有)。相反,我得到了一个编译错误。你知道我应该在代码中改变什么吗?
  • 我得到 Type safety: Unchecked cast from Class to Class in Eclipse.
  • 哎呀,你是对的。我没有看到警告,因为我在构造函数上有 @SuppressWarnings("unchecked")
  • 万岁,成功了!谢谢!

标签: java eclipse maven generics collections


【解决方案1】:

也许对你有帮助。

super((Class<L>)(Class<?>)List.class, name);

注意:它会显示 WARNING 但您可以使用 @SuppressWarnings("unchecked") 禁止它


欲了解更多信息,请查看Class object of generic class (java)

【讨论】:

  • 在强制编译器接受List.class 作为Class&lt;ArrayList&gt;Class&lt;LinkedList&gt; 时,您没有感觉到代码异味吗?我同意在某些情况下您需要欺骗编译器,因为它太愚蠢而无法弄清楚;但这肯定不是其中之一。
【解决方案2】:

假设我按如下方式实例化您的类:

ListColumn<ArrayList<String>, String> listColumn = new ListColumn<ArrayList<String>, String>("column");

现在,您的代码将尝试将 List.class 转换为 Class&lt;ArrayList&gt;,但事实并非如此。

如果您想允许客户端使用您的T 泛型类型的子类型,您可以在您的Column 类中使用协方差。例如,将Column 构造函数更改为:

public Column(Class<? extends T> type, String name)

将允许您在 ListColumn 中调用 super 而无需任何强制转换,因为现在允许 List 的任何子类型,但以类型安全的方式。

至于仅通过警告就欺骗编译器接受任何类型的泛型转换,您可以使用最肮脏的“双重转换”技巧,简单地消除泛型,这样编译器就不会再赶上您的代码了:

List<Integer> l = new ArrayList<Integer>();
List<String> s = (List<String>) (List) l;

但这真的是你想要的吗?

【讨论】:

  • new ListColumn&lt;&gt; 是一个 JAVA 7 语法。 OP 在问 但是,我的问题是如何让这段代码在 1.6 JDK 编译器上工作
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多