Generics was added in Java 5 to provide compile-time type checking and removing risk of
In the heart of generics is “type safety“. What exactly is type safety? It’s just a guarantee by compiler that if correct Types are used in correct places then there should not be any
Another important term in java generics is “type erasure“. It essentially means that all the extra information added using generics into sourcecode will be removed from bytecode generated from it. Inside bytecode, it will be old java syntax which you will get if you don’t use generics at all. This necessarily helps in generating and executing code written prior java 5 when generics were not added in language.
Let’s understand with an example.
When you write above code and compile it, you will get below error: “The method add(Integer) in the type
Second part is getting byte code after removing second line from above example. If you compare the bytecode of above example with/without generics, then there will not be any difference. Clearly compiler removed all generics information. So, above code is very much similar to below code without generics.
In generic code, the question mark (?), called the wildcard, represents an unknown type. A wildcard parameterized type is an instantiation of a generic type where at least one type argument is a wildcard. Examples of wildcard parameterized types are Collection, List, Comparator and Pair. The wildcard can be used in a variety of
situations: as the type of a parameter, field, or local variable;
sometimes as a return type (though it is better programming practice to
be more specific). The wildcard is never used as a type argument for a
generic method invocation, a generic class instance creation, or a
supertype.
Having wild cards at difference places have different meanings as well. e.g.
For example, below are valid declarations involving wild cards:
And below are not valid uses of wildcards, and they will give compile time error.
Wildcards in generics can be unbounded as well as bounded. Let’s identify the difference in various terms.
In below given example, I have created three classes i.e.
Here problem is that
b) You can not create an instance of T
c) Generics are not compatible with primitives in declarations
d) You can’t create Generic exception class,
ClassCastException
that was common while working with collection classes. The whole
collection framework was re-written to use generics for type-safety.
Let’s see how generics help us using collection classes safely.In the heart of generics is “type safety“. What exactly is type safety? It’s just a guarantee by compiler that if correct Types are used in correct places then there should not be any
ClassCastException
in runtime. A usecase can be list of Integer
i.e. List
. If you declare a list in java like List
, then java guarantees that it will detect and report you any attempt to insert any non-integer type into above list.Another important term in java generics is “type erasure“. It essentially means that all the extra information added using generics into sourcecode will be removed from bytecode generated from it. Inside bytecode, it will be old java syntax which you will get if you don’t use generics at all. This necessarily helps in generating and executing code written prior java 5 when generics were not added in language.
Let’s understand with an example.
List new ArrayList list.add( 1000 ); //works fine list.add( "mukesh" ); //compile time error; |
List
is not applicable for the arguments (String)“. Compiler warned you. This exactly is generics sole purpose i.e. Type Safety.Second part is getting byte code after removing second line from above example. If you compare the bytecode of above example with/without generics, then there will not be any difference. Clearly compiler removed all generics information. So, above code is very much similar to below code without generics.
List list =
new
ArrayList();
list.add(
1000
);
In generic code, the question mark (?), called the wildcard, represents an unknown type. A wildcard parameterized type is an instantiation of a generic type where at least one type argument is a wildcard. Examples of wildcard parameterized types are Collection, List, Comparator and Pair
Having wild cards at difference places have different meanings as well. e.g.
- Collection denotes all instantiations of the Collection interface regardless of the type argument.
- List denotes all list types where the element type is a subtype of Number.
- Comparator denotes all instantiations of the Comparator interface for type argument types that are supertypes of String.
For example, below are valid declarations involving wild cards:
Collection coll = new ArrayList //OR List //OR Pair new Pair |
List //OR Comparator |
Unbounded wildcard parameterized type
A generic type where all type arguments are the unbounded wildcard “?” without any restriction on type variables. e.g.ArrayList list = new ArrayList //or ArrayList list = new ArrayList //or ArrayList list = new ArrayList |
Bounded wildcard parameterized type
Bounded wildcards put some restrictions over possible types, you can use to instantiate a parametrized type. This restriction is enforced using keywords “super” and “extends”. To differentiate more clearly, let’s devide them into upper bounded wildcards and lower bounded wildcards.Upper bounded wildcards
For example, say you want to write a method that works on List, List, and List; you can achieve this by using an upper bounded wildcard e.g. you would specify List. Here Integer, Double are subtypes of Number class. In layman’s terms, if you want generic expression to accept all subclasses of a particular type, you will use upper bound wildcard using “extends” keyword.public class GenericsExample { public static void main(String[] args) { //List of Integers List 1 , 2 , 3 , 4 , 5 ); System.out.println(sum(ints)); //List of Doubles List 1 .5d,2d,3d); System.out.println(sum(doubles)); List "1" , "2" ); //This will give compilation error as :: The method sum(List) in the //type GenericsExample System.out.println(sum(strings)); } //Method will accept private static Number sum (List double s = 0.0 ; for (Number n : numbers) s += n.doubleValue(); return s; } } |
Lower bounded wildcards
If you want a generic expression to accept all types which are “super” type of a particular type OR parent class of a particular class then you will use lower bound wildcard for this purpose, using ‘super’ keyword.In below given example, I have created three classes i.e.
SuperClass
, ChildClass
and GrandChildClass
. There relationship is shown in code below. Now, we have to create a method which somehow get a GrandChildClass
information (e.g. from DB) and create an instance of it. And we want to store this new GrandChildClass
in an already existing list of GrandChildClasses
.Here problem is that
GrandChildClass
is subtype of ChildClass
and SuperClass
as well. So any generic list of SuperClasses and ChildClasses is
capable of holding GrandChildClasses as well. Here we must take help of
lower bound wildcard using ‘super‘ keyword.package test.core; import java.util.ArrayList; import java.util.List; public class GenericsExample { public static void main(String[] args) { //List of grand children List new ArrayList grandChildren.add( new GrandChildClass()); addGrandChildren(grandChildren); //List of grand childs List new ArrayList childs.add( new GrandChildClass()); addGrandChildren(childs); //List of grand supers List new ArrayList supers.add( new GrandChildClass()); addGrandChildren(supers); } public static void addGrandChildren(List { grandChildren.add( new GrandChildClass()); System.out.println(grandChildren); } } class SuperClass{ } class ChildClass extends SuperClass{ } class GrandChildClass extends ChildClass{ } |
What is not allowed to do with Generics?
a) You can’t have static field of typeb) You can not create an instance of T
c) Generics are not compatible with primitives in declarations
d) You can’t create Generic exception class,
No comments:
Post a Comment