The compiler doesnβt know the actual element type. If writing Integer were allowed,
but the list is actually a List<String> β there would be a ClassCastException on read.
Raw List vs List<?>
// β Raw type β all checks disabledListraw=newArrayList();raw.add("Hello");raw.add(42);// compiler is silent!// β Wildcard β checks in placeList<?>wildcard=newArrayList<String>();wildcard.add(42);// β compilation error
π΄ Senior Level
Reification and erasure
At the bytecode level, both options are simply List. List<?> is safer because
the compiler blocks unsafe operations, whereas raw type simply disables checks.
List<?> does not give performance advantages
List<?> is not read-only by design. The compiler blocks writes because
it cannot verify type safety, not because it treats the collection as immutable.
No performance optimizations follow from this.
Capture of Wildcard
// Cannot do this:voidswap(List<?>list,inti,intj){// var temp = list.get(i);// list.set(i, list.get(j)); // β capture of ?}// Solution β capture helper:voidswap(List<?>list,inti,intj){swapHelper(list,i,j);}private<T>voidswapHelper(List<T>list,inti,intj){Ttemp=list.get(i);list.set(i,list.get(j));list.set(j,temp);}
Best Practices
// β List<?> for arguments β maximum flexibilityvoidprintAll(List<?>list){}// β List<Object> only for heterogeneous containersList<Object>mixed=newArrayList<>();// β Raw List β disables all checks// β List<Object> when wildcard is needed
π― Interview Cheat Sheet
Must know:
List<Object> β invariant, concrete type, can add any objects
List<?> β covariant, unknown type, read only as Object, cannot write
List<String> is NOT a subtype of List<Object> β generics are invariant
List<?> accepts any parameterized List: List<String>, List<Integer>
List<?> != raw List β wildcard preserves checks, raw disables all
Capture of wildcard β cannot get/set for ? in one method, need helper <T>
Frequent follow-up questions:
Can you add null to List<?>? β Yes, null is valid for any type
**How does List<?> differ from List
What is capture of wildcard? β The compiler cannot match the ? type for writing
**When to use List?** β Heterogeneous containers with different types
Red flags (DO NOT say):
β βList<?> is a read-only listβ β The compiler blocks writes due to unknown type, not immutable
β βList accepts List" β Generics are invariant, List != List
β βList<?> gives performance advantagesβ β No runtime optimizations
β βList<?> and raw List are the sameβ β Wildcard preserves checks, raw disables them
Related topics:
[[11. What are Generics in Java]]
[[16. What is the difference between <? extends T> and <? super T>]]
[[17. What is PECS (Producer Extends Consumer Super)]]
[[19. What are raw types and why should you avoid them]]