7. Data Types

7.1 Type parameters (generics)

Always include the type parameter when dealing with generic classes such as ArrayList, TreeSet, etc. Failing to do so will likely lead to casting that clutter up the code and/or unsafe type operations.

Bad
Stack visited = new Stack();
Good
Stack<String> visited = new Stack<>();

7. 2 Casting

Avoid casting of object types. Casting to object types is essentially disregarding the safety net of the type system that Java provides. It may achieve the desired behavior, but it is usually a sign that we should change the logic of our program elsewhere. Casting to object types should only be done if truly necessary, typically in an equals method and sometimes in order to write a more efficient version of an algorithm.

Casting to primitive types to actually convert values is fine, however, e.g.

int truncated = (int) (Math.random() * 5);
The place you will most likely cast objects is when overriding the equals method. We do not want to overload equals so the parameter shall be of type Object. Use instanceof operator or the getClass() method, to check the parameter is the same type as the this object before casting.
If the class uses generic types, do not attempt to cast to the generic type parameter. Use the wildcard or Object as the data type of the elements of the target of the cast.

Example:

public class GenericList<E> {
    private E[] container;

    public boolean equals(Object obj) { // NOT GenericList<E> obj or GenericList obj. That overloads equals
        if (obj instanceof GenericList<?>) { // obj instanceof GenericList<E> is a syntax error
           
            GenericList<?> otherList = (GenericList<?>) obj;

            // GenericList<E> otherList = (GenericList<E>) obj is NOT SAFE and not allowed in 314.
           

7.3 Prefer simple data types

Sometimes we have options for how we want to represent the data and either option(s) will be able to produce correct behavior. Instead of using a more complicated representation that can do everything we want and more, we should try use the representation that fits the specific problem the best. The intent and logic of your code will be simpler to another reader. Some examples are listed below.

The point of a data structure is to store related values. If a data structure is only used to store one or two values, we prefer to use those value(s) directly.