Understanding Java Generics: Type Erasure, Wildcards, and Common Pitfalls
This article explains Java generics as a type‑parameter mechanism that provides compile‑time safety, describes type erasure, generic classes, methods, interfaces, the three kinds of wildcards, reflection tricks that bypass erasure, and the practical limitations of generics.
Java Generics: A Gatekeeper
Generics in Java are a compact yet often confusing feature that allows types to be parameterized, providing compile‑time type safety and reducing the need for explicit casts.
What Is a Generic?
The term “generic” means “general” and refers to a type that can be supplied as a parameter to a class or method. By declaring a type parameter (e.g., T ) the same code can work with different concrete types.
Type Erasure
At compile time the generic information is removed – a process called type erasure. After erasure List<String> and List<Integer> share the same runtime class List.class , and unbounded type parameters become Object unless a bound is specified.
Generic Classes
A generic class can store a value of type T . When instantiated, the compiler substitutes the actual type, eliminating the need for casts.
public class Cache<T> {
T value;
public T getValue() { return value; }
public void setValue(T value) { this.value = value; }
}Using Cache<String> or Cache<Integer> guarantees that only the declared type can be stored.
Generic Methods
Type parameters can also be declared on methods, appearing before the return type.
public <T> void testMethod(T t) { /* … */ }The method can return a value of the same type parameter, providing flexibility while preserving type safety.
Wildcards
Wildcards ( ? ) express an unknown type or a bounded range.
<?> – unbounded, read‑only collection.
<? extends Base> – any subclass of Base , still read‑only.
<? super Sub> – any supertype of Sub , allows adding Sub instances.
Reflection and Type Erasure
Because generic signatures are erased to Object , reflection can be used to invoke generic methods with mismatched types, bypassing compile‑time checks.
Method m = list.getClass().getDeclaredMethod("add", Object.class);
m.invoke(list, "text"); // works despite List
declarationLimitations
Generics cannot be used with primitive types, cannot create arrays of concrete generic types, and type erasure can hide certain type information.
Conclusion
Generics are not magical; they are a compile‑time tool that improves readability and safety. Understanding type erasure helps developers use generics correctly and avoid pitfalls.
Original article: blog.csdn.net/briblue/article/details/76736356
Java Captain
Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.