Java 从泛型类返回数组
当我运行这个时,我得到了一个Java 从泛型类返回数组,java,Java,当我运行这个时,我得到了一个ClassCastException错误,因为当我运行代码时,隐式地将d转换为double。但是,如果我将中对d的引用更改为Object[],则它不能作为set函数的参数。如果我将set函数更改为接受一个对象[],则一切正常,但如果有人在类型不为N的对象上调用set,则该类将在运行时失败 我需要一个可以get()旧数组(或其克隆)和set()数据到新数组的解决方案 public class Foo<N> { public static void
ClassCastException
错误,因为当我运行代码时,隐式地将d转换为double。但是,如果我将中对d的引用更改为Object[]
,则它不能作为set函数的参数。如果我将set函数更改为接受一个对象[]
,则一切正常,但如果有人在类型不为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;
}
}
公共类Foo{
公共静态void main(字符串[]args){
Foo-Foo=新的Foo();
Double[]d=foo.get();
//做些事情来。。。
foo.set(d);
}
N[]数据;
公共食物({
数据=(N[])新对象[2];
}
公共N[]获取(){
返回(N[])个数据;
}
公共无效集(N[]数据){
这个数据=数据;
}
}
这有个窍门
class Foo<N> {
// Deliberately no parameters.
N[] myArray = makeArray();
private N[] makeArray(N... ns) {
return ns;
}
public N[] get() {
return myArray;
}
}
class-Foo{
//没有参数。
N[]myArray=makeArray();
专用N[]生成数组(N…ns){
返回ns;
}
公共N[]获取(){
返回myArray;
}
}
这看起来可能没有强制转换(这是一件好事),但实际上有,它只是由
varargs
系统完成的。要创建具有正确运行时类型的数组,需要该类型的某种运行时表示。像Foo
这样的泛型类没有N
的运行时表示
有两种解决方案:
列表
。这是最好的,如果可能的话李>
N
的运行时表示形式,方法是将类
传递到Foo
,使用java.lang.reflect.Array.newInstance
创建数组public Foo(Class<N> newDataClass) {
data = (N[]) Array.newInstance(newDataClass, 2);
}
Foo<Double> foo = new Foo<>(Double.class);
public Foo(类newDataClass){
data=(N[])Array.newInstance(newDataClass,2);
}
Foo-Foo=新的Foo(Double.class);
编辑: 如果您想做的是获取现有
双
数组的副本,则可以使用(N[])data.clone()
。设置它不会是一个问题。一个方便(但详细)的方法是将构造函数更改为使用数组类型的伪参数,因为您知道它在主方法中是双精度的
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);
}
}
公共类Foo{
N[]数据;
公共Foo(N inType){
data=(N[])Array.newInstance(inType.getClass(),2);
}
公共N[]获取(){
返回(N[])个数据;
}
公共无效集(N[]数据){
这个数据=数据;
}
公共静态void main(字符串[]args){
Foo-Foo=新Foo(新双精度(0));
Double[]d=foo.get();
//做些事情来。。。
foo.set(d);
}
}
泛型的问题是,它在运行时没有任何特定类型。它只是类对象
,这意味着创建这样的对象是完全没有意义的,因为实际上,您只需要创建一个类型为对象
的对象
但是,您可以从类之外创建这样的对象,因为这里知道对象的真实类型(
Double
)。因此,我建议使用某种类型的列表
,它可以是动态的,存储值。可能的重复不是q的重复。您可以使用它提取类型和数组。newInstance创建数组可能我不清楚这个问题,但在我的情况下数组已经实例化,我需要对其进行更改。所以我需要从foo那里得到它做点什么。然后重置它。我没有在构造函数中实例化它的解决方案。@在您的示例中,您在Foo
构造函数中创建了数组。这不是它应该如何工作的吗?你能更新这个问题让它更清楚吗?@OldCurmudgeon:这行不通。您将始终在myArray
中获得一个对象
数组。当初始化器调用makeArray
时,没有N
留下的痕迹,它已被擦除。泛型vararg方法始终创建对象
数组。根本不可能创建泛型类型的数组。例如,@Lii-擦除后所有数组都是对象[]
。这个把戏只是避免了施放。好吧,看来我误解了目的,对不起。“擦除后,所有数组都是Object[]
”我不确定您在这里的意思。在运行时,泛型类型的所有数组都将是Object[]
。但不是其他的,Double[]
和Double[]
将具有这些运行时类型。擦除只涉及泛型类型。