Search code examples
javagenericssuppress-warningsunchecked

Syntax of java @SuppressWarnings("unchecked") with inheritance of generic types


I have classes defined as follows with some methods in them

public abstract class Pojo<T extends Pojo<T, U>, U extends Phase<U>> {
    ...
    public T updatePhase(U phase) {
        this.previousPhase = this.phase;
        this.phase = phase;
        return getThis();
    }

    public U getPreviousPhase(U phase) {
        return this.previousPhase;
    }

    @SuppressWarnings("unchecked")
    public T getThis() {
        return (T) this;
    }

    public Map<String, String> getMap() {
        return this.map;
    }
}

public interface Phase<U extends Phase<U>> { ... }

Somewhere later in my code, I'm trying to do the following:

Pojo pojo = someService.get(id); // This can't be a definite type since I get this by deserializing a string
Phase ap = pojo.getPreviousPhase();
pojo.updatePhase(ap); // I get the unchecked warning here (case 1)
Map<String, String> myMap = pojo.getMap(); // I get the unchecked warning here (case 2)
myMap.put("1", "2"); // This obviously works

Case 1: unchecked call to updatePhase(U) as a member of the raw type.
I understand why this gives the warning. How do I use the @SuppressWarnings("unchecked") annotation in this case (syntax-wise)? How would it be used if I combine it to a single statement pojo.updatePhase(pojo.getPreviousPhase)

Case 2: unchecked conversion, required Map<String,String>, found Map
Why does it give the warning? I'm returning a definite type Map<String, String> so it shouldn't care... Similarly how do I apply the @SuppressWarnings annotation here? Similarly how would I do it in the single line statement pojo.getMap().put("1", "2")

Note: I do make sure in my code that all these type conversions are correct and would not cause cast errors at runtime.


Solution

  • Using raw types to disable generic type-checking is a bad idea. For the first problem, instead of trying to force an object of unknown type into a generic method parameter of unknown type, you should tell Pojo to pass itself the field value internally:

    public T updateFromPrevious() {
        return updatePhase(getPreviousPhase());
    }
    

    Once you stop using raw types, the compiler will stop ignoring generic types on those lines and the second warning will go away:

    Pojo<?,?> pojo = someService.get(id);
    pojo.updateFromPrevious();
    Map<String, String> myMap = pojo.getMap();
    myMap.put("1", "2");