Narkha Narkha - 4 months ago 7
Java Question

Generic interface with a method that return a list

I have a Generic interface (

Pack<A extends PackAnimal>
) with one method that returns
List<A>
. Today I've found that if in a class that implements the interface I forget to speficy the class (
class XXX implements PackAnimal
) the return type is not checked in compilation time and fail during execution

interface PackAnimal {
}
class Buffalo implements PackAnimal {
}

interface LonelyAnimal {
}
class Puma implements LonelyAnimal {
}

interface Pack<A extends PackAnimal> {
List<A> getMembers();
}

class PumaPack implements Pack {

@Override
public List<Puma> getMembers() {
return null;
}
}


Why is that? How could I force that if there any type of mistake in the declaration the compilation will fail?

Answer

You are experiencing the scary and wierd results of using Raw Types.

Essentially if you miss out the <...> anywhere it should be the compiler treats your code as legacy and does not do much of the normal type checking it should. MOst compilers try their best but it leaves gaping holes in the checking process.

interface PackAnimal {
}

class Buffalo implements PackAnimal {
}

interface LonelyAnimal {
}

class Puma implements LonelyAnimal {
}

interface Pack<A extends PackAnimal> {
    // Obviously fine.
    List<A> getMembers();
}

// Raw type so no checking.
class PumaPack implements Pack {

    @Override
    public List<Puma> getMembers() {
        // Raw typed class so Puma isn't checked for PackAnimal super.
        return Arrays.asList(new Puma());
    }
}

class Six {

}

// Properly typed so Raw Types not happening.
class SixPack implements Pack<Six> {

    @Override
    // NOT ALLOWED: Attempt to use incompatible return type!!!
    public List<Six> getMembers() {
        return null;
    }
}