Raw Types in Java
When generics arrived in Java 5, millions of lines of existing code used plain List and Map. To keep all that code compiling, Java allowed generic types to be used without type arguments. A raw type is exactly that: List instead of List<String>. Raw types switch off generic type checking for that variable, so they bring back the runtime bugs generics were designed to remove.
What a Raw Type Allows
import java.util.ArrayList;
import java.util.List;
public class Raw {
public static void main(String[] args) {
List names = new ArrayList();
names.add("Navika");
names.add(42);
for (Object o : names) {
String s = (String) o;
System.out.println(s.toUpperCase());
}
}
}Compiling it gives only a gentle note:
Note: Raw.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.With -Xlint:unchecked, the compiler explains each risky line:
Raw.java:7: warning: [unchecked] unchecked call to add(E) as a member of the raw type List
names.add("Navika");
^
where E is a type-variable:
E extends Object declared in interface ListAnd running it crashes, far from the real mistake on line 8:
NAVIKA
Exception in thread "main" java.lang.ClassCastException: class java.lang.Integer cannot be cast to class java.lang.String (java.lang.Integer and java.lang.String are in module java.base of loader 'bootstrap')
at Raw.main(Raw.java:10)Raw vs <Object> vs <?>
These three look similar but mean different things:
| Type | Accepts which lists? | Can add? | Type checking |
|---|---|---|---|
List (raw) | Any list | Anything, with a warning | Off |
List<Object> | Only List<Object> | Any object | On |
List<?> | Any list | Nothing (except null) | On |
If you want "a list of anything" as a parameter, use List<?>; it's as flexible as the raw type but keeps the compiler on your side.
Where Raw Names Are Fine
Some places can't take type arguments at all, so the raw name is correct there:
| Place | Example |
|---|---|
| Class literals | List.class (not List<String>.class) |
instanceof without a pattern variable | obj instanceof List (or List<?>) |
| Imports | import java.util.List; |
Common Mistakes
Forgetting <> when creating objects: new ArrayList(). Use new ArrayList<>().
Implementing raw interfaces: implements Comparable. Write implements Comparable<Student>.
Ignoring "uses unchecked or unsafe operations". Recompile with -Xlint:unchecked and fix each warning.
Practice
- Easy: Fix
Raw.javaby adding type arguments. What happens to thenames.add(42)line? - Harder: Write a method that takes a raw
Listand returns its size, then change it to takeList<?>. Show that both accept aList<String>and aList<Integer>.
Was this tutorial helpful?