Advantage of Java Generics
Advantage of Java Generics
Advantage of Java Generics
The Java Generics programming is introduced in J2SE 5 to deal with type-safe objects. It makes the code
stable by detecting the bugs at compile time.
Before generics, we can store any type of objects in the collection, i.e., non-generic. Now generics force the
java programmer to store a specific type of objects.
1) Type-safety: We can hold only a single type of objects in generics. It doesn?t allow to store other objects.
3) Compile-Time Checking: It is checked at compile time so problem will not occur at runtime. The good
programming strategy says it is far better to handle the problem at compile time than runtime.
1. ClassOrInterface<Type>
2. ArrayList<String>
Full Example of Generics in Java
Here, we are using the ArrayList class, but you can use any collection class such as ArrayList, LinkedList,
HashSet, TreeSet, HashMap, Comparator etc.
1. import java.util.*;
2. class TestGenerics1{
3. public static void main(String args[]){
4. ArrayList<String> list=new ArrayList<String>();
5. list.add("rahul");
6. list.add("jai");
7. //list.add(32);//compile time error
8.
9. String s=list.get(1);//type casting is not required
10. System.out.println("element is: "+s);
11.
12. Iterator<String> itr=list.iterator();
13. while(itr.hasNext()){
14. System.out.println(itr.next());
15. }
16. }
17. }
1. import java.util.*;
2. class TestGenerics1{
3. public static void main(String args[]){
4. ArrayList<String> list=new ArrayList<String>();
5. list.add("rahul");
6. list.add("jai");
7. //list.add(32);//compile time error
8.
9. String s=list.get(1);//type casting is not required
10. System.out.println("element is: "+s);
11.
12. Iterator<String> itr=list.iterator();
13. while(itr.hasNext()){
14. System.out.println(itr.next());
15. }
16. }
17. }
Output:
Now we are going to use map elements using generics. Here, we need to pass key and value. Let us
understand it by a simple example:
1. import java.util.*;
2. class TestGenerics2{
3. public static void main(String args[]){
4. Map<Integer,String> map=new HashMap<Integer,String>();
5. map.put(1,"vijay");
6. map.put(4,"umesh");
7. map.put(2,"ankit");
8.
9. //Now use Map.Entry for Set and Iterator
10. Set<Map.Entry<Integer,String>> set=map.entrySet();
11.
12. Iterator<Map.Entry<Integer,String>> itr=set.iterator();
13. while(itr.hasNext()){
14. Map.Entry e=itr.next();//no need to typecast
15. System.out.println(e.getKey()+" "+e.getValue());
16. }
17.
18. }}
Output
1 vijay
2 ankit
4 umesh
Generic class
A class that can refer to any type is known as a generic class. Here, we are using the T type parameter to
create the generic class of specific type.
Let's see a simple example to create and use the generic class.
1. class MyGen<T>{
2. T obj;
3. void add(T obj){this.obj=obj;}
4. T get(){return obj;}
5. }
The T type indicates that it can refer to any type (like String, Integer, and Employee). The type you specify
for the class will be used to store and retrieve the data.
1. class TestGenerics3{
2. public static void main(String args[]){
3. MyGen<Integer> m=new MyGen<Integer>();
4. m.add(2);
5. //m.add("vivek");//Compile time error
6. System.out.println(m.get());
7. }}
Output
Type Parameters
The type parameters naming conventions are important to learn generics thoroughly. The common type
parameters are as follows:
1. T - Type
2. E - Element
3. K - Key
4. N - Number
5. V - Value
Generic Method
Like the generic class, we can create a generic method that can accept any type of arguments. Here, the
scope of arguments is limited to the method where it is declared. It allows static as well as non-static
methods.
Let's see a simple example of java generic method to print array elements. We are using here E to denote the
element.
Output
The ? (question mark) symbol represents the wildcard element. It means any type. If we write <? extends
Number>, it means any child class of Number, e.g., Integer, Float, and double. Now we can call the method
of Number class through any child class object.
We can use a wildcard as a type of a parameter, field, return type, or local variable. However, it is not
allowed to use a wildcard as a type argument for a generic method invocation, a generic class instance
creation, or a supertype.
1. import java.util.*;
2. abstract class Shape{
3. abstract void draw();
4. }
5. class Rectangle extends Shape{
6. void draw(){System.out.println("drawing rectangle");}
7. }
8. class Circle extends Shape{
9. void draw(){System.out.println("drawing circle");}
10. }
11. class GenericTest{
12. //creating a method that accepts only child class of Shape
13. public static void drawShapes(List<? extends Shape> lists){
14. for(Shape s:lists){
15. s.draw();//calling method of Shape class by child class instance
16. }
17. }
18. public static void main(String args[]){
19. List<Rectangle> list1=new ArrayList<Rectangle>();
20. list1.add(new Rectangle());
21.
22. List<Circle> list2=new ArrayList<Circle>();
23. list2.add(new Circle());
24. list2.add(new Circle());
25.
26. drawShapes(list1);
27. drawShapes(list2);
28. }}
Output
drawing rectangle
drawing circle
drawing circle
The purpose of upper bounded wildcards is to decrease the restrictions on a variable. It restricts the unknown
type to be a specific type or a subtype of that type. It is used by declaring wildcard character ("?") followed
by the extends (in case of, class) or implements (in case of, interface) keyword, followed by its upper bound.
Syntax
Here,
? is a wildcard character.
extends, is a keyword.
Suppose, we want to write the method for the list of Number and its subtypes (like Integer, Double).
Using List<? extends Number> is suitable for a list of type Number or any of its subclasses
whereas List<Number> works with the list of type Number only. So, List<? extends Number> is less
restrictive than List<Number>.
In this example, we are using the upper bound wildcards to write the method for List<Integer> and
List<Double>.
1. import java.util.ArrayList;
2.
3. public class UpperBoundWildcard {
4.
5.
6. private static Double add(ArrayList<? extends Number> num) {
7.
8. double sum=0.0;
9.
10. for(Number n:num)
11. {
12. sum = sum+n.doubleValue();
13. }
14.
15. return sum;
16. }
17.
18. public static void main(String[] args) {
19.
20. ArrayList<Integer> l1=new ArrayList<Integer>();
21. l1.add(10);
22. l1.add(20);
23. System.out.println("displaying the sum= "+add(l1));
24.
25. ArrayList<Double> l2=new ArrayList<Double>();
26. l2.add(30.0);
27. l2.add(40.0);
28. System.out.println("displaying the sum= "+add(l2));
29.
30.
31. }
32.
33. }
Output
Unbounded Wildcards
The unbounded wildcard type represents the list of an unknown type such as List<?>. This approach can be
useful in the following scenarios: -
o When the given method is implemented by using the functionality provided in the Object class.
o When the generic class contains the methods that don't depend on the type parameter.
1. import java.util.Arrays;
2. import java.util.List;
3.
4. public class UnboundedWildcard {
5.
6. public static void display(List<?> list)
7. {
8.
9. for(Object o:list)
10. {
11. System.out.println(o);
12. }
13.
14. }
15.
16.
17. public static void main(String[] args) {
18.
19. List<Integer> l1=Arrays.asList(1,2,3);
20. System.out.println("displaying the Integer values");
21. display(l1);
22. List<String> l2=Arrays.asList("One","Two","Three");
23. System.out.println("displaying the String values");
24. display(l2);
25. }
26.
27. }
Output
The purpose of lower bounded wildcards is to restrict the unknown type to be a specific type or a supertype
of that type. It is used by declaring wildcard character ("?") followed by the super keyword, followed by its
lower bound.
Syntax
Here,
? is a wildcard character.
super, is a keyword.
Suppose, we want to write the method for the list of Integer and its supertype (like Number, Object).
Using List<? super Integer> is suitable for a list of type Integer or any of its superclasses
whereas List<Integer> works with the list of type Integer only. So, List<? super Integer> is less restrictive
than List<Integer>.
In this example, we are using the lower bound wildcards to write the method for List<Integer> and
List<Number>.
1. import java.util.Arrays;
2. import java.util.List;
3.
4. public class LowerBoundWildcard {
5.
6. public static void addNumbers(List<? super Integer> list) {
7.
8. for(Object n:list)
9. {
10. System.out.println(n);
11. }
12.
13.
14.
15. }
16. public static void main(String[] args) {
17.
18. List<Integer> l1=Arrays.asList(1,2,3);
19. System.out.println("displaying the Integer values");
20. addNumbers(l1);
21.
22. List<Number> l2=Arrays.asList(1.0,2.0,3.0);
23. System.out.println("displaying the Number values");
24. addNumbers(l2);
25. }
26.
27. }
Output