2015-12-24 53 views
7

当我运行此代码时,得到ClassCastException错误,因为我在运行代码时将d隐式转换为double。但是,如果我将对d的引用更改为Object[],那么它不能作为设置函数的参数。如果我改变所设定的功能来接受Object[]然后一切工作正常,但是后来有人来电话的对象,它是N类型的未设置的课程将在运行时失败。从泛型类中返回数组

我需要一个解决方案,可以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; 
    } 

} 
+1

可能的重复[如何在Java中创建通用数组?](http://stackoverflow.com/questions/529085/how-to-create-a-generic-array-in-java) – Julien

+0

这不是一个那个q的重复。 – avisnacks

+0

你可以使用这个http:// stackoverflow。com/a/3403976/2513573来提取类型和Array.newInstance来创建数组 – AdamSkywalker

回答

1

要创建具有合适的运行时类型的阵列需要某种该类型的运行时表示的。像Foo<N>这样的通用类没有运行时表示N

解决办法有两个:

  1. 使用List<N>代替。如果可能的话,这是最好的!
  2. 通过传递Class<N>Foo手动添加运行时表示N,使用java.lang.reflect.Array.newInstance来创建阵列。

代码的第二个解决方案:

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

Foo<Double> foo = new Foo<>(Double.class); 

编辑:

如果你想要做的是什么,而不是让现有Double数组,你可以做副本与(N[]) data.clone()。设置它不会是一个问题。

1

这是一个窍门。

class Foo<N> { 

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

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

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

这可能看起来像没有铸造(这是一件好事),但实际上存在,它只是由varargs系统来完成。

+0

也许我不清楚问题,但在我的情况下,该数组已经实例化,我需要对其进行更改。所以我需要从foo做到这一点。并重置它。我不能有一个解决方案在constructer中实例化它。 – avisnacks

+2

@avisnacks:在你的例子中,你在'Foo'构造函数中创建数组。这不是它应该如何工作?你能否更新这个问题来使这个更清楚? – Lii

+0

@OldCurmudgeon:这不起作用。你总是会在'myArray'中得到一个'Object'数组。当初始化程序调用'makeArray'时,没有剩下'N'的痕迹,它已被擦除。通用可变参数方法总是创建“对象”数组。根本不可能创建泛型类型的数组。例如在[Java教程](https://docs.oracle.com/javase/tutorial/java/generics/restrictions.html#createArrays)中对此进行了描述。 – Lii

1

一个方便(但是详细)的方法是更改​​构造函数以使用数组类型的伪参数,因为您知道它在主方法中是双重的。

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

    } 
0

与通用的问题是,它并没有在运行任何特定的类型。这只是类Object,这意味着创建这样的对象是完全没有意义的,因为实际上,您只需创建一个类型为Object的对象。

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