Monday, 17 March 2014

Wild Card Capture


Wild Card Capture
When Evaluating an expression compiler infers particular type from the code, this is called Wild card capture. While evaluating any expression, if compiler found any chance of wrong types, then compiler throws the error.

Example
import java.util.*;
 
class Test{
 
    static void combine(List<?> a, List<?> b){
        setData(a, b);
    }
    
     static <T> void setData(List<T> a, List<T> b){
    }
 
}
When you tries to compile the above code compiler tries to infer the types and place it in the expressions.

combine(List<?> a, List<?> b) is calling the method setData(List<T> a, List<T> b). Where Parameters in setData has type “T”, which is called by the method combine(List<?> a, List<?> b).

So combine can be called like below
combine(List<Integer> list1, List<Float> list2);
combine(List<Double> list1, List<String> list2);

since “?” can accept any type. But the method setData signature is different, It can able to accept the parameters which is of same type "T". So there is an ambiguity, so while trying to compile the above program, compiler throws the below error.

Test.java:6: error: method setData in class Test cannot be applied to given types;
setData(a, b);
^
required: List<T>,List<T>
found: List<CAP#1>,List<CAP#2>
reason: no instance(s) of type variable(s) T exist so that argument type List<
CAP#2> conforms to formal parameter type List<T>
where T is a type-variable:
T extends Object declared in method <T>setData(List<T>,List<T>)
where CAP#1,CAP#2 are fresh type-variables:
CAP#1 extends Object from capture of ?
CAP#2 extends Object from capture of ?
1 error

Below program compiles fine, since T1 and T2 are two different variables.
import java.util.*;
 
class Test1{
 
    static void combine(List<?> a, List<?> b){
        setData(a, b);
    }
    
     static <T1, T2> void setData(List<T1> a, List<T2> b){
    }
}
 

Will see one more program, to better understand the wild capture.
import java.util.*;
class Test2{
    public static void main(String args[]){
        List<? extends Number> list1 = new ArrayList<Number> ();
        list1.add(10);
    }
}
 

List<? extends Number> list1: the compiler knows that it, is a List of Number or some subclass of Number, but it does not know which. Therefore, you will never be allowed to add anything to such a list. So when trying to compile the above program compiler throws the below error.

Test2.java:5: error: no suitable method found for add(int)
list1.add(10);
^
method List.add(int,CAP#1) is not applicable
(actual and formal argument lists differ in length)
method List.add(CAP#1) is not applicable
(actual argument int cannot be converted to CAP#1 by method invocation conversion)
where CAP#1 is a fresh type-variable:
CAP#1 extends Number from capture of ? extends Number
1 error
 


 



Prevoius                                                 Next                                                 Home

No comments:

Post a Comment