Explain Codes LogoExplain Codes Logo

What is a raw type and why shouldn't we use it?

java
type-safety
generics
best-practices
Anton ShumikhinbyAnton Shumikhin·Jan 11, 2025
TLDR

Generics provide type safety in Java, while raw types circumvent it. Avoid raw types to prevent potential ClassCastException.

Use generics correctly as follows:

List<String> safeList = new ArrayList<>(); // No funny business here. Only Strings allowed! safeList.add("safe");

Incorrect raw type usage:

List unsafeList = new ArrayList(); // "Hold my beer" moment awaits. Could be anything in there. Better not.

Generics confirm that only Strings will be added, hence eliminating the need for casting.

Unmasking raw types: an unnecessary relic

Raw types represent a relic from Java's prehistoric era before the introduction of Java 5, when generics were not part of the language. They denote a class or interface without type parameter(s), thereby bypassing the type safety.

Type Safety: Catch errors before they catch you

Parameterized types (List<Integer> for example) allow the compiler to ensure that your list only holds Integers. This compile-time checking protects you from those hideous runtime errors.

Compatibility: You can't teach an old dog new tricks, but you can refactor it

Raw types stick around for interaction with legacy code. When updating or writing new code, avoid them like avocado on pizza. For legacy code, use -Xlint:unchecked arsenal to detect and fix unsafe operations.

Code Maintainability: Clean code today saves tomorrow

Generics not only enhance the reliability but maintainability (read geometric coffee breaks). They make interfaces more readable and code clearer because types are checked at compile-time.

Beware of unchecked warnings

You might face unchecked warning at runtime and hidden flaws, such as unexpected exceptions, when you resort to raw types. Use @SuppressWarnings("unchecked") sparingly, it's not a magic wand.

Generics: Your chivalrous knight for type safety

Interface Implementation: Multiply your potential

Generics allow you to implement multiple interfaces with different type parameters, something raw types can't play with, providing more versatile reusable code.

Bytecode: All that glitters is not gold

Even though generics add complexity to your source code, they boil to the same bytecode as raw types due to type erasure.

Best Practice: Do it Alice's way

Always prefer parameterized types over raw types. The only exception is class literals and instanceof checks, where their use is safe.

Evolution: Change is the only constant

Stumble upon raw types in the legacy system, review and transition to parameterized types where possible. New types that support generics should be explicitly parameterized for type safety.