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 possibilities of how this can be used (and misused). I crafted this example to help illustrate.
On the sample below, the compiler is giving me an error
dispatch(new AlphabetSoup());
The method dispatch(Demo.Soup) is ambiguous for the type Demo
I can understand this because either method signature matches. My question is how could this be resolved without changing the methods? If I wanted force a call to the Soup version I could downcast to Soup:
dispatch((Soup) new AlphabetSoup())
But I'm unsure how you'd force a call to the other version. Is it possible?
public class Demo {
interface HasA { public char getA(); }
interface HasB { public char getB(); }
interface HasC { public char getC(); }
interface Soup {
public void eat();
}
class Alphabet implements HasA, HasB, HasC {
public char getA() { return 'a'; }
public char getB() { return 'b'; }
public char getC() { return 'c'; }
}
class AlphabetSoup implements Soup, HasA, HasB, HasC {
public void eat() { System.out.println("Mmm Mmm Good!"); }
public char getA() { return 'a'; }
public char getB() { return 'b'; }
public char getC() { return 'c'; }
}
public void dispatch(Soup soup) {
System.out.println("Eating some soup...");
soup.eat();
}
public <T extends HasA & HasB & HasC> void dispatch(T letters) {
System.out.println("Reciting ABCs...");
System.out.println(letters.getA());
System.out.println(letters.getB());
System.out.println(letters.getC());
}
public void test() {
dispatch(new Alphabet());
dispatch(new AlphabetSoup());
}
public static void main(String[] args) {
new Demo().test();
}
}
-- Edit: Just learned that "multiple bounded type parameters are formally referred to as "Intersection Types"
The inclusion of generics gives rise to a new type of error that you must guard against ambiguity. Ambiguity errors occur when erasure causes two seemingly distinct generic declarations to resolve to the same erased type, causing a conflict. Here is an example that involves method overloading.
This ambiguous method call error always comes with method overloading where compiler fails to find out which of the overloaded method should be used.
There are ambiguities while using variable arguments in Java. This happens because two methods can definitely be valid enough to be called by data values. Due to this, the compiler doesn't have the knowledge as to which method to call.
Ambiguity is the possibility of having more than one answer. If something is ambiguous, it means it might have more than one answer or more than one solution to the problem.
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 ?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With