Raw Types in Java β€” Why to Avoid Them

A raw type is a generic class used without its type arguments β€” List instead of List<String>. Raw types exist only for backward compatibility with pre-Java-5 code. Modern code should never use them; doing so disables compile-time type checks and reintroduces the runtime casting errors generics were invented to prevent.

What raw means

List list = new ArrayList();         // raw β€” no type argument
list.add("hello");
list.add(42);                         // compiles β€” anything goes
String s = (String) list.get(1);      // ClassCastException at runtime

Unchecked warnings

The compiler warns about every raw-type operation:

warning: [unchecked] unchecked call to add(E) as a member of the raw type List
warning: [rawtypes]  found raw type: List

Silencing them with @SuppressWarnings without fixing the underlying issue papers over bugs.

Raw vs wildcard

public void rawApi(List list)    { list.add("anything"); }   // raw β€” unsafe
public void wildApi(List<?> list) { list.size(); }            // wildcard β€” safe, read-only

List<?> means "a list of some unknown type" β€” you can't add to it (except null), but you can read from it as Object. It's the safe equivalent of a raw type when you truly don't know the element type.

Heap pollution

List raw = new ArrayList();
List<String> strings = raw;          // unchecked
raw.add(42);                          // int in a "List<String>" β€” polluted
String s = strings.get(0);            // ClassCastException later

Interop with legacy APIs

If you must consume a raw-type API (old library, unparameterised DTO), constrain the conversion at the boundary:

@SuppressWarnings("unchecked")
List<String> typed = (List<String>) legacyApi.fetch();
// Better: verify element-by-element if you have any doubt
for (Object o : legacyApi.fetch()) {
    if (!(o instanceof String)) throw new ClassCastException();
}

Common mistakes

  • Omitting type arguments from intermediate locals β€” var list = new ArrayList<>(); without context infers ArrayList<Object>, not raw, but still not what you want.
  • Silencing unchecked warnings wholesale β€” hides real bugs. Narrow to the line.
  • Public APIs returning raw types β€” punishes every caller. Parameterise.

Related

Pillar: Java generics. See also wildcards, type erasure.