Showing posts with label wildcard. Show all posts
Showing posts with label wildcard. Show all posts

Sunday, 3 July 2011

Wildcard in Java classpath

One of the less known new features of JDK 6 is the ability to use wildcards in classpaths.
That means that instead of doing…
java -cp lib\x.jar;lib\y.jar;lib\z.jar; com.company.MyProggy
…you could just do…
java -cp lib\*.jar; com.company.MyProggy
That generally turns out to be quite a time saver. Especially so if you are trying out something at a remote box and vi is your only editor.
However, if you use the wild card, there is no way to predict the order in which the jars will be used. In some cases, the order is important – and in those cases, you will need to add in the jars like one normally does by enumerating each one explicitly.
Also, don’t forget the semi colon at the end of the classpath. Sometimes lots of time is lost due to this. It can be really frustrating!

Friday, 1 July 2011

Wildcards in Java Generics

What is covariance, contravariance and invariance?
As we've seen in the previous post, the subtyping relation of generic types is invariant. Sometimes, though, we'd like to use generic types in the same way we can use ordinary types:

  • Narrowing a reference (covariance).
  • Widening a reference (contravariance
Wildcard in Generics

Lower - bounded wildcards in Generics
Upper bounded wildcards in Generics
Using multiple bounds in Generics
The get and put principle of bounded wildcard
Restriction of Wildcards in generics

Tuesday, 19 April 2011

The Get and Put Principle in bounded wildcard (Generics)

Use extends only when you intend to get values out of a structure or Collection, use super only when you intend to put values into a structure or Collection.
This also implies: don’t use any wildcards when you intend to both get and put values into and out of a structure.

// Copy all elements, subclasses of T, from source to dest 
//which contains elements that are superclasses of T.public static <T> void copy(List<? super T> dest, List<? extends T> source) {
for (int i = 0; i < source.size(); i++) {
dest.set(i, source.get(i));
}
}

// Extends wildcard violationList<Integer> integers = new LinkedList<Integer>();
List<? extends Number> numbers = integers;
numbers.get(i); // Works fine!numbers.add(3); // Won't compile!
// Super wildcard violationList<Number> numbers = new LinkedList<Number>();
List<? super Integer> integers = numbers;
numbers.add(3); // Works fine!int i = numbers.get(0); // Won't' compile!Object o = numbers.get(0); // Works fine since object is the upper bound!

Restrictions on wildcards in generics:

The get and put principle is one of the restrictions on wildcards. Additional to the above principle there are also a few restrictions on wildcards: Don’t use wilcards when creating instances, specifying generic method calls and extending superclasses:
List<?> integers = new LinkedList<?>();         // Won't compile!List<?> integers = Lists.<?>factory();          // Won't compile!class AnyList implements List<?> {}             // Won't compile!

Using multiple bounds in generics

The <A extends B> syntax applies even if B is an interface because 1) it doesn't matter operationally if B is a class or an interface and 2) if B is a type parameter, the compiler doesn't know a priori whether it is a class or an interface.  
Since Java allows multiple inheritance in the form of implementing multiple interfaces, it is possible that multiple bounds are necessary to specify a type parameter.    To express this situation, one uses the following syntax:
<T extends A & B & C & ...>
For instance:
  interface A {
...
}

interface B {
...
}

class MultiBounds<T extends A & B> {
...
}

Lower Bounded Wildcards in Generics

Suppose we wish to write a method called copyTo()such that it copies the data the opposite direction, i.e. from the host object to the given object:
public void copyTo(Box<E> b) {
  b.data = this.data(); 
}

The above code works fine so long as you are copying from one Box to another of exactly the same type (invariant type relationship), e.g. both are Box<Integer> or both are Box<String>. 

But operationally, b could be a Box of any type that is a superclass of E and the copying would be type safe.  This is a contravariant type relationship between Box<E> amd the input parameter to the copyTo() method where the type parameter of the object referenced by the variable b  is a superclass of E.
To express this, we write
public void copyTo(Box<? super E> b) {
  b.data = this.data();  // b.data is a superclass of this.data
}

The type parameterization <? super E> is called a "lower bounded wildcard" because it defines a type that could be any type so long as it is bounded by the subclass E.
Once again, we have greatly increased the utility of the copyTo() method because it is now not limited to only inputs of type Box<E> but will now work with any compatible Box object.
Upper and lower bounded wildcards will prove indispensable when implementing the visitor pattern on generic (parameterized) classes.

Expressing dependencies in type parameters : Wildcards vs bounded type parameters

This article explains When should I use generic methods, and when should I use wildcard types?
To understand the answer, let’s examine a few methods from the Collection libraries. It has to methods :
containAll and addAll .

Using wildcard:

interface Collection<E> {
public boolean containsAll(Collection<?> c);
public boolean addAll(Collection<? extends E> c);
}

Using Bounded type parameters
We could have used generic methods here instead:
interface Collection<E> {
public <T> boolean containsAll(Collection<T> c);
public <T extends E> boolean addAll(Collection<T> c);
// hey, type variables can have bounds too!
}

However, in both containsAll and addAll, the type parameter T is used only once.
The return type doesn’t depend on the type parameter, nor does any other argument to the method (in this case, there simply is only one argument).

This tells us that the type argument is being used for polymorphism; its only effect is to allow a variety of actual argument types to be used at different invocation sites. If that is the case, one should use wildcards. Wildcards are designed to support flexible subtyping, which is what we’re trying to express here.

Generic methods allow type parameters to be used to express dependencies among the types of one or more arguments to a method and/or its return type. If there isn’t such a dependency, a generic method should not be used.


It is possible to use both generic methods and wildcards in tandem. Here is the method Collections.copy():

class Collections {
    public static <T> void copy(List<T> dest, List<? extends T> src){...}
}

Note the dependency between the types of the two parameters. Any object copied from the source list, src, must be assignable to the element type T of the destination list, dst. So the element type of src can be any subtype of T - we don’t care which. The signature of copy expresses the dependency using a type parameter, but uses a wildcard for the element type of the second parameter.

We could have written the signature for this method another way, without using wildcards at all:
class Collections {
     public static <T, S extends T>
     void copy(List<T> dest, List<S> src){...}
}

This is fine, but while the first type parameter is used both in the type of dst and in the bound of the second type parameter, S, S itself is only used once, in the type of src - nothing else depends on it. This is a sign that we can replace S with a wildcard.

Using wildcards is clearer and more concise than declaring explicit type parameters, and should therefore be preferred whenever possible. Wildcards also have the advantage that they can be used outside of method signatures, as the types of fields, local variables and arrays.
Here is an example on this. Returning to our shape drawing problem, suppose we want to keep a history of
drawing requests. We can maintain the history in a static variable inside class Shape, and have drawAll() store its incoming argument into the history field.

static List<List<? extends Shape>> history = 
new ArrayList<List<? extends Shape>>();
public void drawAll(List<? extends Shape> shapes) {

history.addLast(shapes);
for (Shape s: shapes) {
s.draw(this);
}

}

Beginner's mistake of using Object as parameter in Generics

Imagine you have a method that processes the elements of a List, e.g. print out all elements in the List. Here is how such a method could look:

public void printElements(List<Object> elements){
for(Object o : elements){
System.out.println(o);
}
}
 
Could you call this method with a List<String> instance?
The answer is no. A List<String> is not a subtype of List<Object>. The reason is this:
Imagine you could upcast a List<String> to a List<Object>. It would not cause any problems to iterate each String instance in the List as an Object. After all, a String is a subtype of Object.

The problem arises when you insert elements into the List. In a List<Object> instance you can insert any Object instance, also non-String elements. Thus, if you could upcast a List<String> to a List<Object>, you could now insert non-String objects into the List, meaning the type safety would be broken.
This is true for any kind of collection, not just List's.

So what's the solution for it. Its solution is wildcards (click on link to read on wildcards).

Generic method : How generic are they ?

Beginner's mistake of using Object as parameter
Consider writing a method that takes an array of objects and a collection and puts all objects in the array into the collection. So we try to implement it .

Here is a first attempt:

static void fromArrayToCollection(Object[] a, Collection<?> c) {
for (Object o : a) {
c.add(o); // compile time error

}
}

By now, you will have learned to avoid the beginner’s mistake of trying to use Collection<Object>.
static void fromArrayToCollection(T[] a, Collection<T> c) {
for (Object o : a) {
c.add(o); // works fine this time

}
}


Now we can have method as :

Object[] objectArray = new Object[100];
Collection<Object> collObject = new ArrayList<Object>();
fromArrayToCollection(objectArray , collObject );// T inferred to be Object 
 
String[] stringArr = new String[100];

Collection<String> collString = new ArrayList<String>();
fromArrayToCollection(stringArr , collString );// T inferred to be String
fromArrayToCollection(stringArr , co);// T inferred to be Object

Integer[] ia = new Integer[100];
Float[] fa = new Float[100];
Number[] na = new Number[100];
Collection<Number> cn = new ArrayList<Number>();

fromArrayToCollection(ia, cn);// T inferred to be Number
fromArrayToCollection(fa, cn);// T inferred to be Number
fromArrayToCollection(na, cn);// T inferred to be Number
fromArrayToCollection(na, co);// T inferred to be Object
fromArrayToCollection(na, cs);// compile-time error


Also see here for clearer picture on Using type parameter as Object.
Notice that we don’t have to pass an actual type argument to a generic method. The compiler infers the type argument for us, based on the types of the actual arguments. It will generally infer the most specific type argument that will make the call type-correct.

See this for more:
Expressing dependencies in type parameters : Wildcards vs bounded type parameters



Wednesday, 27 October 2010

Upper Bounded Wildcards in generics

Suppose we want to write a generic method which takes a list and print it only when it contains elements subclassing one particular class. So here we need upper bound.
It is possible to set the upper bound of the wildcard like this:
List<? extends Vehicle> vehicles = new ArrayList<? extends Vehicle>();    

In this example I have specified the upper bound to be the class Vehicle. I can now define the printElements() method like this:

public void printElements(List<? extends Vehicle> elements){
for(Vehicle o : elements){
System.out.println(o);
}
}

As you can see it is now safe to cast each element in the list to a Vehicle, as it is done by the new for loop inside the method.
Furthermore, it is now safe to call the method using a List<Car> instance, provided that Car extends Vehicle. Here is an example:
List<Car> elements = new ArrayList<Car>
// ... add Car elements to the list.

printElements(elements);

But, even when using a wildcard with an upper bound it is not safe to write to the List. After all, a Car is always a Vehicle, but a Vehicle is not always a Car.

The type parameterization <? extends E> is called an "upper bounded wildcard" because it defines a type that could be any type so long as it is bounded by the superclass E. It provides covariant relationship such that the referenced object's (eg. Car ) type parameter is a subclass ofVehicle's type parameter

Wildcards in Generics

We just saw here about generic methods. But how generic are they?
Suppose we have to write a generic method which takes list of elements and prints elements onto screen. Element can be String, Integer,Object...So one can think of using object as type parameter. But this will be a mistake. See here for this.
So solution is wildcards.

Wildcards

The wildcard operator is a solution to the problem explained above.
The character '?' is a wild-card character and it stands for any Java type. It can be java.lang.Object type or some other type. It is just a place-holder that tells that it can be assigned with any type. Considering this case, the following are now valid syntaxes. 

List<?> anyObjects = null; 

List<Integer> integers = new ArrayList<Integer>();
anyObjects = integers;

List<Double> doubles = new ArrayList<Double>();
anyObjects = doubles;


Here is how you write a generic List using the wildcard operator:

List<?> listOfUnknown = new ArrayList<?>();    

Generic method using wildcards
We can now define the printElements() method like this:

public void printElements(List<?> elements){
for(Object o : elements){
System.out.println(o);
}
}
 
You can call the printElements() with any generified List instance. For instance:
List<String> elements = new ArrayList<String>
// ... add String elements to the list.

printElements(elements); 
 
When you upcast a List<String> to a List<?> you can now read all elements of the List<?> safely as Object instances. But you still cannot insert elements into the List<?>. The ? could represent any type, and thus it would be possible to insert types that did not match the original definition of the List.