1

I have a question according to casting when generics in Java are used. I tried to provide a small example that explains my problem.

IVariable.java

public interface IVariable {
}

IProblem.java

public interface IProblem<V extends IVariable> {
}

Algorithm.java

public class Algorithm<V extends IVariable, P extends IProblem<V>> {

    public void doSomething(P problem) {

        // ERROR: Type mismatch: cannot convert from P to IProblem<IVariable>
        IProblem<IVariable> genericProblem = problem;

    }

}

Why do I need to cast the variable genericProblem explicitly to

@SuppressWarnings("unchecked")
IProblem<IVariable> genericProblem = (IProblem<IVariable>) problem;

and get a warning?

The method has P as an argument which is of type IProblem because V has to implement IVariable as well. Where is my mistake? What is the workaround?

I do not want to write

IProblem<V> genericProblem = problem;

because the input variable of the problem might be different. Anyway in my opinion is IProblem<V> more specific than IProblem<IVariable>.

Thanks in advance!

Julian
  • 416
  • 1
  • 4
  • 8

2 Answers2

2

An IProblem<V> is not equivalent to an IProblem<IVariable>, even if V is constrainted to be an IVariable, because Java's generics are invariant. Sure, IProblem<V> is the way to go, but if you don't want that, you can use an upper-bounded wildcard to express the relationship between V and IVariable instead:

IProblem<? extends IVariable> genericProblem = problem;
rgettman
  • 176,041
  • 30
  • 275
  • 357
1

The generic types needs to be an exact match. V extends IVariable and IVariable are not interchangeable types. Let me give you another example.

List<Integer> ints = new ArrayList<>(); // list of ints.
List<Number> nums = ints; // doesn't compile but this is what you are trying to do
nums.add(new BigDecimal(0.0)); // fine as BigDecimal is a Number.
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130