### /com/in28minutes/java/generics/GenericsExamples.java ``` package com.in28minutes.java.generics; import java.util.ArrayList; public class GenericsExamples { static ArrayList multiplyNumbersBy2(ArrayList numbers) { ArrayList result = new ArrayList(); for (int i = 0; i < numbers.size(); i++) { // TYPE CAST is required int value = (Integer) numbers.get(i); result.add(value * 2); } return result; } static void addElement(ArrayList something) { something.add(new String("String")); } public static void main(String[] args) { // Older code - Before Java 5 ArrayList numbers = new ArrayList(); numbers.add(5); numbers.add(6); // javac gives warning because multiplyNumbersBy2(ArrayList) is invoked // with a Specific ArrayList // and in the method multiplyNumbersBy2 an element is added to ArrayList // com/rithus/generics/GenericsExamples.java uses unchecked or unsafe // operations. // Recompile with -Xlint:unchecked for details. System.out.println(multiplyNumbersBy2(numbers));// [10, 12] // javac gives warning because addElement(ArrayList) is invoked with a // Specific ArrayList // and in the method addElement, an element is added to the list. // com/rithus/generics/GenericsExamples.java uses unchecked or unsafe // operations. addElement(numbers); // Throws runtime exception - java.lang.ClassCastException System.out.println(multiplyNumbersBy2(numbers)); // New code - After } // javac -Xlint:unchecked com/rithus/generics/GenericsExamples.java // com/rithus/generics/GenericsExamples.java:14: warning: [unchecked] // unchecked call to add(E) as a member of the raw type java.util.ArrayList // result.add(value * 2); // ^ // com/rithus/generics/GenericsExamples.java:21: warning: [unchecked] // unchecked call to add(E) as a member of the raw type java.util.ArrayList // something.add(new String("String")); // ^ // 2 warnings } ``` ### /com/in28minutes/java/generics/GenericsExamples2.java ``` package com.in28minutes.java.generics; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.List; class Animal { } class Dog extends Animal { } public class GenericsExamples2 { static void doSomethingArray(Animal[] animals) { // do Something with Animals } static void doSomethingList(List animals) { // do Something with Animals } static void doSomethingListModified(List extends Animal> animals) { // Adding an element into a list declared with ? is prohibited. // animals.add(new Animal());//COMPILER ERROR! // animals.add(new Dog());//COMPILER ERROR! } static void doSomethingListModifiedSuper(List super Dog> animals) { // Adding an element into a list declared with ? is prohibited. // animals.add(new Animal());//COMPILER ERROR! // animals.add(new Dog());//COMPILER ERROR! } /* even for interfaces extends keyword should be used */ static void doSomethingListInterface(List extends Serializable> animals) { // Adding an element into a list declared with ? is prohibited. // animals.add(new Animal());//COMPILER ERROR! // animals.add(new Dog());//COMPILER ERROR! } public static void main(String[] args) { Animal[] animalsArray = { new Animal(), new Dog() }; Dog[] dogsArray = { new Dog(), new Dog() }; List animalsList = Arrays.asList(animalsArray); List dogsList = Arrays.asList(dogsArray); // Array method can be called with Animal[] or Dog[] doSomethingArray(animalsArray); doSomethingArray(dogsArray); // List method works with List // Gives compilation error with List. doSomethingList(animalsList); // List not compatible with List // doSomethingList(dogsList);//COMPILER ERROR // Method declared with List extends Animal> compiles // with both List and List doSomethingListModified(animalsList); doSomethingListModified(dogsList); // Method declared with List super Dog> compiles // with both List and List // List of any super class of Dog is fine. // List of any Subclass of Dog is not valid parameter. doSomethingListModifiedSuper(animalsList); doSomethingListModifiedSuper(dogsList); // A method declared with List can only be called with a List // declared with type Object. None of the other classes are valid. // A method declared with List> can be called with a List of any type. // A method declared with List extends Object> can be called with a // List of any type - since all classes are sub classes of Object. // ? can only be used in Declaring a type. Cannot be used as part of // definition. List extends Animal> listAnimals = new ArrayList(); // COMPILES // List> genericList = new ArrayList extends Animal>(); //COMPILER // ERROR } } ``` ### /com/in28minutes/java/generics/GenericsExamples3.java ``` package com.in28minutes.java.generics; import java.util.List; class MyList { private List values; void add(String value) { values.add(value); } void remove(String value) { values.remove(value); } } class MyListGeneric { private List values; void add(T value) { values.add(value); } void remove(T value) { values.remove(value); } T get(int index) { return values.get(index); } } class MyListRestricted { private List values; void add(T value) { values.add(value); } void remove(T value) { values.remove(value); } T get(int index) { return values.get(index); } } public class GenericsExamples3 { static X doSomething(X number) { X result = number; // do something with result return result; } public static void main(String[] args) { // MyList can be used to store a list of Strings only. MyList myList = new MyList(); myList.add("Value 1"); myList.add("Value 2"); // If I would want to create MyList accepting Integer's, I would need to // create a new Class. // Solution to this Problem is generics. // Replace String with T and create a new class MyListGeneric. // Note the declaration of the class "class MyListGeneric". // Instead of T, We can use any valid identifier(ofcourse the same // identifier everywhere) // If a generic is declared as part of class declaration, it can be used // any where a type can be used in a class - method (return type or // argument), member variable etc. // Now the MyListGeneric class can be used to create a list of Integers // or a list of Strings MyListGeneric myListString = new MyListGeneric(); myListString.add("Value 1"); myListString.add("Value 2"); MyListGeneric myListInteger = new MyListGeneric(); myListInteger.add(1); myListInteger.add(2); // In MyListGeneric, Type P is defined as part of class declaration. Any // Java Type can be used a type for this class. // If we would want to restrict the types allowed for a Generic Type, we // can use a Generic Restriction // In declaration of the class, we specified a constraint // "T extends Number" // class MyListRestricted // Now, we can use the class MyListRestricted with any class extending // Number - Float, Integer, Double etc. // String not valid substitute for constraint "T extends Number" // MyListRestricted restrictedStringList = // new MyListRestricted();//COMPILER ERROR MyListRestricted restrictedListInteger = new MyListRestricted(); restrictedListInteger.add(1); restrictedListInteger.add(2); // A generic type can be declared as part of method declaration as well. // Then the generic type can be used anywhere in the method (return // type, parameter type, local or block variable type) Integer i = 5; Integer k = doSomething(i); } } ```