0

Consider the following scenario:

public abstract class A {}

public class B extends A {}

public interface Provider<T extends A> {
    List<String> list(T param);
}

public class ProviderB implements Provider<B> {
    @Override
    public List<String> list(B param) {
        return Collections.singletonList("ProviderB");
    }
}


public class Factory {
    public static Provider get(int x) {
        if (x == 1)
            return new ProviderB();
        throw new RuntimeException("Not supported");
    }
}


public class Main {
    public static void main(String[] args) {
        Provider provider = Factory.get(1);
        A a = new B();
        List<String> result = provider.list(a);
    }
}

In Main at List<String> result = provider.list(a); , I'm getting:

Unchecked call to list(T) ..
Unchecked assignment java.util.List .. Reason 'provider' has raw type.

I do know some basic stuff about type erasure in generics. How would you solve the warnings ?

EDIT: Actually main will look like this:

public static void main(Map<Integer, ? extends A> types) {
        for (Map.Entry<Integer, ? extends A> entryType : types.entrySet()) {
            Provider provider = Factory.get(entryType.getKey());
            List<String> result = provider.list(entryType.getValue());
        }
    }
cehptr
  • 157
  • 1
  • 7
  • 6
    You've painted yourself into a corner. If you don't know what type of `Provider` the factory returns, you can't know what type of `T` to pass to `list()`. It would help if you explain what you're actually trying to accomplish. – shmosel May 22 '18 at 19:40
  • `public static Provider extends A> get(int x) {` and `Provider extends A> provider = Factory.get(1);` should fix this. - well, except you get an error on `provider.list(a);`, because `a` is an `A`, but only some (unspecified) subclass might be accepted. – Johannes Kuhn May 22 '18 at 19:46
  • @shmosel take a look at the usecase – cehptr May 22 '18 at 19:47
  • 1
    @JohannesKuhn `Provider>` should work just as well. – shmosel May 22 '18 at 19:48
  • @cehptr Who's enforcing the relationship between key and value type? – shmosel May 22 '18 at 19:49
  • 1
    Seems like generics is only overcomplicating your solution. – Bhesh Gurung May 22 '18 at 19:51
  • The scenario is more complex, but they are related. So I should support somehow this behavior. – cehptr May 22 '18 at 19:51
  • @JohannesKuhn using ` extends Something>` is better suited for argument rather than for return type. – Luiggi Mendoza May 22 '18 at 20:01
  • 1
    What you expect to do cannot be achieved using generics like that. Maybe you'd need to pass a specific class to know which kind of provider to get instead of having it all abstract. – Luiggi Mendoza May 22 '18 at 20:03
  • 2
    See https://stackoverflow.com/q/2770321/2891664 for why we shouldn't use raw types (such as `Provider` with no type argument) in new code. You should change all uses of `Provider` to `Provider>`, but this will move the unchecked warning to a compilation error. The new code won't compile because there's a more general problem, which is that you don't know what the actual type of the returned provider is, so passing things to its `list` method is unsafe according to the compiler. I think we need to know more about what you're actually doing to suggest a real solution. – Radiodef May 22 '18 at 20:09

0 Answers0