Reputation: 81
I get a ClassCastException
error when I run this because of the implicit cast of d to a double when I run the code. However, if I change reference to d in to Object[]
then it can't be a parameter to the set function. If I change the set function to accept an Object[]
then everything works fine, but then the class will fail at runtime if anyone calls set on an object that isn't of type N
.
I need a solution that can get()
the old array (or a clone thereof) and that can set()
data to a 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;
}
}
Upvotes: 7
Views: 160
Reputation: 12112
To create an array with the right runtime type requires some kind of runtime representation of that type. A generic class like Foo<N>
has no runtime representation of N
.
There are two solutions:
List<N>
instead. This is best if it is possible!N
by passing in a Class<N>
to Foo
, use java.lang.reflect.Array.newInstance
to create the 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 what you want to do is instead to get a copy of an existing Double
array you can do that with (N[]) data.clone()
. Setting it will not be a problem.
Upvotes: 1
Reputation: 14792
The problem with a generic is, that it does not have any specific type at runtime. It's just the class Object
, which means, that creating such object is completely pointless, because you would, in fact, just create an object of type Object
.
You can however create such objects from outside of the class, because the real type of the object is known here (Double
). Thus I would suggest to use some sort of List
, which can be dynamic, to store the values.
Upvotes: 0
Reputation: 1441
A convenient (but verbose) way to do this would be to change the constructor to take a dummy argument with the array type, since you know that it is double at 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);
}
}
Upvotes: 1
Reputation: 65813
There's a trick to this.
class Foo<N> {
// Deliberately no parameters.
N[] myArray = makeArray();
private N[] makeArray(N... ns) {
return ns;
}
public N[] get() {
return myArray;
}
}
This may look like there is no casting (which is a good thing) but actually there is, it is just being done by the varargs
system.
Upvotes: 1