简体   繁体   中英

Java generics and arrays construction

Suppose I have a generic class with a generic parameter T which is a Number subclass. I would like to initialize an array of T during class construction. Is it possible? If yes how? If not why?

public class AClass<T extends Number>{

    private T array[];
    private int arrayOfInt[];

    public AClass(int size){
        arrayOfInt = new int[size];
        array = ? //what should I put here?
    } 
} 

T is only know at compile time. It is not know at runtime and thus you cannot initilise the contents of the array. However you can create the array, every value will be null .

array = (T[]) new Number[size];

EDIT: The problem with creating instances of any type is you need to know what is the default value you want and which constructor you want to call. eg there is no new Double()

As mentioned below, double[] will be more efficient and faster than Number[] and unless you need large long values, it will be able to store every possible value.

If you want to use arrays, there are two options:

  1. Peter Lawrey's answer, array = (T[]) new Number[size]; . You have to make sure never to return or pass this variable to code outside of the class that expect it to be an array of a particular type, which will cause an exception.

  2. Declare array as type Number[] , then just do array = new Number[size]; . The downside of this is that when you get anything out of it you will need to explicitly cast to T to use it as such.

The two are the same after type erasure, and they will both cause unchecked cast warning, so it's really a matter of personal preference. The former is more convenient, while the latter is more formally correct (you are not pretending it's a type it's not).

Alternately, some people will tell you to use an ArrayList<T> instead. But internally, an ArrayList is still implemented using one of these two options.

This is not possible.

Because Java generics use type erasure , the type of T isn't known at runtime, so you can't create an array of it.

Other options than mentioned are to use toArray(T[]) or java.lang.reflect.Array :

public class AClass<T extends Number>{
    private T array[];

    public AClass(final int size, T[] a){
        array = (new ArrayList<T>() {{
            for (int i = 0; i < size; i++) {
                add(null);
            }
        }}).toArray(a);
    }

    public AClass(int size, Class<T[ ]> clazz) {  
        array = clazz.cast(java.lang.reflect.Array.newInstance(
            clazz.getComponentType( ), size));  
    }  

    public static void main(String[] args) {
        System.out.println("toArray: "
                + new AClass<Double>(42, new Double[]{}).array.length);
        System.out.println("java.lang.reflect.Array: "
                + new AClass<Double>(42, Double[].class).array.length);
    }
} 

PS. solution using reflection is close to one suggested in Langer's Generics FAQ ( Utilities.createBuffer ): How do I generically create objects and arrays?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM