Is List<?> just a fancy way of writing the raw type List? Explain the practical difference.
answer
- Raw List = type checking OFF (legacy)
- List<?> = type checking ON
- Raw: add anything + unchecked warning
- Wildcard: add only null, read as Object
- Never use raw types in new code
basics
~20 sNo. The raw List turns off generic checking and lets you do unsafe things with warnings. List<?> keeps the type checks on: you read as Object and can only add null, so the compiler still protects you.
solid answer
~40 sThey are very different despite both meaning 'a list of unspecified type'. The raw type List is the pre-generics form kept for backward compatibility; using it disables generic type checking for that reference, so you can call add with any object and only get an unchecked warning - safety is off. List<?> is a real parameterized type that keeps type checking fully on: the compiler treats the element type as a single unknown type, so it lets you read elements as Object but refuses every add except null. In short, raw List trades safety for permissiveness, while List<?> keeps safety by being read-only. You should never use raw types in new code; if you want 'a list of anything', use List<?>.
go deeper
Knows List<?> is type-safe and the raw type is not, and that raw types should be avoided.
Explains that the raw type disables checking (unchecked warnings, runtime ClassCastException) while the wildcard keeps it.
Frames the difference historically and in terms of soundness, and can articulate exactly which operations differ.
Establishes a 'no raw types' policy and explains how the wildcard preserves the type-safety guarantees the raw type sacrifices.
## Both say 'list of unspecified type' - but for opposite reasons When people first see `List<?>` they often assume it is just a verbose way to write the old `List`. It is not. The two come from different eras of Java and behave oppositely. ## The raw type `List` Before Java 5 (2004) there were no generics, so you just wrote `List`. When generics arrived, the old syntax was kept for **backward compatibility** - this is the **raw type**. Using a raw type does something drastic: it **turns off generic type checking** for that reference. You can put anything in: ``` List raw = new ArrayList(); raw.add("hello"); raw.add(42); // compiles - no error, only an 'unchecked' warning String s = (String) raw.get(1); // ClassCastException at runtime! ``` The compiler warns ('unchecked call') but does not stop you. You have **lost type safety**, and bugs surface at runtime as `ClassCastException`. ## The wildcard type `List<?>` `List<?>` is a genuine parameterized type. The element type is **unknown but checked**. The compiler keeps all safety guarantees: ``` List<?> any = new ArrayList<String>(); any.add("hello"); // COMPILE ERROR - cannot prove the unknown type is String any.add(null); // OK Object o = any.get(0); // OK, read as Object ``` No unsafe operation slips through. The price is that you can't add (except `null`) and can only read as `Object` - but that's exactly the safety the raw type threw away. ## Summary of the difference | | raw `List` | `List<?>` | |---|---|---| | Era | pre-generics, compatibility only | modern generics | | Type checking | **off** (unchecked warnings) | **on** | | `add(x)` | allowed (unsafe) | rejected except `null` | | `get()` | returns `Object`, unchecked | returns unknown type, read as `Object` | | Recommended? | **never** in new code | yes, for 'a list of anything' | ## The takeaway Use `List<?>` when you mean 'a list whose element type I don't care about but want to handle safely'. Reserve the raw type for nothing - avoid it entirely. The compiler-enforced restriction on `List<?>` is a *feature*: it stops you from doing the unsafe writes the raw type would silently allow.
- Why does the raw type still exist if it is unsafe?For backward compatibility with pre-generics (Java 4 and earlier) code, so old libraries and codebases keep compiling. It is retained, not recommended.
- Which one triggers 'unchecked' compiler warnings?The raw type. Operations through a raw reference (like add) are unchecked. List<?> is fully checked and produces no such warnings.
saying these in an interview costs you the question
- Saying they are equivalent - they have opposite safety behavior
- Believing List<?> emits unchecked warnings like the raw type does
- Using raw types in new code 'because it's shorter'
- Thinking the add restriction on List<?> is a bug rather than a safety feature