Back to Basics – Subtler Nuances – Generics

public class Person {
	String person;

	public Person() {
	}

	public Person(String person) {
		this.person = person;
	}

	public String getName() {
		return this.person;
	}
}

public class Driver extends Person {
	String driver;

	public Driver(String driver) {
		this.driver = driver;
	}

	public String getDriver() {
		return this.driver;
	}

	public String getName() {
		return this.driver;
	}
}
import java.util.*;

public class Test {
	public void test() {
		List<String> list = new ArrayList<String>();
		list.add("Matty");
		for (String s : list) {
			System.out.println(s);
		}
	}

	public static void main(String[] args) {
		new Test().test();
	}
}
/*

The correct way to use a simple generic type

D:\work\projects\generics>java Test
Matty
*/

import java.util.*;

public class Test3 {
	public void test() {
		List<String> list = new ArrayList<String>();
		List<Object> object = list;
		object.add("jacob");
		list.add("Matty");
		for (String s : list) {
			System.out.println(s);
		}
	}

	public static void main(String[] args) {
		new Test3().test();
	}
}
/*

List<Object> is not a supertype of List<String> or List of any type for that matter!

Test3.java:7: incompatible types
found   : java.util.List<java.lang.String>
required: java.util.List<java.lang.Object>
List<Object> object = list;
*/
import java.util.*;

public class Test4 {
	public void test() {
		List<String> stringList = new ArrayList<String>();
		stringList.add("jacob");
		stringList.add("Matty");
		List<?> list = new ArrayList<String>();
		list = stringList;
		for (Object s : list) {
			System.out.println(s);
		}
	}

	public static void main(String[] args) {
		new Test4().test();
	}
}
/*

List<?> is a supertype of any List<genericType> It is used as a wildcard.
We can read elements from this list and assign them Object since whatever type of collection, it always contain objects
However it is not safe to add any element to this list including Object because
the added element would have to be a subtype of the actual type of this list
and since we dont know the actual type it is illegal to add any element to it! Except null.

D:\work\projects\generics>java Test4
jacob
Matty
*/
import java.util.*;

public class Test5 {
	public void test() {
		List<String> stringList = new ArrayList<String>();
		stringList.add("jacob");
		stringList.add("Matty");
		List<?> list = new ArrayList<String>();
		list.add((Object) ("Matty"));
		list = stringList;
		for (Object s : list) {
			System.out.println(s);
		}
	}

	public static void main(String[] args) {
		new Test5().test();
	}
}
/*

List<?> is a supertype of any List<genericType>
We can read elements from this list and assign them Object since whatever type of collection, it always contain objects
However it is not safe to add any element to this list including Object because
the added element would have to be a subtype of the actual type of this list
and since we dont know the actual type it is illegal to add any element to it! Except null

Test5.java:10: cannot find symbol
symbol  : method add(java.lang.Object)
location: interface java.util.List<capture#145 of ?>
list.add((Object)("Matty"));

*/

import java.util.*;

public class Test6 {
	public void test() {
		List<String> stringList = new ArrayList<String>();
		stringList.add("jacob");
		stringList.add("Matty");
		List<?> list = new ArrayList<String>();
		list.add(("Matty"));
		list = stringList;
		for (Object s : list) {
			System.out.println(s);
		}
	}

	public static void main(String[] args) {
		new Test6().test();
	}
}
/*

List<?> is a supertype of any List<genericType>
We can read elements from this list and assign them Object since whatever type of collection, it always contain objects
However it is not safe to add any element to this list including Object because
the added element would have to be a subtype of the actual type of this list
and since we dont know the actual type it is illegal to add any element to it! Except null

Test6.java:10: cannot find symbol
symbol  : method add(java.lang.String)
location: interface java.util.List<capture#145 of ?>
list.add(("Matty"));

*/
import java.util.*;

public class Test7 {
	public void test() {
		List<?> driverList = new ArrayList<Driver>();
		driverList.add(new Driver("jacob"));
		driverList.add(new Driver("Matty"));
		for (Driver s : driverList) {
			System.out.println(s);
		}
	}

	public static void main(String[] args) {
		new Test7().test();
	}
}
/*
List<?> is a supertype of any List<genericType>
We can read elements from this list and assign them Object since whatever type of collection, it always contain objects
However it is not safe to add any element to this list including Object because
the added element would have to be a subtype of the actual type of this list
and since we dont know the actual type it is illegal to add any element to it! Except null

D:\work\projects\generics>javac Test7.java
Test7.java:7: cannot find symbol
symbol  : method add(Driver)
location: interface java.util.List<capture#466 of ?>
driverList.add(new Driver("jacob"));
^
Test7.java:8: cannot find symbol
symbol  : method add(Driver)
location: interface java.util.List<capture#145 of ?>
driverList.add(new Driver("Matty"));
^
Test7.java:9: incompatible types
found   : java.lang.Object
required: Driver
for(Driver s:driverList)
^
3 errors
*/


import java.util.*;

public class Test8 {
	public void test() {
		List<Driver> driverList = new ArrayList<Driver>();
		driverList.add(new Driver("jacob"));
		driverList.add(new Driver("Matty"));
		List<?> genericList = driverList;
		for (Object s : genericList) {
			System.out.println(s);
		}
	}

	public static void main(String[] args) {
		new Test8().test();
	}
}
/*

List<?> is a supertype of any List<genericType>
We can read elements from this list and assign them Object since whatever type of collection, it always contain objects
However it is not safe to add any element to this list including Object because
the added element would have to be a subtype of the actual type of this list
and since we dont know the actual type it is illegal to add any element to it! Except null

D:\work\projects\generics>java Test8
Driver@addbf1
Driver@42e816
*/

import java.util.*;

public class Test9 {
	public void test() {
		List<Driver> driverList = new ArrayList<Driver>();
		driverList.add(new Driver("jacob"));
		driverList.add(new Driver("Matty"));
		List<?> genericList = driverList;
		for (Object s : genericList) {
			System.out.println(((Driver) s).getDriver());
		}
	}

	public static void main(String[] args) {
		new Test9().test();
	}
}
/*

List<?> is a supertype of any List<genericType>
We can read elements from this list and assign them Object since whatever type of collection, it always contain objects
However it is not safe to add any element to this list including Object because
the added element would have to be a subtype of the actual type of this list
and since we dont know the actual type it is illegal to add any element to it! Except null

D:\work\projects\generics>java Test9
jacob
Matty
*/
import java.util.*;

public class Test11 {
	public void test() {
		List<Driver> driverList = new ArrayList<Driver>();
		driverList.add(new Driver("jacob"));
		driverList.add(new Driver("Matty"));
		List<Driver> genericList = driverList;
		for (Driver s : genericList) {
			System.out.println(s.getDriver());
		}
	}

	public static void main(String[] args) {
		new Test11().test();
	}
}
/*
The correct way to assign a generic list to another when we dont use wildcards

D:\work\projects\generics>java Test11
jacob
Matty
*/

import java.util.*;

public class Test12 {
	public void test() {
		List<Driver> list1 = new ArrayList<Driver>();
		list1.add(new Driver("jacob"));
		list1.add(new Driver("Matty"));
		List<Person> list2 = new ArrayList<Person>();
		list2.add(new Person("Jimmy"));
		printName(list1);
		printName(list2);
	}

	public void printName(List<? extends Person> list) {
		for (Person s : list) {
			System.out.println(s.getName());
		}
	}

	public static void main(String[] args) {
		new Test12().test();
	}
}
/*

The list of generic type <? extends Person> can accept any object which is a subtype of Person
The disadvanatage is illegal to add objects to this generic list

D:\work\projects\generics>java Test12
jacob
Matty
Jimmy
*/
import java.util.*;

public class Test13 {
	public void test() {
		List<Driver> list1 = new ArrayList<Driver>();
		list1.add(new Driver("jacob"));
		list1.add(new Driver("Matty"));
		addName(list1);
	}

	public void addName(List<? extends Person> list) {
		list.add(new Driver("abc"));
		list.add(new Person("xyz"));
	}

	public static void main(String[] args) {
		new Test13().test();
	}
}
/*

The list of generic type <? extends Person>  can accept any object which is a subtype of Person
The disadvanatage is illegal to add objects to this generic list

D:\work\projects\generics>javac Test13.java
Test13.java:13: cannot find symbol
symbol  : method add(Driver)
location: interface java.util.List<capture#145 of ? extends Person>
list.add(new Driver("abc"));
^
Test13.java:14: cannot find symbol
symbol  : method add(Person)
location: interface java.util.List<capture#339 of ? extends Person>
list.add(new Person("xyz"));
*/
import java.util.*;

public class Test15 {
	public void test() {
		List<Driver> list = new ArrayList<Driver>();
		list.add(new Driver("jacob"));
		list.add(new Driver("Matty"));
		String[] arr = new String[1];
		arr[0] = "mj";
		addArrToList(arr, list);
	}

	public void addArrToList(String[] arr, List<? extends Person> list) {
		for (String name : arr) {
			list.add(name);
		}
	}

	public static void main(String[] args) {
		new Test15().test();
	}
}
/*
The list of generic type <? extends Person> can accept any object which is a subtype of Person
The disadvanatage is illegal to add objects to this generic list

D:\work\projects\generics>javac Test15.java
Test15.java:17: cannot find symbol
symbol  : method add(java.lang.String)
location: interface java.util.List<capture#145 of ? extends Person>
list.add(name);
^
1 error
*/

import java.util.*;

public class Test16 {
	public void test() {
		Collection<Person> list = new ArrayList<Person>();
		list.add(new Person("jacob"));
		list.add(new Person("Matty"));
		Driver[] arr = new Driver[1];
		arr[0] = new Driver("mj");
		addArrToList(arr, list);// T inferred to be Person
	}

	public <T> void addArrToList(T[] arr, Collection<T> list)// generic method
																// declaration
	{
		for (T t : arr) {
			list.add(t);
		}
		for (T x : list) {
			System.out.println(((Person) x).getName());
		}
	}

	public static void main(String[] args) {
		new Test16().test();
	}
}
/*

addArrToList is a generic method. Just like type declarations, method declarations can be generic.
The method overcomes the disadvantage that was encountered in the previous example.
i.e. it allows objects to be added to generic list.
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.

Object[] oa = new Object[100];
Collection<Object> co = new ArrayList<Object>();
fromArrayToCollection(oa, co);// T inferred to be Object
String[] sa = new String[100];
Collection<String> cs = new ArrayList<String>();
fromArrayToCollection(sa, cs);// T inferred to be String
fromArrayToCollection(sa, 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

D:\work\projects\generics>java Test16
jacob
Matty
mj
*/

About cuppajavamattiz
Matty Jacob - Avid technical blogger with interests in J2EE, Web Application Servers, Web frameworks, Open source libraries, Relational Databases, Web Services, Source control repositories, ETL, IDE Tools and related technologies.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: