# Generics Generics are a facility of [generic programming](https://en.wikipedia.org/wiki/Generic_programming) that were added to the Java programming language in 2004 within version J2SE 5.0. They were designed to extend Java's type system to allow "a type or method to operate on objects of various types while providing compile-time type safety". The Java collections framework supports generics to specify the type of objects stored in a collection instance. ## Motivation The following block of Java code illustrates a problem that exists when not using generics. First, it declares an `ArrayList` of type `Object`. Then, it adds a `String` to the `ArrayList`. Finally, it attempts to retrieve the added `String` and cast it to an `Integer` — an error in logic, as it is not generally possible to cast an arbitrary string to an integer. ``` List v = new ArrayList(); v.add("test"); // A String that cannot be cast to an Integer Integer i = (Integer)v.get(0); // Run time error ``` Although the code is compiled without error, it throws a runtime exception (`java.lang.ClassCastException`) when executing the third line of code. This type of logic error can be detected during compile time by using generics and is the primary motivation for using them. The above code fragment can be rewritten using generics as follows: ``` List v = new ArrayList(); v.add("test"); Integer i = (Integer)v.get(0); // (type error) compilation-time error ``` The type parameter `String` within the angle brackets declares the `ArrayList` to be constituted of `String` (a descendant of the `ArrayList`'s generic `Object` constituents). With generics, it is no longer necessary to cast the third line to any particular type, because the result of `v.get(0)` is defined as `String` by the code generated by the compiler. The logical flaw in the third line of this fragment will be detected as a compile-time error (with J2SE 5.0 or later) because the compiler will detect that `v.get(0)` returns `String` instead of `Integer`. ## [Generic Methods](https://www.baeldung.com/java-generics#generic-methods) We write generic methods with a single method declaration, and we can call them with arguments of different types. The compiler will ensure the correctness of whichever type we use. These are some properties of generic methods: - Generic methods have a type parameter (the diamond operator enclosing the type) before the return type of the method declaration; - Type parameters can be bounded; - Generic methods can have different type parameters separated by commas in the method signature; - Method body for a generic method is just like a normal method. Here's an example of defining a generic method to convert an array to a list: ``` public List fromArrayToList(T[] a) { return Arrays.stream(a).collect(Collectors.toList()); } ``` The `` in the method signature implies that the method will be dealing with generic type `T`. This is needed even if the method is returning void. As mentioned, the method can deal with more than one generic type. Where this is the case, we must add all generic types to the method signature. Here is how we would modify the above method to deal with type `T` and type `G`: ``` public static List fromArrayToList(T[] a, Function mapperFunction) { return Arrays.stream(a) .map(mapperFunction) .collect(Collectors.toList()); } ``` We're passing a function that converts an array with the elements of type `T` to list with elements of type `G`. An example would be to convert `Integer` to its `String` representation: ``` @Test public void givenArrayOfIntegers_thanListOfStringReturnedOK() { Integer[] intArray = {1, 2, 3, 4, 5}; List stringList = Generics.fromArrayToList(intArray, Object::toString); assertThat(stringList, hasItems("1", "2", "3", "4", "5")); } ``` Note that Oracle recommendation is to use an uppercase letter to represent a generic type and to choose a more descriptive letter to represent formal types. In Java Collections, we use `T` for type, `K` for key and `V` for value. ## Generic Classes A generic class declaration looks like a non-generic class declaration, except that the class name is followed by a type parameter section. As with generic methods, the type parameter section of a generic class can have one or more type parameters separated by commas. These classes are known as parameterized classes or parameterized types because they accept one or more parameters. Following example illustrates how we can define a generic class: ``` public class Box { private T t; public void add(T t) { this.t = t; } public T get() { return t; } public static void main(String[] args) { Box integerBox = new Box(); Box stringBox = new Box(); integerBox.add(new Integer(10)); stringBox.add(new String("Hello World")); System.out.printf("Integer Value :%d\n\n", integerBox.get()); System.out.printf("String Value :%s\n", stringBox.get()); } } ``` This will produce the following result: ``` Integer Value :10 String Value :Hello World ``` ## [Bounded Generics](https://www.baeldung.com/java-generics#1-bounded-generics) Remember that type parameters can be bounded. Bounded means “restricted,” and we can restrict the types that a method accepts. For example, we can specify that a method accepts a type and all its subclasses (upper bound) or a type and all its superclasses (lower bound). To declare an upper-bounded type, we use the keyword `extends` after the type, followed by the upper bound that we want to use: ``` public List fromArrayToList(T[] a) { ... } ``` We use the keyword `extends` here to mean that the type `T` extends the upper bound in case of a class or implements an upper bound in case of an interface. ## [Multiple Bounds](https://www.baeldung.com/java-generics#2-multiple-bounds) A type can also have multiple upper bounds: ``` ``` If one of the types that are extended by `T` is a class (e.g. `Number`), we have to put it first in the list of bounds. Otherwise, it will cause a compile-time error. # Links [Generics in Java](https://en.wikipedia.org/wiki/Generics_in_Java) [The Basics of Java Generics](https://www.baeldung.com/java-generics#generic-methods) [Java - Generics](https://www.tutorialspoint.com/java/java_generics.htm) # Further reading [Lesson: Generics](https://docs.oracle.com/javase/tutorial/java/generics/index.html) [Java Generics Example Tutorial - Generic Method, Class, Interface](https://www.digitalocean.com/community/tutorials/java-generics-example-method-class-interface) [Language Features of Java Generics](http://www.angelikalanger.com/GenericsFAQ/FAQSections/Features.html) # Next questions [What do you know about wildcard?](https://github.com/Kirchhoff-/Android-Interview-Questions/blob/master/Java/What%20do%20you%20know%20about%20wildcard.md)