How do I resolve ambiguous methods caused by intersection types in Java generics?

前端 未结 5 400
猫巷女王i
猫巷女王i 2020-12-31 16:52

I just recently discovered that you can specify multiple types in a single type parameter bound (see example). Like any new tool, I\'ve been trying to explore the possibilit

相关标签:
5条回答
  • 2020-12-31 17:22

    The compiler is right, and saves you from a mess.

    AlphaBetSoup is a subtype of soup and also a subtype of HasA, HasB, and HasC

    Therefore, it fits the bill for both versions of Dispatch

    Since Soup is not a subtype of HasA, HasB, or HasC, it also can't say that one version is more "specific" than the other.

    Therefore you'll get the error correctly.

    Overloaded method should not be ambiguous. If you have a type that mixes both types and you had an overload for each, change your hierarchy or get rid of an overload. It's wrong use of subtyping and overloading.

    0 讨论(0)
  • 2020-12-31 17:28

    Let me explain this with a very simple program:

    Code below illustrated couse of The method is ambiguous for the type compiler error.

    public class AmbiguousMethodOwner {
                void ambiguousMethod(Comparable c){}
                void ambiguousMethod(Serializable c){}
                void test() {
                       ambiguousMethod("bar");
               }
         }
    

    The problem now is obvious: since String implements both Comparable and Serializable, the compiler cannot know which method you intend to call.

    A simple cast will solve the problem:

    ambiguousMethod((Comparable)"bar");

    http://www.javaneverdie.com/java/the-method-is-ambiguous-for-the-type/

    In our case method dispatch is creating problem. See

    class AlphabetSoup implements Soup,  HasA, HasB, HasC 
    

    and

    public void dispatch(Soup soup)
     public <T extends HasA & HasB & HasC> void dispatch(T letters) {
    

    now if you call dispatch(new AlphabetSoup()); compiler would be confused as to which version of dispatch should be called ?

    0 讨论(0)
  • 2020-12-31 17:30

    Note that you do not have a real problem, as the methods you are interested in calling are already called due to dynamic binding.

    Running dispatch((Soup) new AlphabetSoup()); yields:

    Reciting ABCs...
    a
    b
    c
    Eating some soup...
    Mmm Mmm Good!
    

    Hence, the AlphabetSoup method are already called due to basic polymorphic behavior.

    0 讨论(0)
  • 2020-12-31 17:37

    Note that the error is not related to generics, you get the same result if you use interfaces and a type is the intersection:

    public class AA {
    
        interface XX{};
        interface YY{};
    
        public void doSomething(XX x){}
        public void doSomething(YY x){}
    
        class XY implements XX,YY{
    
        }
    
        public void runner(){
            doSomething(new XY());
        }
    }
    

    You get the same error in "doSomething", the compiler cannot resolve the ambiguity. Do you want to interpret as XX or as YY? You have to specify it with a cast. But if you have a hierarchy, like "YY extends XX" and "XY implements YY", the compiler can infer the correct method to call.

    0 讨论(0)
  • 2020-12-31 17:38

    Not that you should keep the overloaded dispatch method (I upvoted Uri for that reason), but you can force the generic version to be called by trying:

    demo.<AlphabetSoup>dispatch(new AlphabetSoup());
    

    or call the soup version with:

    demo.dispatch((Soup) new AlphabetSoup());
    

    The better way around this, though, is to not have the overloaded dispatch method in the first place.

    void dispatchSoup(Soup soup);
    <T extends HasA & HasB & HasC> void dispatchLetters(T letters);
    
    0 讨论(0)
提交回复
热议问题