Returning an array from a common class

I get a ClassCastException error when I run this due to the implicit cast of d to double when the code runs. However, if I change the link in d in to Object[] , then this cannot be a parameter for the set function. If I change the set function to accept Object[] , then everything will work fine, but then the class will fail at runtime if someone calls set on an object that is not of type N

I need a solution that can get() use the old array (or its clone) and which can set() pass data to the new array.

 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; } } 
+7
java
source share
4 answers

To create an array with the correct runtime type, some representation of the runtime of this type is required. A generic class, such as Foo<N> , has no run-time representation of N

There are two solutions:

  • Use List<N> instead. It is better if possible!
  • Manually add a run-time view of N by passing to Class<N> in Foo , use java.lang.reflect.Array.newInstance to create an array.

Code for the second solution:

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

EDIT:

If you want to make a copy of an existing Double array, you can do this with (N[]) data.clone() . Installing it will not be a problem.

+1
source share

There is a trick.

 class Foo<N> { // Deliberately no parameters. N[] myArray = makeArray(); private N[] makeArray(N... ns) { return ns; } public N[] get() { return myArray; } } 

It may seem like there is no casting (this is good), but in fact it only happens with the varargs system.

+1
source share

A convenient (but true) way to do this is to change the constructor to accept a dummy argument with the type of the array, since you know that it is double in your main method.

  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); } } 
+1
source share

The problem with the general is that at run time it does not have a specific type. It's just an Object class, which means that creating such an object is completely pointless, because in fact you would just create an object of type Object .

However, you can create such objects outside the class, because the real type of the object ( Double ) is known here. So, I would suggest using some sort of List , which can be dynamic, to preserve the values.

0
source share

All Articles