Chapter: Java The Complete Reference - The Java Language - Generics

Study Material, Lecturing Notes, Assignment, Reference, Wiki description explanation, brief detail

Ambiguity Errors - Java

The inclusion of generics gives rise to a new type of error that you must guard against: ambiguity.

Ambiguity Errors

 

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:

 

 

     // Ambiguity caused by erasure on overloaded methods.

 

class MyGenClass<T, V> { T ob1;

 

V ob2;

 

 

 

     //These two overloaded methods are ambiguous and will not compile.

 

void set(T o) { ob1 = o;

 

}

 

void set(V o) { ob2 = o;

 

}

 

}

 

Notice that MyGenClass declares two generic types: T and V. Inside MyGenClass, an attempt is made to overload set( ) based on parameters of type T and V. This looks

reasonable because T and V appear to be different types. However, there are two ambiguity problems here.

First, as MyGenClass is written, there is no requirement that T and V actually be different types. For example, it is perfectly correct (in principle) to construct a MyGenClass object as shown here:

 

 

MyGenClass<String, String> obj = new MyGenClass<String, String>()

 

In this case, both T and V will be replaced by String. This makes both versions of set( ) identical, which is, of course, an error.

The second and more fundamental problem is that the type erasure of set( ) reduces both versions to the following:

 

void set(Object o) { // ...

 

Thus, the overloading of set( ) as attempted in MyGenClass is inherently ambiguous. Ambiguity errors can be tricky to fix. For example, if you know that V will always be

some type of Number, you might try to fix MyGenClass by rewriting its declaration as shown here:

 

 

class MyGenClass<T, V extends Number> { // almost OK!

 

This change causes MyGenClass to compile, and you can even instantiate objects like the one shown here:

 

MyGenClass<String, Number> x = new MyGenClass<String, Number>();

 

This works because Java can accurately determine which method to call. However, ambiguity returns when you try this line:

 

MyGenClass<Number, Number> x = new MyGenClass<Number, Number>();

 

In this case, since both T and V are Number, which version of set( ) is to be called? The call to set( ) is now ambiguous.

Frankly, in the preceding example, it would be much better to use two separate method names, rather than trying to overload set( ). Often, the solution to ambiguity involves the restructuring of the code, because ambiguity frequently means that you have a conceptual error in your design.

 

Study Material, Lecturing Notes, Assignment, Reference, Wiki description explanation, brief detail


Copyright © 2018-2020 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.