Generics were introduced in Java 5.0 to provide compile-time type safety and prevent runtime errors. The document discusses key features of generics like type erasure, type inference, subtype polymorphism, wildcard types, and generic methods. It analyzes data from open source projects to evaluate hypotheses about generics reducing type casts and code duplication. The findings show generics benefits were limited and adoption by projects and developers was uneven, with conversion of legacy code to use generics being uncommon.
1. Java Generics
By –
Satyajit Kulkarni
Akshay Chaudhari
2. Overview
O Introduction
O C++ Template vs Java Generics
O How generic works ?
O Type Inference and Subtype
Polymorphism
O Wildcard
O Generic Methods
O Research paper - Java Adoption
O Conclusion
2
3. Introduction
O J2SE 5.0 provides compile-time type safety
with the Java Collections framework through
generics
O Generics allows you to specify, at compile-
time, the types of objects you want to store in
a Collection. Then when you add and get
items from the list, the list already knows
what types of objects are supposed to be
acted on.
O So you don't need to cast anything. The "<>"
characters are used to designate what type is
to be stored. If the wrong type of data is
3
provided, a compile-time exception is thrown.
4. Why Generics??
O To enable a compiler to detect as much
errors as it can at compile time rather than
getting ‗surprises‘ at run time.
O Extended code reusability
O Improved readability and robustness.
4
6. Motivation for Generics
contd..
HashMap test1 = new HashMap();
test1.put(101, 9000);
test1.put(102, "9000");
Integer salary = test1.get(101); // Compile Time
Error!
salary = (Integer) test1.get(101); // Works fine.
salary = (Integer) test1.get(102); // No compile
time error and code fails at run time with
ClassCastException thrown.
6
7. Motivation for Generics
contd..
O Cast in line 2 is annoying.
O Prominently, compiler never gives any
error or warning and program fails at run
time (if line 1 is commented or removed.)
O If programmer commits mistake, cast may
get failed resulting in run time error.
O What if hashmap would be restricted to
contain only particular data type for key –
value pairs?
7
8. A program with Java Generics
HashMap<Integer, Integer> test2 = new
HashMap<Integer, Integer>();
Integer salary = null;
test2.put(101, 9000);
test2.put(102, "9000");
salary = test2.get(101);
salary = (Integer) test2.get(102);
8
9. A program with Java Generics
HashMap<Integer, Integer> test2 = new
HashMap<Integer, Integer>();
Integer salary = null;
test2.put(101, 9000);
test2.put(102, "9000"); // Compile Time
Error!!!
salary = test2.get(101); // No casting
required, makes code more readable.
9
10. Advantages of Generics
O Generics move runtime errors to compile time
errors.
O Programmers no longer have to manually cast
elements from pseudo-generic data structures
or methods.
O Generics prevent code duplication and errors
resulting from maintaining multiple typed data
collections.
O Generics enhance readability and
specification.
O Generics lower cognitive load by requiring the
programmer to remember fewer details.
10
11. C++ Templates vs. Java
Generics
C++ Templates Java Generics
Parameters can be any type, integral value, or Parameters can only be reference types (not primitive
character literal. types).
Separate copies of the class or function are likely to One version of the class or function is compiled,
be generated for each type parameter when compiled. works for all type parameters.
Type parameters are erased when compiled; objects
Objects of a class with different type parameters are
of a class with different type parameters are the same
different types at run time.
type at run time.
Templates can be specialized -- a separate
implementation could be provided for a particular Generics cannot be specialized.
template parameter.
Template parameters can have default Generic type parameters cannot have default
arguments (only for template classes, not functions). arguments.
Does not support wildcards. Instead, return types are Supports wildcard as type parameter if it is only used
often available as nested typedefs. once.
Static variables are not shared between classes of Static variables are shared between instances of a
different type parameters. classes of different type parameters.
11
12. How Generics works?
O The feature of Generics which was introduced in java
1.5 works on the principle of ―Type Erasure‖.
O Actually designed to maintain backward compatibility
with pre-Java5 code
O Reduces runtime memory load from multiple
specializations of a generic types
O After statically analyzing to ensure type safety, the
compiler removes all references to the parameters of
generic type
O Internally, type parameter X is converted to Object (or
its bound) in the byte code
O Main disadvantage of type erasure is that as type
information is not present at run time, automatically
generated casts may fail when interoperating with ill-
behaved legacy code.
12
13. Another Feature -> Type
Inference
O We can replace the type arguments required to
invoke the constructor of a generic class with an
empty set of type parameters (<>) as long as the
compiler can infer the type arguments from the
context.
O This pair of angle brackets is informally called
the diamond.
e.g. Map<String, String> myMap = new
HashMap<String, String>();
can be written as
Map<String, String> myMap = new
HashMap<>(); 13
14. Type Inference contd..
O class MyClass<X> {
<T> MyClass(T t) {
// ... }
}
O Consider the following instantiation of the class MyClass,
which is valid in Java SE 7 and prior releases:
new MyClass<Integer>("")
O MyClass<Integer> myObject = new <String>
MyClass<>("");
O MyClass<Integer> myObject = new MyClass<>(""); // After
Java
SE 7
14
15. Subtype Polymorphism
O The same piece of code can be reused by taking different types of
objects (as real method arguments), as long as they all belong to
subtypes of a base type.
O For example, you can assign an Integer to an Object,
since Object is one of Integer's super types:
Object someObject = new Object();
Integer someInteger = new Integer(10);
someObject = someInteger; // OK
Similarly,
public void someMethod(Number n){
// method body omitted }
someMethod(new Integer(10)); // OK
someMethod(new Double(10.1)); // OK
15
16. Subtype Polymorphism
contd…
O The same is also true with generics. You can perform a generic type
invocation, passing Number as its type argument, and any subsequent
invocation of add will be allowed if the argument is compatible with Number:
Box<Number> box = new Box<Number>();
box.add(new Integer(10)); // OK
box.add(new Double(10.1)); // OK
O Now consider the following method:
public void boxTest(Box<Number> n){
// method body omitted }
O Are we allowed to pass in Box<Integer> or Box<Double>, as one might
expect?
O Surprisingly, the answer is "no", because Box<Integer> and Box<Double> are
not subtypes of Box<Number>.
16
17. Wildcard
O Older version of the language (i.e., a pre-5.0 release):
void printCollection(Collection c) {
Iterator i = c.iterator();
for (k = 0; k < c.size(); k++) {
System.out.println(i.next()); }}
O Using generics (and the new for loop syntax):
void printCollection(Collection<Object> c) {
for (Object e : c) {
System.out.println(e); }}
Problem: Collection<Object> is not a supertype of all kinds of
collections.
Solution: Wildcard Type
Collection whose element type matches anything called a wildcard
type written Collection<?>
17
18. Parameterized Bounded
Wildcard
O Suppose TwoD,
ThreeD and FourD
be the three classes
18
19. Parameterized Bounded
Wildcard contd…
O Defining an upper bound of wild card:
List<FourD> fourD = new FourDList<FourD>();
List<? extends ThreeD> threeD= fourD;
O FourD is a subtype of ThreeD and List< FourD > is a subtype of
List<? extends ThreeD >.
O ThreeD is the Upper bound of the wildcard
O Defining a lower bound of wild card:
List<TwoD> twoD = new twoDList<TwoD>();
List<? super ThreeD> = TwoD;
O ThreeD is the lower bound of the wildcard
19
20. Wildcard Example#2
O interface Cage<E> extends Collection<E>; // A cage is a collection of things, with bars
to keep them in.
O interface Lion extends Animal {} // A lion is a kind of animal, so Lion would be a subtype
of Animal:
Lion king = ...;
Animal a = king; // Where we need some animal, we're free to provide a lion:
Cage<Lion> lionCage = ...; // A lion can of course be put into a lion cage:
lionCage.add(king);
O interface Butterfly extends Animal {}
Butterfly monarch = ...;
Cage<Butterfly> butterflyCage = ...;
butterflyCage.add(monarch); // and a butterfly into a butterfly cage:
O Cage<Animal> animalCage = ...; // A cage which can contain any animal
animalCage.add(king); // This is a cage designed to hold all kinds of animals, mixed
together. It must have bars strong enough to hold in the lions, and spaced
closely enough to hold in the butterflies.
animalCage.add(monarch);
20
21. Wildcard Example#2
contd…
O animalCage = lionCage; // compile-time error
animalCage = butterflyCage; // compile-time error
O "Is Cage<Lion> a subtype of Cage<Animal>?".
By the above definition of animal cage, the answer must be "no". This is surprising!
O Reason: A lion cage cannot be assumed to keep in butterflies, and a butterfly cage
cannot be assumed to hold in lions. Therefore, neither cage can be considered an "all-
animal" cage.
O The phrase "animal cage― defined a cage designed not for any kind of animal, but
rather for some kind of animal whose type is unknown.
O So by generics, cage capable of holding some kind of animal:
Cage<? extends Animal> someCage = ...;
O "? extends Animal" as "an unknown type that is a subtype of Animal,
possibly Animal itself.
O This is an example of a bounded wildcard, where Animal forms the upper bound of
the expected type..
21
22. Wildcard Example#2
contd…
O Cage<Lion> and Cage<Butterfly> are not subtypes of Cage<Animal>,but they are
subtypes of
Cage<? extends Animal>:
someCage = lionCage; // OK
someCage = butterflyCage; // OK
O Question: "Can you add butterflies and lions directly to someCage?".
O Answer: ―No―.
someCage.add(king); // compiler-time error
someCage.add(monarch); // compiler-time error
O Reason:
O If someCage is a butterfly cage, it would hold butterflies just fine, but the lions
would be able to break free.
O If it's a lion cage, then all would be well with the lions, but the butterflies would fly
away.
O So you can't set anything into someCage. You can only get its contents:
O void feedAnimals(Cage<? extends Animal> someCage) {
for (Animal a : someCage) a.feedMe(); }
O Here, you can invoke this method first for the lions and then for the butterflies:
feedAnimals(lionCage);
22
feedAnimals(butterflyCage);
23. Generic Method
O static void fromArrayToCollection(Object[] a, Collection<?> c) {
for (Object o : a) {
c.add(o); // Compile time error
}}
O Problem: One cannot just shove objects into a collection of
unknown type.
O Solution: Generic methods. Just like type declarations, method
declarations can be generic--that is, parameterized by one or more
type parameters.
O static <T> void fromArrayToCollection(T[] a, Collection<T> c) {
for (T o : a) {
c.add(o); // Correct
}}
23
24. Difference between non-Generic
Method and Generic Method
O When a non-generic method is invoked,
actual arguments are substituted for the
formal parameters, and the method body
is evaluated.
O When a generic declaration is invoked,
the actual type arguments are substituted
for the formal type parameters.
24
25. Java Generics Adoption:
How New Features are
Introduced, Championed,
or Ignored
By:-
Chris Parnin
Christian Bird
Emerson Murphy-Hill
26. Claims on generics
O Naftalin and Wadler "generics work
synergistically with other features of Java
such as for-each for loops and
autoboxing."
O In Effective Java, Bloch ―By using
generics, the type system shows the
developer exactly where he inserted the
incorrect object, reducing the time to fix
the problem.‖
O Donavan et al. ―The addition of generics
to the type system moves runtime errors
to compile time type errors.‖
27. Hypothesis & Questions
O Hypothesis 1 - When generics are introduced
into a code-base, the number of type casts in
that codebase will be reduced.
O Hypothesis 2 - Introduction of user-defined
generics classes reduce code-duplication.
O Question 1 - Will project members broadly use
generics after introduction into the project?
O Question 2 - Will there be large-scale efforts to
convert old code using raw types to use
generics?
O Question 3 - Does generics support in the IDE
influence adoption?
28. Projects Studied
O ohloh.net
O The 20 most used project were:-
O Ant, Azureus, CheckStyle, Commons
Collections, FreeMind, FindBugs, Jetty,
JEdit, JDT, JUnit, Eclipse-cs, Hibernate,
Log4j, Lucene, Maven, Spring
Framework, Squirrel-SQL, Subclipse,
Weka and Xerces.
30. Hypothesis - 2
O Number of unique parameterizations for all
parameterized types to determine the number
of clones.
O D = LOC *(P - 1)
O E=D*R*K
O where D - Duplicated lines
P - Unique parameter
LOC- Lines of Code
R - No of revision
K - error constant
E – Estimated potential faults
31. cont…
O Results:-
O 107,985 lines of duplicated code were prevented.
O 400 errors would have been prevented
O 28 bugs were prevented by a generic type
O This supports Hypothesis 2; however, the impact
may not have been as extensive as expected.
The benefit of preventing code duplication is
largely conned to a few highly used types.
32. Raw type generification
O Total raw types generified/raw types
introduced
O Squirrel-SQL 574/1240 (40.7%)
O JEdit 517/4360 (11.9%)
O Eclipse-cs 30/497 (6%)
O Commons Collections (28%) and Lucene
(33.4%)
O Only 3 of the 15 projects that use generics
converted more than 12%
O most projects do not show a large scale
conversion of raw to parameterized types.
34. contd..
O Generics are usually introduced by one or
two contributors who champion their use
and broad adoption by the project
community is uncommon.
O Lack of IDE support for generics did not
have an impact on its adoption.
35. Conclusion
O Over half of the projects and developers
did not use generics; for those that did,
use was consistently narrow.
O Generics are almost entirely used to either
hold or traverse collections of objects in a
type safe manner.
36. Favorite Questions
O public class AnimalHouse<E> {
private E animal;
public void setAnimal(E x) { animal = x; }
public E getAnimal() { return animal; }
}
public class Animal{ }
public class Cat extends Animal { }
public class Dog extends Animal { }
O For the following code snippets, identify whether the code:
A. fails to compile,
B. compiles with a warning,
C. generates an error at runtime, or
D. none of the above (compiles and runs without problem.)
36
37. Favorite Questions Continued
O Question:
AnimalHouse<Animal> house = new
AnimalHouse<Cat>();
O Answer:
Fails to compile.
Reason : AnimalHouse<Cat> and
AnimalHouse<Animal> are not compatible types, even
though Cat is a subtype of Animal.
37
38. Favorite Questions Continued
O Question:
AnimalHouse<Cat> house = new
AnimalHouse<Animal>();
O Answer:
Fails to compile.
Reason: Same as 1a: AnimalHouse<Cat>
and AnimalHouse<Animal> are not
compatible types, even though Cat is a
subtype of Animal.
38
39. Favorite Questions Continued
O Question:
AnimalHouse<?> house = new
AnimalHouse<Cat>(); house.setAnimal(new
Cat());
O Answer:
Fails to compile.
Reason: While the first line is acceptable — it is
OK to define an instance of unknown type — the
compiler doesn't know the type of animal stored in
house so the setAnimal method cannot be used.
39
40. Favorite Questions Continued
O Question:
AnimalHouse house = new AnimalHouse();
house.setAnimal(new Dog());
O Answer:
Compiles with a warning.
Reason: The compiler doesn't know what
type house contains. It will accept the code,
but warn that there might be a problem when
setting the animal to an instance of Dog.
40
41. References
O http://en.wikipedia.org/wiki/Comparison_of_Java_a
nd_C%2B%2B#Templates_vs._Generics
O http://download.oracle.com/javase/tutorial/extra/ge
nerics/index.html
O http://download.oracle.com/javase/tutorial/java/gen
erics/index.html
O http://www.javacodegeeks.com/2011/04/java-
generics-quick-tutorial.html
O http://javarevisited.blogspot.com/2011/09/generics-
java-example-tutorial.html
O http://people.engr.ncsu.edu/ermurph3/papers/msr1
1.pdf
41