Skip to main content

Avoid Using Generic Wildcard Types in Return Types

High
correctnessmaintainability

What is it?

This practice is triggered by the use of generic wildcard types in method return types in Java, which makes the return type unspecific and may not reflect the developer's true intent.

Why apply it?

Using wildcards in return types can obscure the intended specificity of the method's output, making code harder to read, understand, and maintain. Type variance rules are misapplied when wildcards are used this way, potentially leading to runtime exceptions or logical errors.

How to fix it?

Remove the wildcard from the return type to ensure it is specific and use invariant types. Alternatively, replace the return type with a more accurate super or subtype that matches the developer's intent.

Examples

Example 1:

Negative

The negative example uses a wildcard in the return type, which is unnecessarily vague.

import java.util.List;
import java.util.ArrayList;

class Zoo {
public List<? extends Animal> getAnimals() { /* Noncompliant */
List<Animal> animals = new ArrayList<>();
animals.add(new Dog());
animals.add(new Cat());
return animals;
}
}

Example 2:

Positive

The positive example provides a method with a specific return type, avoiding wildcards.

import java.util.List;
import java.util.ArrayList;

class Zoo {
public List<Animal> getAnimals() { /* Compliant */
List<Animal> animals = new ArrayList<>();
animals.add(new Dog());
animals.add(new Cat());
return animals;
}
}

Negative

The negative example uses a wildcard in the return type, making it ambiguous and potentially misleading.

import java.util.List;
import java.util.ArrayList;

class PlantNursery {
public List<? super Plant> getPlants() { /* Noncompliant */
List<Plant> plants = new ArrayList<>();
plants.add(new Tree());
plants.add(new Shrub());
return plants;
}
}

Example 3:

Positive

In this positive example, the method returns a specific subclass type, which is more explicit than a wildcard.

import java.util.List;
import java.util.ArrayList;

class PlantNursery {
public List<Flower> getFlowers() { /* Compliant */
List<Flower> flowers = new ArrayList<>();
flowers.add(new Rose());
flowers.add(new Tulip());
return flowers;
}
}