简体   繁体   中英

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?

Your List is declared with an unknown type. Use the class type:

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

// won't compile because Puma not within bound
class PumaPack implements Pack<Puma> {
    List<Puma> getMembers() {return null;}
}

// compiles OK
class BuffaloPack implements Pack<Buffalo> {
    List<Buffalo> getMembers() {return null;}
}

But you can't stop someone coding a raw (missing type) implementation like your PumpPack example, however you will get a compiler warning :

// compile warning
class PumaPack implements Pack {
    List getMembers() {return null;}
}

If you set your compile to fail if there are warnings:

javac -Werror ...

then you will achieve your goal even for raw types.

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;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM