【问题标题】:Type T cannot be instantiated directly (tring to swap using generics)类型 T 不能直接实例化(使用泛型进行交换)
【发布时间】:2020-11-02 04:06:54
【问题描述】:

我正在尝试使用泛型类型进行交换,但在倒数第三行出现上述错误 “新 T[输出.size()]);” 有谁知道我该如何解决这个问题?

public class Exchange {
    public static <T> T[] swap(T[] a, int i, int j){
        int length = a.length;
        ArrayList<T> output = new ArrayList<T>();
        for (int b = 0; i<length;i++){
            if (b==i){
                output.add(a[j]);
            }else if (b==j){
                output.add(a[i]);
            }else {
                output.add(a[b]);
            }
        }
        T[] outputs = output.toArray(new T[output.size()]);
        return outputs;
    }
}

【问题讨论】:

    标签: java arrays generics swap


    【解决方案1】:

    这是因为你想要的在某种程度上是不可能的(但在这种特定情况下,好消息!你可以做到这一点)。

    泛型是编译器的想象。它不在类文件中,也不属于运行时类型。泛型(T)用于“链接”事物。它告诉编译器:无论何时调用此方法,返回类型和第一个参数都是“链接的”——它们是同一件事。

    换句话说,泛型没有被具体化:鉴于:

    List<String> list = new ArrayList<String>();
    getStringOut(list); // this method is not possible
    

    不可能的原因是list 是一个指向ArrayList 实例的变量,而该实例实际上并不知道它是一个字符串列表。这完全是 javac 做的,检查你从未向list 添加非字符串。列表本身并不关心(它不会知道您是否尝试向其添加整数),类验证器也不介意。只是javac不会让你。

    这与被具体化的数组形成对比:

    String[] x = new String[10];
    getStringOut(x); // this CAN be done!
    

    这就是为什么new T[] 是完全不可能的。

    但是,你说有好消息

    你在这里走运了——你有一个数组(具体类型!)并且你希望输出数组有完全相同的组件类型,所以你实际上可以这样做:

    Class<?> componentType = a.getComponentType();
    T[] outputs = (T[]) java.lang.reflect.Array.newInstance(componentType, output.size());
    

    有点不幸的是,强制转换会导致 javac 发出警告,但是你可以忽略这种警告(通常你不应该)。 javac 不确定newInstance 的输出是否真的保证是一个Ts 的数组,但是,你可以用你的眼球验证一定是这样,因此,你可以@SuppressWarnings 这个了。

    但你在这里很幸运——你有一个 T 数组,这是你能做到这一点的唯一方法。或者像Supplier&lt;T&gt; 这样的工厂函数,否则这是不可能的。

    注意:您当然总是可以“就地”交换,修改输入数组。

    【讨论】:

      猜你喜欢
      • 2023-01-10
      • 1970-01-01
      • 2013-10-03
      • 2011-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多