Explain Codes LogoExplain Codes Logo

How to create a generic array in Java?

java
type-safety
generics
reflection
Alex KataevbyAlex Kataev·Jan 16, 2025
TLDR

The best way to create a generic array in Java is through reflection, using the Array.newInstance() method. This helps us to circumvent Java's type erasure issue by explicitly defining the class of the generic type:

public class GenericArray<T> { private T[] array; public GenericArray(Class<T> componentType, int size) { array = (T[]) Array.newInstance(componentType, size); } // Getters and setters don't get the spotlight this time. } // Example of instantiation: GenericArray<Integer> intArray = new GenericArray<>(Integer.class, 5);

In this code, an array for the generic type T is created without triggering unchecked cast warnings, making it safe and easy to use.

Java features a concept known as type erasure that maintains backwards compatibility with older Java versions. It's like Java's memory eraser: it clears out type parameters of generics, replacing them with their bounds or Object for unbounded types.

The Array.newInstance() method is central in the quest to create generic arrays, as it helps to outsmart type erasure by accepting a Class argument, thereby retaining your array’s true identity at runtime.

The plot twist is that when we cast the result of Array.newInstance() to (T[]), it's an unchecked operation because the compiler can't guarantee it's a safe move at compile-time (it didn't bring its safety gear). So, we use @SuppressWarnings("unchecked") to communicate that the developer is okay with living on the edge.

Striking gold with class literals as runtime type tokens

In a reflection context, class literals serve as passports at runtime. They give us the exact type of the array elements, allowing for a great generic array creation:

// Class literal used to create a typed array of gold...just kidding, of Strings. String[] strings = GenericArray.newInstance(String.class, 10);

With this approach, we can create an array of the precise type we want, foregoing casting an array of Object.

Think collections, not arrays

Despite being able to create generic arrays, the rift between Java arrays and generics can be bridged more comfortably with Collections, due to arrays' covariant nature.

Consider using the ArrayList<T> instead. It's like a shape-shifter, adapting to any generic type without requiring a drop of reflection:

ArrayList<T> list = new ArrayList<T>(); // No casting spell required.

Did I mention that lists are adjustable to your size preference and come with an assortment of utility tools? Arrays can't keep up.

Journey into multi-dimensional arrays

To create multi-dimensional generic arrays, simply pass the array dimensions into newInstance():

T[][] twoDimArray = (T[][]) Array.newInstance(componentType, firstDimSize, secondDimSize);

This makes it possible to create multi-dimensional generic arrays where each dimension comes prepped with a size tag.

Stay safe with varargs and array copying

When needing to create a generic array with varargs, deploy methods like Arrays.copyOf and the @SafeVarargs annotation. This resolves the heap pollution issue to keep your environment tidy:

@SafeVarargs public static <T> T[] createArray(T... elements) { // Light bulb moment: re-assigns the contents of elements to a new array return Arrays.copyOf(elements, elements.length, (Class<? extends T[]>) elements.getClass()); }

Practical when you know the initial elements at compile-time. Performs type-safely, without the need to live dangerously with unchecked casts.