从泛型类返回数组

时间:2015-12-24 09:51:55

标签: java

当我运行此命令时出现ClassCastException错误,因为在运行代码时将d隐式转换为double。但是,如果我将对d in的引用更改为Object[],则它不能成为set函数的参数。如果我将set函数更改为接受Object[],那么一切正常,但如果有人对不属于N类型的对象调用set,则该类将在运行时失败。

我需要一个可以get()旧数组(或其克隆)并且可以set()数据到新数组的解决方案。

public class Foo<N> {

    public static void main(String[] args) {
        Foo<Double> foo = new Foo<Double>();
        Double[] d = foo.get();

        // do stuff to d ...

        foo.set(d);
    }

    N[] data;

    public Foo() {
        data = (N[]) new Object[2];
    }

    public N[] get() {
        return (N[]) data;
    }

    public void set(N[] data) {
        this.data = data;
    }

}

4 个答案:

答案 0 :(得分:1)

这是一个诀窍。

class Foo<N> {

    // Deliberately no parameters.
    N[] myArray = makeArray();

    private N[] makeArray(N... ns) {
        return ns;
    }

    public N[] get() {
        return myArray;
    }
}

这可能看起来没有强制转换(这是一件好事),但事实上,它只是由varargs系统完成。

答案 1 :(得分:1)

要使用正确的运行时类型创建数组,需要某种类型的运行时表示。像Foo<N>这样的泛型类没有N的运行时表示。

有两种解决方案:

  1. 请改用List<N>。如果可能的话,这是最好的!
  2. 通过将N传递给Class<N>手动添加Foo的运行时表示,使用java.lang.reflect.Array.newInstance创建数组。
  3. 第二个解决方案的代码:

    public Foo(Class<N> newDataClass) {
        data = (N[]) Array.newInstance(newDataClass, 2);
    }
    
    Foo<Double> foo = new Foo<>(Double.class);
    

    修改

    如果您要执行的操作是获取现有Double数组的副本,则可以使用(N[]) data.clone()执行此操作。设置它不会有问题。

答案 2 :(得分:1)

一种方便(但冗长)的方法是更改​​构造函数以使用数组类型获取伪参数,因为您知道它在main方法中是双精度。

  public class Foo<N> {
         N[] data;

         public Foo(N inType) {
             data = (N[]) Array.newInstance(inType.getClass(), 2) ;
         }

         public N[] get() {
             return (N[]) data;
         }

         public void set(N[] data) {
             this.data = data;
         }

         public static void main(String[] args) {
             Foo<Double> foo = new Foo<Double>(new Double(0));
             Double[] d = foo.get();
             // do stuff to d ...
             foo.set(d);
         }

  }

答案 3 :(得分:0)

泛型的问题是,它在运行时没有任何特定类型。它只是类Object,这意味着,创建这样的对象是完全没有意义的,因为事实上,你只需要创建一个Object类型的对象。

但是,您可以从类外部创建此类对象,因为此处已知对象的实际类型(Double)。因此,我建议使用某种List(可以是动态的)来存储值。