Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning an Array from a generic class

Tags:

java

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

}
like image 524
avisnacks Avatar asked Dec 24 '15 09:12

avisnacks


People also ask

Can you make an array of generics?

Generic array creation is not allowed in Java. Hope this helps!! If you need to know more about Java, join our Java certification course online.

Is it possible to return an array in Java?

We can return an array in Java from a method in Java. Here we have a method createArray() from which we create an array dynamically by taking values from the user and return the created array.

How do you return an array element in Java?

get() is an inbuilt method in Java and is used to return the element at a given index from the specified Array.


2 Answers

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:

  1. Use a List<N> instead. This is best if it is possible!
  2. Manually add a runtime representation of 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.

like image 61
Lii Avatar answered Oct 10 '22 11:10

Lii


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.

like image 31
OldCurmudgeon Avatar answered Oct 10 '22 10:10

OldCurmudgeon