Question
In Java, direct generic array creation is not allowed because of how generics are implemented. For example, this code does not compile:
public class GenSet<E> {
private E[] a;
public GenSet() {
a = new E[10]; // Error: generic array creation
}
}
How can this be implemented while preserving type safety?
One common solution uses reflection:
import java.lang.reflect.Array;
class Stack<T> {
private final T[] array;
public Stack(Class<T> clazz, int capacity) {
array = (T[]) Array.newInstance(clazz, capacity);
}
}
Why does this approach work, and what is happening behind the scenes in Java?
Short Answer
By the end of this page, you will understand why new T[] or new E[] is illegal in Java, how type erasure causes this limitation, how Array.newInstance(...) works, and when you should prefer arrays versus collections like ArrayList. You will also see how to use reflective array creation carefully and safely in real code.
Concept
Java generics and Java arrays enforce type information in different ways.
- Arrays are reified: they know their element type at runtime.
- A
String[]knows it is aString[]while the program is running. - Because of that, Java can reject invalid stores at runtime.
- A
- Generics are erased: most generic type information does not exist at runtime.
List<String>andList<Integer>both become justListat runtime.
This mismatch is the reason Java does not allow:
new T[10]
When Java compiles generic code, T is erased. At runtime, Java would not know what exact array type to create. But arrays require a real runtime component type such as String.class, Integer.class, or Object.class.
Why Java forbids generic array creation
Suppose Java allowed this:
T[] data = new T[];
Mental Model
Think of a generic type like T as a label that exists mainly during compilation, while an array is a box that must have its item type stamped on it at runtime.
- A generic says: “Trust me, this class works with some type.”
- An array says: “I need the exact item type right now.”
So new T[10] fails because the array asks, “What exact type should I stamp on this box?” and generics reply, “That information was erased.”
Passing Class<T> is like handing the factory a blueprint:
- Without
Class<T>: “Build me a box for some unknown type.” - With
Class<T>: “Build me a box forStringitems.”
Then the factory can produce a real String[].
Syntax and Examples
The common pattern is to pass a Class<T> token into the constructor and use reflection to create the array.
import java.lang.reflect.Array;
public class GenericBuffer<T> {
private final T[] items;
@SuppressWarnings("unchecked")
public GenericBuffer(Class<T> clazz, int size) {
items = (T[]) Array.newInstance(clazz, size);
}
public void set(int index, T value) {
items[index] = value;
}
public T get(int index) {
return items[index];
}
public int size() {
return items.length;
}
}
Usage:
public class Main {
public static void main(String[] args) {
GenericBuffer<String> buffer = <>(String.class, );
buffer.set(, );
buffer.set(, );
System.out.println(buffer.get());
System.out.println(buffer.size());
}
}
Step by Step Execution
Consider this code:
import java.lang.reflect.Array;
public class Demo<T> {
private final T[] values;
@SuppressWarnings("unchecked")
public Demo(Class<T> clazz, int size) {
values = (T[]) Array.newInstance(clazz, size);
}
public void setFirst(T value) {
values[0] = value;
}
public T getFirst() {
return values[0];
}
}
Used like this:
Demo<String> demo = new Demo<>(String.class, 2);
demo.setFirst("hello");
String result = demo.getFirst();
Step by step
1. Demo<String> is created
At compile time, T is treated as String in this usage.
Real World Use Cases
Generic arrays appear less often than generic collections, but they still matter in some practical situations.
Common use cases
- Custom data structures
- Stacks
- Queues
- Ring buffers
- Heaps
- Performance-sensitive code
- Arrays can be faster and more memory-efficient than some collection wrappers.
- Libraries that need fixed-size storage
- Internal buffers for parsing, caching, or batch processing.
- Bridging with APIs that require arrays
- Some older Java APIs or lower-level code still work naturally with arrays.
Example scenarios
Fixed-capacity stack
A parser or expression evaluator may use a generic stack backed by an array.
Message buffer
A messaging system may keep a fixed-size array of events before flushing them.
Object pools
A framework may store reusable objects in an internal array for speed.
In all of these cases, developers often either:
- use
Object[]internally, or - create a typed array with
Array.newInstance(...)if a realT[]is needed.
Real Codebase Usage
In real projects, developers usually choose one of three patterns.
1. Prefer collections when possible
This is the most common approach:
List<T> items = new ArrayList<>();
Why teams prefer it:
- no generic array creation problem
- flexible resizing
- clearer APIs
- fewer unchecked casts
2. Use Object[] internally with controlled casts
This is common in internal implementations of data structures.
public class Bag<T> {
private final Object[] items;
private int size;
public Bag(int capacity) {
items = new Object[capacity];
}
public void add(T item) {
items[size++] = item;
}
@SuppressWarnings("unchecked")
public T get(int index) {
return (T) items[index];
}
}
Common Mistakes
1. Trying to write new T[] directly
Broken code:
public class Box<T> {
private T[] items = new T[10];
}
Why it fails:
- Java does not know
Tat runtime. - Generic type parameters are erased.
How to avoid it:
- use
Array.newInstance(...), or - use
Object[], or - use a collection like
ArrayList<T>.
2. Assuming generics and arrays work the same way
Broken assumption:
List<String> list = new ArrayList<>();
// list knows String at runtime? No, not in the same way arrays do.
Arrays keep runtime component type information; generic type arguments usually do not.
3. Using the wrong Class<T> token
Broken code:
Comparisons
| Concept | Runtime type info | Compile-time type safety | Can create directly with new? | Notes |
|---|---|---|---|---|
String[] | Yes | Yes | Yes | Arrays know their component type at runtime |
T[] in generic code | Not directly | Yes at compile time | No | T is erased, so direct creation is forbidden |
Object[] backing store | Yes (Object[]) | Limited internally | Yes | Common internal implementation strategy |
Cheat Sheet
Quick rules
new T[10]is illegal in Java.- Arrays are reified: they know their element type at runtime.
- Generics are erased:
Tusually is not known at runtime. - To create a real generic array, pass
Class<T>and useArray.newInstance(...). - If you only need internal storage,
Object[]is often enough. - If you do not need an array specifically, prefer
List<T>.
Core pattern
import java.lang.reflect.Array;
public class Holder<T> {
private final T[] items;
@SuppressWarnings("unchecked")
public Holder(Class<T> clazz, int size) {
items = (T[]) Array.newInstance(clazz, size);
}
}
Alternative internal pattern
public class Holder<T> {
private final Object[] items;
public {
items = [size];
}
T {
(T) items[index];
}
}
FAQ
Why can't I create new T[] in Java?
Because generic type parameters are erased at runtime, and arrays require a real runtime component type.
Is Array.newInstance(...) type-safe?
It can be, if you pass the correct Class<T> and keep the cast and array usage controlled inside the class.
Why does Array.newInstance(...) return Object?
Reflection APIs are general-purpose. They return Object, so you must cast the result to the array type you expect.
Should I use arrays or ArrayList<T>?
Use ArrayList<T> unless you specifically need an array or fixed-size internal storage.
Why is there an unchecked cast warning?
The compiler cannot fully verify the cast from Object to T[] because of type erasure.
Can I use Object[] instead of T[]?
Yes. This is a very common implementation strategy for generic containers.
What is the difference between arrays and generics in Java?
Mini Project
Description
Build a fixed-size generic stack in Java. This project demonstrates how to store values of any type in an array-backed data structure without trying to write new T[] directly. It is useful because stacks are a classic real-world data structure used in parsers, undo systems, and expression evaluation.
Goal
Create a reusable generic stack that can push, pop, peek, and report whether it is empty, using safe reflective array creation.
Requirements
- Create a generic
ArrayStack<T>class. - Accept
Class<T>and capacity in the constructor. - Store stack items in an internal array created with
Array.newInstance(...). - Implement
push,pop,peek,isEmpty, andsizemethods. - Throw an exception when pushing to a full stack or popping from an empty stack.
Keep learning
Related questions
Avoiding Java Code in JSP with JSP 2: EL and JSTL Explained
Learn how to avoid Java scriptlets in JSP 2 using Expression Language and JSTL, with examples, best practices, and common mistakes.
Choosing a @NotNull Annotation in Java: Validation vs Static Analysis
Learn how Java @NotNull annotations differ, when to use each one, and how to choose between validation, IDE hints, and static analysis tools.
Convert a Java Stack Trace to a String
Learn how to convert a Java exception stack trace to a string using StringWriter and PrintWriter, with examples and common mistakes.