m1(ArrayList<String>)

It is applicable for ArrayList of only String type.

m1(ArrayList<? extends x> l)

Here if ‘x’ is a class then this method is applicable for ArrayList of either x or it’s child classes.
If ‘x’ is an interface then this method is applicable for ArrayList of any implementation class of x

m1(ArrayList <? super x> l)

If ‘x’ is a class then this method is applicable for ArrayList of either x or it’s super classes.
If ‘x’ is an interface then this method is applicable for ArrayList of any super classes of implemented class of x.

m1(ArrayList <?> l)

This method is applicable for ArrayList of any type.

In the method declaration,if we use ‘?’, in that method we are not allowed to insert any element except null. Because we don’t know exactly what type of object is coming.

Example:

import java.util.ArrayList;

class Test {
	public static void main(String arg[]) {
		ArrayList<String> l1 = new ArrayList<String>();
		l1.add("A");
		l1.add("B");
		l1.add("C");
		l1.add("D");
		m1(l1);
		ArrayList<Integer> l2 = new ArrayList<Integer>();
		l2.add(10);
		l2.add(20);
		l2.add(30);
		l2.add(40);
		m1(l2);
	}

	public static void m1(ArrayList<?> l) {
		//l.add("D");//C.E: Because we can’t expect what type of value will come
		l.remove(1);
		l.add(null);
		System.out.println(l);
	}
}
/*
[A, C, D, null]
[10, 30, 40, null]
*/

Note:We can use Unicode character ‘?’ in the declaration part but not in the construction part.

Communication with legacy non-generic code

To provide compatibility with old non-generic versions,sun people compromised the generics concept in some places,the following is one such place.

import java.util.ArrayList;

class Test {
	public static void main(String arg[]) {
		ArrayList<String> l = new ArrayList<String>();
		l.add("A");
		l.add("B");
		l.add("C");
		//l.add(10);
		m1(l);
		System.out.println(l);
	}

	public static void m1(ArrayList l) {
		l.add(new Integer(10));
		l.add(new StringBuffer("Java"));
	}
}
/*
[A, B, C, 10, Java]
*/

Note:
Generics is the concept applicable only at compile time to provide type safety, at run time there is no generic concept at all.