secuf
secuf

Reputation: 35

Java generics: Generic parameter defined at method level vs interface level

I'm having the following issue to do with generics. I have the following:

InterfaceA as:

public interface InterfaceA {
    public <T extends DTOInterface> Object methodName (T dto) {}
}

DTOInterface is just an empty interface.

Then my implementation would be:

public class ImplementationA implements InterfaceA {
    public Object methodName(DTOImplementation dto) {
        return null;
    }
}

DTOImplementation is just a class implementing DTOInterface.

This is failing because the method in ImplementationA is not recognized as a valid implementation of the method in InterfaceA.

However, if I define the parameter at interface level i.e.

public interface InterfaceA **<T extends DTOInterface>** {
    public Object methodName (T dto) {}
}

And then define the implementation as:

public class ImplementationA implements **InterfaceA<DTOImplementation>** {
    public Object methodName(DTOImplementation dto) {
        return null;
    }
}

It does work. The method is recognized as a valid implementation.

Does anyone know why this is happening?

Upvotes: 2

Views: 2135

Answers (2)

Boris the Spider
Boris the Spider

Reputation: 61168

Your interface definition has a generic method

public <T extends DTOInterface> Object methodName (T dto) {}

This method states that it takes any type T that extends DTOInterface. If you want to implement the interface you need to provide the exact same method in the implementation.

You cannot restrict the method in an implementation because what would happen if you did this:

AnotherDTOImplementation adi = new AnotherDTOImplementation();
InterfaceA obj = new ImplementationA();
ojb.methodName(adi);

This obviously breaks type safety.

In your second example you have a generic interface. This means that when you implement the interface you either have to declare the generic type of specify the implementation as a generic class.

This means that ImplementationA is of type InterfaceA<DTOImplementation> which in turn means that you have type safety.

Upvotes: 2

jacobm
jacobm

Reputation: 14035

The first declaration says that in order to implement InterfaceA, the subclass needs to provide a method methodName that works for any type T that extends DTOInterface of the method caller's choice. In other words, T is a parameter that the caller of methodName gets to choose; the class that implements InterfaceA doesn't get to choose it. So when you provide an implementation that attempts to choose a particular value of T for methodName and only implement that, the compiler rejects your program.

The second declaration, on the other hand, is an interface that allows the implementor to provide a particular value for T and only implement its methods for that particular choice. ImplementationA choose to implement InterfaceA only for one particular subtype of DTOInterface (namely, DTOImplementation) and provides a method only for that choice of T. That's perfectly fine.

Upvotes: 4

Related Questions