Java Generics - 5. Wildcards

This is part 5 of the 9 part series on Java Generics 



Prev Topic

Topics



Next Topic



Java Generics - Wildcards


“?” wildcard in Java, means “any”. If a method takes in a declaration with <?>, it means it can take any type. Say you’d like to perform a certain operation which applies to all types (usually for a library class) , then this wildcard can be handy. Say you want a method which gives back the size of the list, but you also want to handle ‘null’ scenarios. Then you could write the code as:


       public static int getSize(List<?> list){
              return list == null ? 0 : list.size();
       }


In fact this method is not different with the one declared below.


       public static <E> int getSize(List<E> list){
              return list == null ? 0 : list.size();
       }


Then which one we should use? Answer would be any one you like. My personal preference is the second one, because first, it appears more clear and second, because while referring individual elements of List, I can use E directly without defining it once again. It appears more elegant. Consider the two methods below. They count how many elements are greater than the given number. They essentially do the same thing. Again it’s a matter of choice and you can use any style over the other one.
Note that the method getSize(List<E> list) or getSize(List<?> list) list is different from getSize(List<Object> list). The latter takes in only the List of Object and not any type of List.


       public static int countGT2(List<? extends Number> nList, int num){
              int c = 0;
              for (Number e : nList){
                     if (e.intValue() > num)
                           c++;
              }
              return c;
       }
      
       public static <E extends Number> int countGT1(List<E> nList, int num){
              int c = 0;
              for (E e : nList){
                     if (e.intValue() > num)
                           c++;
              }
              return c;
       }


Then what is the use of an additional wildcard “?”, in the java programming language? Maybe it wasn’t needed at all! Well it is most useful in declaring and referring variables, something we will explore in the coming sections.
Java goes one step farther and checks for as many type checks as possible during compilation. For instance it does instanceof checks for classes, but not interfaces.


       public <F extends Mango> void foo(F f){
             
              if (f instanceof Fruit){
                     // do something
              }
             
              if (f instanceof Alphonso){
                     // do something
              }
                          
              if (f instanceof Object){
                     // do something
              }
             
              if (f instanceof Map<?, ?>){
                     // do something
              }
             
              // compiler error
              // Incompatible conditional operand types F and Wheat
              if (f instanceof Wheat){
                     // do something
              }            
       }


In the method above, F extends Mango, so the instanceof checks are valid for Fruit too as Mango is a fruit. It is also valid for Alphonso which is a type of Mango. The java compiler does not check for interfaces so any interface check (in this case check for Map<?,?>) will not throw any error. Wheat for instance does not fall under the Mango hierarchy and so the compiler would throw the error - Incompatible conditional operand types F and Wheat. It will also throw error for Grape and Shiraz as they are not a part of Mango hierarchy.




Prev Topic

Topics



Next Topic

Comments

Popular posts from this blog

Java Generics - 7. Upper and Lower Bounds

Java Functional Programming : 3. The java.util.function Library

Java Generics - 3. Multiple bounding