0% found this document useful (0 votes)
2 views18 pages

Generics

The document explains the concept of Generics in Java, highlighting the importance of type safety in collections and the differences between arrays and collections. It details how generics allow for type-safe operations without the need for type casting, and introduces bounded types and wildcards for greater flexibility in generic programming. Additionally, it provides examples of generic classes, methods, and the use of wildcards with extends and super keywords.

Uploaded by

Rakesh kumar
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views18 pages

Generics

The document explains the concept of Generics in Java, highlighting the importance of type safety in collections and the differences between arrays and collections. It details how generics allow for type-safe operations without the need for type casting, and introduces bounded types and wildcards for greater flexibility in generic programming. Additionally, it provides examples of generic classes, methods, and the use of wildcards with extends and super keywords.

Uploaded by

Rakesh kumar
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

Generics:

—------
In Java applications, if we represent the same type of elements as a
single entity there we are able to get Type Safety and we are able to
perform Type safe operations.

In Java applications, if we represent different types of elements as a


single entity then we are unable to get Type Safety and we are unable
to perform Type Safe operations.

As per the above rule, in Java Arrays are able to provide Type
Safety , because Arrays are able to allow only one type of elements
and it is giving guarantee for the elements type but Collections are
unable to provide Type Safety , because Collections are able to allow
different types of elements and it is not giving guarantee for the
elements type.

To represent one thing if we allow only one data type then it is type
safe operation.

EX: Arrays are providing type safe operation.


Student[] std = new Student[3];
std[0] = new Student();----> Valid
std[1] = new Student();----> Valid
std[2] = new Customer();---> Invalid

To represent one thing if we allow more than one type then it is Type
unsafe operation.

EX: Collection objects are providing type Unsafe operation, because


Collection objects are able to allow heterogeneous elements.
ArrayList al = new ArrayList();
[Link]("AAA");
[Link](new Employee());
[Link](new Integer(10));
[Link](new StringBuffer("CCC"));

If we use Generics along with Collections then it is not required to


type cast while iterating elements.

In Collections, the main purpose of Generics is


1. To provide Type Safety in Collections
2. To avoid Type Casting problems while reading elements from
Collections.
In Collections to improve typedness or to provide type safe operations
then we have to use "Generics".
In Collections, if we want to read an element from Collection object
then we have to use get() method, it will return the element in Object
type, where we have to perform Typecasting to get elements in their
original type.
EX:
ArrayList al = new ArrayList();
[Link](“AAA”);
[Link](“BBB”);
[Link](“CCC”);
[Link](10);

String str1 = (String)[Link](0);


String str2 = (String)[Link](1);
String str3 = (String)[Link](2);
String str4 = (String)[Link](3); —> [Link]

To overcome the above Type Safety problem and Type Casting problem we
have to use Generics which are introduced by JAVA in its JDK1.5
version.

Generics is a Type parameter specified along with Collections in order


to fix a particular type of elements to add.

To provide Generics in Collections we have to use the following


Syntax.

CollectionType<Type> refVar = new CollectionType<Type>();

EX:
ArrayList<String> al = new ArrayList<String>();

Here ArrayList is able to allow only String type elements, if we add


any other element then the compiler will raise an error.

[Link](“AAA”);
[Link](“BBB”);
[Link](“CCC”);
[Link](new Integer(10)); —---> Error
Now we can get elements from the above ArrayList object directly in
the form of String without using Type casting.

String str1 = [Link](0);


String str2 = [Link](1);
String str3 = [Link](2);

EX:
ArrayList<Integer> al = new ArrayList<Integer>();
[Link](new Integer(10));
[Link](new Integer(20));
[Link](new Integer(30));
[Link](new String(“AAA”)); —-> Error

Integer in1 = [Link](0);


Integer in2 = [Link](1);
Integer in3 = [Link](2);

EX:
import [Link];

public class Main {


public static void main(String[] args) {
ArrayList<String> al = new ArrayList<String>();
[Link]("AAA");
[Link]("BBB");
[Link]("CCC");
[Link]("DDD");
//[Link](new Integer(10)); ---> Error
[Link](al);
String str1 = [Link](0);
String str2 = [Link](1);
String str3 = [Link](2);
String str4 = [Link](3);
[Link](str1);
[Link](str2);
[Link](str3);
[Link](str4);
}
}
In the case of Collections we are unable to provide primitive data
types as Generic Types.

EX:
ArrayList<int> al = new ArrayList<int>(); —-> Invalid
ArrayList<Integer> al = new ArrayList<Integer>(); —> Valid

In the case of Collections, we are unable to provide polymorphism over


the generic Types.

EX:
ArrayList<Serializable> al = new ArrayList<String>();
Compilation Error

ArrayList<Object> al = new ArrayList<String>();


Compilation Error

Generic Classes:
—-----------------
If we declare a class with Generic parameter Type then that class is
called Generic class.

Syntax:
class ClassName<Type>{
—---
}

If we want to create an Object for the generic class then we have to


use the following syntax.

ClassName<Type> refVar = new ClassName<Type>();

EX:
Before the JDK1.5 version, the ArrayList class was as below.

Public class ArrayList{


public void add(Object obj){
—----
}
public Object get(int index){
—----
}
}
After JDK1.5 version the ArrayList was as below.

Public class ArrayList<T>{


public void add(T t){
—----
}
public T get(int index){
—----
}
}

EX:
class Account<T>{
—---
}
EX:
Account<Gold> acc = new Account<Gold>();
Account<Silver> acc = new Account<Silver>();

EX:
Medal<Gold> medal = new Medal<Gold>();
Medal<Silver> medal = new Medal<Silver>();

EX:
class Test<T>{
T t;
Test(T t){
this.t = t;
}
public void show(){
[Link]("The Type of Object is :
"+[Link]().getName());
}
public T getObject(){
return t;
}
}
public class Main {
public static void main(String[] args) {
Test<Integer> test1 = new Test<Integer>(10);
[Link]();
[Link]([Link]());

Test<String> test2 = new Test<String>("Durgasoft");


[Link]();
[Link]([Link]());

Test<Double> test3 = new Test<Double>(22.2222);


[Link]();
[Link]([Link]());

}
}

Bounded Types:
—-------------
If we declare a generic class then we are able to pass any data type
as generic type Parameter.

class Test<T>{
}
It is an unbounded type, we can pass any type of parameter.

Test<Integer> t1 = new Test<Integer>();


Test<String> t2 = new Test<String>();
In the above example, if we want to restrict generic Type parameters
then we have to use Bounded Types by using ‘extends’ keyword.

Syntax:

class Test<T extends X>{


}

1. Where if X is a class then we are able to pass either X type or


its sub types only as type parameters.
2. Where if X is an interface then we are able to pass either X or
its implementation classes only.

EX:
class Payment
{
}
class CashPayment extends Payment
{
}
class CardPayment extends Payment
{
}
class Bill<T extends Payment>
{
}
Bill<Payment> bill = new Bill<Payment>(); —--->Valid
Bill<CashPayment> bill = new Bill<CashPayment>(); —--->Valid
Bill<CardPayment> bill = new Bill<CardPayment>(); —---->Valid

EX:
class Test<T extends Number>{
}
Test<Number> t = new Test<Number>(); —---->Valid
Test<Integer> t = new Test<Float>(); —---->Valid
Test<String> t = new Test<String>(); —---->Invalid

If 'X' is an interface then we are Able to pass either X type elements


of its implementation class types as parameter.

EX:
class Test<T extends Number>{

}
public class Main {
public static void main(String[] args) {
Test<Number> test1 = new Test<Number>();
Test<Integer> test2 = new Test<Integer>();
Test<Float> test3 = new Test<Float>();
//Test<String> test4 = new Test<String>(); ---> Error
}
}

EX:
import [Link];

class Test<T extends Serializable>{

}
public class Main {
public static void main(String[] args) {

Test<Number> test1 = new Test<Number>();


Test<Integer> test2 = new Test<Integer>();
Test<Float> test3 = new Test<Float>();
Test<String> test4 = new Test<String>();
//Test<Thread> test5 = new Test<Thread>(); --> Error
}
}

Note: To declare bounded types in the Generic classes we have to use


only extends keyword, it is not possible to use super keyword and
implements keywords.
class Test<T implements Runnable>
{
}
Status: Invalid

EX:
class Test<T super String>
{
}
Status: Invalid

In Generic classes, we can use more than one type as bounded parameter
by using '&' symbol.
class Test<T extends Runnable & Serializable>{}

Here Test class is able to allow the elements which must be either the
same as NUmber or sub classes to the number and which must be the
implementations of Serializable interface.

Test t=new Test();--> Valid


Test t=new Test();--> Valid
Test t=new Test--> Invalid.

EX:
class Test<T extends Number & Thread>{}

Status: Invalid
Reason: extends keyword will not allow two class types at a time.

EX:
class Test<T extends Number & Serializable>{}

Statis: valid.
Reason: extends keyword is able to allow more than one interface type.

EX:
class Test<T extends Number & Runnable>{}

Status: Valid.
Reson: Extends is able to allow both class type and interface type ,
but, first we have to specify class type then we have to specify
Interface type.

EX:
class Test<T extends Runnable & Number>{}

Status: Invalid.
Reason: extends keyword allows first class_Name then interface_Name

EX:
import [Link].*;
class Account
{
String accNo;
String accName;
String accType;
Account(String accNo, String accName, String accType)
{
[Link]=accNo;
[Link]=accName;
[Link]=accType;
}
}
class Bank
{
public ArrayList getAccountsList(ArrayList al)
{
[Link](new Account("a111", "AAA", "Savings"));
[Link](new Account("b111", "BBB", "Savings"));
[Link](new Account("c111", "CCC", "Savings"));
[Link](new Account("d111", "DDD", "Savings"));
return al;
}
}
class Test {
public static void main(String[] args){
ArrayList al=new ArrayList();
Bank bank=new Bank();
ArrayList acc_List=[Link](al);
[Link]("ACCNO\tACCNAME\tACCTYPE");
[Link]("------------------------------");
for(Account acc: acc_List){
[Link]([Link]+"\t"+[Link]+"\
t"+[Link]);
}
}
}

Wild Card Characters in Generic Methods:


—----------------------------------------
If we declare a method with the parameter contains generic Type then
that method is a Generic method.
EX:
void m1(ArrayList<String> al){
}

The above method is able to take an ArrayList as a parameter, it must


have only String type elements, it must not have any other type
elements.
EX:
import [Link];
import [Link];

class Bank{
public void getCustomersDetails(ArrayList<String> list){

[Link](list);
}
}

public class Main {


public static void main(String[] args) {
Bank bank = new Bank();
ArrayList<String> al = new ArrayList<String>();
[Link]("AAA");
[Link]("BBB");
[Link]("CCC");
[Link](al);

ArrayList<Integer> al1 = new ArrayList<Integer>();


[Link](10);
[Link](20);
[Link](30);
//[Link](al1); --> Error

}
}

EX:
void m1(ArrayList<Integer> al){
}

The above method is able to take an ArrayList as a parameter, it must


have only Integer type elements, it must not have any other type
elements.

EX:
import [Link];
import [Link];
class Bank{
public void getCustomersDetails(ArrayList<Integer> list){

[Link](list);
}
}

public class Main {


public static void main(String[] args) {
Bank bank = new Bank();
ArrayList<String> al = new ArrayList<String>();
[Link]("AAA");
[Link]("BBB");
[Link]("CCC");
//[Link](al); --> error

ArrayList<Integer> al1 = new ArrayList<Integer>();


[Link](10);
[Link](20);
[Link](30);
[Link](al1);

}
}

In the Generic Methods,if we want to pass a parameter having Generic


Type and it must have any type of elements then we have to use
Wildcard character.

Syntax:
void m1(ArrayList<?> al){
}

Inside the method we must not add any other element except null.

EX:
import [Link];
import [Link];

class Bank{
public void getCustomersDetails(ArrayList<?> list){
[Link](list);
}
}

public class Main {


public static void main(String[] args) {
Bank bank = new Bank();
ArrayList<String> al = new ArrayList<String>();
[Link]("AAA");
[Link]("BBB");
[Link]("CCC");
[Link](al);

ArrayList<Integer> al1 = new ArrayList<Integer>();


[Link](10);
[Link](20);
[Link](30);
[Link](al1);

}
}

In the generic methods we are able to provide boundaries to the


wildcard characters by using extends and super keywords.

void m1(ArrayList<? extends X> al){


}

If X is a class then the ArrayList is able to add either X type


elements or its subtype elements.

If X is an interface then this method is applicable for ArrayList of


either X type element or its implementation class types.

EX:
import [Link];
import [Link];

class Bank{
public void getDetails(ArrayList<? extends Number> list){
[Link](list);
}
}

public class Main {


public static void main(String[] args) {
Bank bank = new Bank();

ArrayList<Integer> al1 = new ArrayList<Integer>();


[Link](10);
[Link](20);
[Link](30);
[Link](al1);

ArrayList<Float> al2 = new ArrayList<Float>();


[Link](22.22f);
[Link](33.33f);
[Link](44.44f);
[Link](al2);

ArrayList<String> al3 = new ArrayList<String>();


[Link]("AAA");
[Link]("BBB");
[Link]("CCC");
//[Link](al3); --> Error

}
}

EX:
import [Link];
import [Link];

class Bank{
public void getDetails(ArrayList<? extends Serializable> list){

[Link](list);
}
}

public class Main {


public static void main(String[] args) {
Bank bank = new Bank();

ArrayList<Integer> al1 = new ArrayList<Integer>();


[Link](10);
[Link](20);
[Link](30);
[Link](al1);

ArrayList<Float> al2 = new ArrayList<Float>();


[Link](22.22f);
[Link](33.33f);
[Link](44.44f);
[Link](al2);

ArrayList<String> al3 = new ArrayList<String>();


[Link]("AAA");
[Link]("BBB");
[Link]("CCC");
[Link](al3);

}
}

void m1(ArrayList<? super X>){


}

If X is a class then it is applicable for the ArrayList of either X


type or its Super type elements.

If X is an interface then this method is applicable for ArrayList of


either X type or super classes of the X implementation class.

EX:
import [Link];
import [Link];

class Bank{
public void getDetails(ArrayList<? super Integer> list){

[Link](list);
}
}
public class Main {
public static void main(String[] args) {
Bank bank = new Bank();

ArrayList<Integer> al1 = new ArrayList<Integer>();


[Link](10);
[Link](20);
[Link](30);
[Link](al1);

ArrayList<Number> al2 = new ArrayList<Number>();


[Link](22.22f);
[Link](33.33f);
[Link](44.44f);
[Link](al2);

ArrayList<Float> al3 = new ArrayList<Float>();


[Link](22.22f);
[Link](33.33f);
[Link](44.44f);
//[Link](al3); --> Error

}
}

EX:
import [Link];
import [Link];

class Bank{
public void getDetails(ArrayList<? super Runnable> list){

[Link](list);
}
}

public class Main {


public static void main(String[] args) {
Bank bank = new Bank();

ArrayList<Runnable> al1 = new ArrayList<Runnable>();


[Link](al1);

ArrayList<Object> al2 = new ArrayList<Object>();


[Link](al2);

}
}

Q)Find the valid Syntaxes from the following generic Declarations?


—-----------------------------------------------------------------
1. ArrayList<String> al = new ArrayList<String>();// Valid
2. ArrayList<?> al = new ArrayList<String>();//Valid
3. ArrayList<?> al = new ArrayList<Integer>();//Valid
4. ArrayList<? extends Number> al = new ArrayList<Integer>();//
Valid
5. ArrayList<? extends Number> al = new ArrayList<String>();//
Invalid
6. ArrayList<?> al = new ArrayList<? extends Number>();// Invalid
7. ArrayList<?> al = new ArrayList<?>();// Invalid
8. Map<String, String> map = new HashMap<String, String>();//Valid
9. Map<String, Number> map = new HashMap<String, Integer>();//
Invalid
10. Map<?,?> map = new HashMap<String, String>();// Valid
11. Map<?,?> map = new HashMap<Integer, Integer>();// Valid
12. class Test<T extends Number>{ } // Valid
13. class Test<T extends Number, String>{} // Valid
14. class Test<T extends Number, Runnable>{} // Valid
15. Class Test{ void m1(ArrayList<String> al){} }// Valid
16. Class Test{ void m1(ArrayList<?> al){} }// Valid
17. Class Test{ void m1(ArrayList<? extends Number> al){} }//
Valid
18. Class Test{ void m1(ArrayList<? extends Number, String>
al){}}//Invalid
19. Class Test{ void m1(ArrayList<? extends Number, Runnable>
al){}}//Invalid
20. Class Test{ void m1(ArrayList<? super Integer>
al){}}//valid
21. Class Test{ void m1(ArrayList<? super Integer,String> al)
{}}//invalid
22. Class Test{ void m1(ArrayList<? super Integer,Runnable> al)
{}}//Invalid

You might also like