Java Unit 2
Java Unit 2
A package as the name suggests is a pack(group) of classes, interfaces and other packages. In java we use
packages to organize our classes and interfaces. We have two types of packages in Java: built-in packages
and the packages we can create (also known as user defined package). In this guide we will learn what are
packages, what are user-defined packages in java and how to use them.
In java we have several built-in packages, for example when we need user input, we import a package like
this:
import java.util.Scanner
Here:
→ java is a top level package
→ util is a sub package
→ and Scanner is a class which is present in the sub package util.
Before we see how to create a user-defined package in java, lets see the advantages of using a package.
These are the reasons why you should use packages in Java:
Reusability: While developing a project in java, we often feel that there are few things that we are
writing again and again in our code. Using packages, you can create such things in form of classes
inside a package and whenever you need to perform that same task, just import that package and use
the class.
Better Organization: Again, in large java projects where we have several hundreds of classes, it is
always required to group the similar types of classes in a meaningful package name so that you can
organize your project better and when you need something you can quickly locate it and use it, which
improves the efficiency.
Name Conflicts: We can define two classes with the same name in different packages so to avoid
name collision, we can use packages
As mentioned in the beginning of this guide that we have two types of packages in java.
1) User defined package: The package we create is called user-defined package.
2) Built-in package: The already defined package like java.io.*, java.lang.* etc are known as built-in
packages.
We have already discussed built-in packages, lets discuss user-defined packages with the help of examples.
I have created a class Calculator inside a package name letmecalculate. To create a class inside a package,
declare the package name in the first statement in your program. A class can have only one package
declaration.
Calculator.java file created inside a package letmecalculate
package letmecalculate;
import letmecalculate.Calculator;
public class Demo{
public static void main(String args[]){
Calculator obj = new Calculator();
System.out.println(obj.add(100, 200));
}
}
To use the class Calculator, I have imported the package letmecalculate. In the above program I have
imported the package as letmecalculate.Calculator, this only imports the Calculator class. However if you
have several classes inside package letmecalculate then you can import the package like this, to use all the
classes of this package.
import letmecalculate.*;
As we have seen that both package declaration and package import should be the first statement in your java
program. Lets see what should be the order when we are creating a class inside a package while importing
another package.
//Declaring a package
package anotherpackage;
//importing a package
import letmecalculate.Calculator;
public class Example{
public static void main(String args[]){
Calculator obj = new Calculator();
System.out.println(obj.add(100, 200));
}
}
So the order in this case should be:
→ package declaration
→ package import
You can use fully qualified name to avoid the import statement. Lets see an example to understand this:
Calculator.java
package letmecalculate;
public class Calculator {
public int add(int a, int b){
return a+b;
}
public static void main(String args[]){
Calculator obj = new Calculator();
System.out.println(obj.add(10, 20));
}
}
Example.java
//Declaring a package
package anotherpackage;
public class Example{
public static void main(String args[]){
//Using fully qualified name instead of import
letmecalculate.Calculator obj =
new letmecalculate.Calculator();
System.out.println(obj.add(100, 200));
}
}
In the Example class, instead of importing the package, I have used the full qualified name such
as package_name.class_name to create the object of it. You may also want to read: static import in Java
A package inside another package is known as sub package. For example If I create a package inside
letmecalculate package then that will be called sub package.
Lets say I have created another package inside letmecalculate and the sub package name is multiply. So if I
create a class in this subpackage it should have this package declaration in the beginning:
package letmecalculate.multiply;
Multiplication.java
package letmecalculate.multiply;
public class Multiplication {
int product(int a, int b){
return a*b;
}
}
Now if I need to use this Multiplication class I have to either import the package like this:
import letmecalculate.multiply;
or I can use fully qualified name like this:
letmecalculate.multiply.Multiplication obj =
new letmecalculate.multiply.Multiplication();
Points to remember:
1. Sometimes class name conflict may occur. For example: Lets say we have two
packages abcpackage and xyzpackage and both the packages have a class with the same name, let it
be JavaExample.java. Now suppose a class import both these packages like this:
import abcpackage.*;
import xyzpackage.*;
This will throw compilation error. To avoid such errors you need to use the fully qualified name method that
I have shown above. For example
2. I have already discussed this above, let me mention it again here. If we create a class inside a package
while importing another package then the package declaration should be the first statement, followed by
package import. For example:
package abcpackage;
import xyzpackage.*;
3. A class can have only one package declaration but it can have more than one package import statements.
For example:
import abc.*;
Then it will only import classes Example1, Example2 and Example3 but it will not import the classes of sub
package.
import abc.foo.*;
This will import Demo1 and Demo2 but it will not import the Example1, Example2 and Example3.
So to import all the classes present in package and subpackage, we need to use two import statements like
this:
import abc.*;
import abc.foo.*;
Setting CLASSPATH:
package package_name;
Now having a look at the directory structure of both the packages and the testing class file:
Important points:
1. Every class is part of some package.
2. If no package is specified, the classes in the file goes into a special unnamed package (the same
unnamed package for all files).
3. All classes/interfaces in a file are part of the same package. Multiple files can specify the same package
name.
4. If package name is specified, the file must be in a subdirectory called name (i.e., the directory name
must match the package name).
5. We can access public classes in another (named) package using: package-name.class-name
What is Interface in Java with Example
What is an Interface?
An interface is just like Java Class, but it only has static constants and abstract method. Java uses Interface to
implement multiple inheritance. A Java class can implement multiple Java Interfaces. All methods in an
interface are implicitly public and abstract.
interface {
//methods
}
To use an interface in your class, append the keyword "implements" after your class name followed by the
interface name.
To understand the concept of Java Interface better, let see an example. The class "Media Player" has two
subclasses: CD player and DVD player. Each having its unique implementation method to play music.
Another class "Combo drive" is inheriting both CD and DVD (see image below). Which play method should
it inherit? This may cause serious design issues. And hence, Java does not allow multiple inheritance.
Now let's take another example of Dog.
Suppose you have a requirement where class "dog" inheriting class "animal" and "Pet" (see image below).
But you cannot extend two classes in Java. So what would you do? The solution is Interface.
Class Dog can extend to class "Animal" and implement interface as "Pet".
Java Interface Example:
interface Pet{
public void test();
}
class Dog implements Pet{
public void test(){
System.out.println("Interface Method Implemented");
}
public static void main(String args[]){
Pet p = new Dog();
p.test();
}
}
Step 2) Save , Compile & Run the code. Observe the Output.
Class Interface
In class, you can instantiate variable and create an In an interface, you can't instantiate variable and
object. create an object.
Class can contain concrete(with implementation) The interface cannot contain concrete(with
methods implementation) methods
The access specifiers used with classes are private, In Interface only one specifier is used- Public.
protected and public.
When to use Interface and Abstract Class?
Use an abstract class when a template needs to be defined for a group of subclasses
Use an interface when a role needs to be defined for other classes, regardless of the inheritance tree
of these classes
A Java class can implement multiple Java Interfaces. It is necessary that the class must implement all
the methods declared in the interfaces.
Class should override all the abstract methods declared in the interface
The interface allows sending a message to an object without concerning which classes it belongs.
Class needs to provide functionality for the methods declared in the interface.
All methods in an interface are implicitly public and abstract
An interface cannot be instantiated
An interface reference can point to objects of its implementing classes
An interface can extend from one or many interfaces. Class can extend only one class but implement
any number of interfaces
An interface cannot implement another Interface. It has to extend another interface if needed.
An interface which is declared inside another interface is referred as nested interface
At the time of declaration, interface variable must be initialized. Otherwise, the compiler will throw
an error.
The class cannot implement two interfaces in java that have methods with same name but different
return type.
Summary:
The class which implements the interface needs to provide functionality for the methods declared in
the interface
All methods in an interface are implicitly public and abstract
An interface cannot be instantiated
An interface reference can point to objects of its implementing classes
An interface can extend from one or many interfaces. A class can extend only one class but
implement any number of interfaces
Interface vs Abstract Class in Java: What's the Difference?
What is Interface?
The interface is a blueprint that can be used to implement a class. The interface does not contain any
concrete methods (methods that have code). All the methods of an interface are abstract methods.
An interface cannot be instantiated. However, classes that implement interfaces can be instantiated.
Interfaces never contain instance variables but, they can contain public static final variables (i.e., constant
class variables)
A class which has the abstract keyword in its declaration is called abstract class. Abstract classes should
have at least one abstract method. , i.e., methods without a body. It can have multiple concrete methods.
Abstract classes allow you to create blueprints for concrete classes. But the inheriting class should
implement the abstract method.
An abstract class permits you to make functionality that subclasses can implement or override whereas an
interface only permits you to state functionality but not to implement it. A class can extend only one abstract
class while a class can implement multiple interfaces.
Multiple
Implement several Interfaces Only one abstract class
Inheritances
While adding new stuff to the interface, it is a In case of Abstract Class, you can take
Default
nightmare to find all the implementors and advantage of the default
Implementation
implement newly defined stuff. implementation.
Data fields the interface cannot contain data fields. the class can have data fields.
Multiple
A class may implement numerous interfaces. A class inherits only one abstract class.
Inheritance Default
Use of Access You cannot use access modifiers for the You can use an abstract class which
modifiers method, properties, etc. contains access modifiers.
Interfaces help to define the peripheral An abstract class defines the identity of
Usage
abilities of a class. a class.
An interface can inherit multiple interfaces An abstract class can inherit a class and
Inheritance
but cannot inherit a class. multiple interfaces.
An interface can have only public abstract An abstract class has protected and
Class type
methods. public abstract methods.
Sample code for Interface and Abstract Class in Java
Interface Syntax
interface name{
//methods
}
interface Pet {
public void test();
}
class Dog implements Pet {
public void test() {
System.out.println("Interface Method Implemented");
}
public static void main(String args[]) {
Pet p = new Dog();
p.test();
}
}
Java IO Stream
Java performs I/O through Streams. A Stream is linked to a physical layer by java I/O system to make input
and output operation in java. In general, a stream means continuous flow of data. Streams are clean way to
deal with input/output without having every part of your code understand the physical.
Java encapsulates Stream under java.io package. Java defines two types of streams. They are,
1. Byte Stream : It provides a convenient means for handling input and output of byte.
2. Character Stream : It provides a convenient means for handling input and output of characters.
Character stream uses Unicode and therefore can be internationalized.
These two abstract classes have several concrete classes that handle various devices such as disk files,
network connection etc.
Some important Byte stream classes.
DataOutputStream An output stream that contain method for writing java standard data
type
These classes define several key methods. Two most important are
These two abstract classes have several concrete classes that handle unicode character.
import java.io.*;
class MyInput
{
public static void main(String[] args)
{
String text;
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
text = br.readLine(); //Reading String
System.out.println(text);
}
}
Java - RandomAccessFile
This class is used for reading and writing to random access file. A random access file behaves like a
large array of bytes. There is a cursor implied to the array called file pointer, by moving the cursor we do the
read write operations. If end-of-file is reached before the desired number of byte has been read than
EOFException is thrown. It is a type of IOException.
Constructor
Constructor Description
RandomAccessFile(String name, Creates a random access file stream to read from, and
String mode) optionally to write to, a file with the specified name.
Method
void close() It closes this random access file stream and releases any
system resources associated with the stream.
void seek(long pos) It sets the file-pointer offset, measured from the
beginning of this file, at which the next read or write
occurs.
void writeDouble(double It converts the double argument to a long using the
v) doubleToLongBits method in class Double, and then
writes that long value to the file as an eight-byte quantity,
high byte first.
void seek(long pos) It sets the file-pointer offset, measured from the
beginning of this file, at which the next read or write
occurs.
Example
1. import java.io.IOException;
2. import java.io.RandomAccessFile;
3.
4. public class RandomAccessFileExample {
5. static final String FILEPATH ="myFile.TXT";
6. public static void main(String[] args) {
7. try {
8. System.out.println(new String(readFromFile(FILEPATH, 0, 18)));
9. writeToFile(FILEPATH, "I love my country and my people", 31);
10. } catch (IOException e) {
11. e.printStackTrace();
12. }
13. }
14. private static byte[] readFromFile(String filePath, int position, int size)
15. throws IOException {
16. RandomAccessFile file = new RandomAccessFile(filePath, "r");
17. file.seek(position);
18. byte[] bytes = new byte[size];
19. file.read(bytes);
20. file.close();
21. return bytes;
22. }
23. private static void writeToFile(String filePath, String data, int position)
24. throws IOException {
25. RandomAccessFile file = new RandomAccessFile(filePath, "rw");
26. file.seek(position);
27. file.write(data.getBytes());
28. file.close();
29. }
30. }
The myFile.TXT contains text "This class is used for reading and writing to random access file."
The Java Console class is be used to get input from console. It provides methods to read texts and
passwords.
If you read password using Console class, it will not be displayed to the user.
The java.io.Console class is attached with system console internally. The Console class is introduced since
1.5.
1. String text=System.console().readLine();
2. System.out.println("Text is: "+text);
Method Description
String readLine() It is used to read a single line of text from the console.
String readLine(String fmt, Object... It provides a formatted prompt then reads the single line
args) of text from the console.
char[] readPassword(String fmt, Object... It provides a formatted prompt then reads the password
args) that is not being displayed on the console.
Console format(String fmt, Object... It is used to write a formatted string to the console
args) output stream.
Console printf(String format, Object... It is used to write a string to the console output stream.
args)
System class provides a static method console() that returns the singleton instance of Console class.
1. Console c=System.console();
1. import java.io.Console;
2. class ReadStringTest{
3. public static void main(String args[]){
4. Console c=System.console();
5. System.out.println("Enter your name: ");
6. String n=c.readLine();
7. System.out.println("Welcome "+n);
8. }
9. }
Output
1. import java.io.Console;
2. class ReadPasswordTest{
3. public static void main(String args[]){
4. Console c=System.console();
5. System.out.println("Enter password: ");
6. char[] ch=c.readPassword();
7. String pass=String.valueOf(ch);//converting char array into string
8. System.out.println("Password is: "+pass);
9. }
10. }
Output
Enter password:
Password is: 123
Serialization and Deserialization in Java
1. Serialization
2. Serializable Interface
3. Example of Serialization
4. Example of Deserialization
5. Serialization with Inheritance
6. Externalizable interface
7. Serialization and static data member
Serialization in Java is a mechanism of writing the state of an object into a byte-stream. It is mainly used in
Hibernate, RMI, JPA, EJB and JMS technologies.
The reverse operation of serialization is called deserialization where byte-stream is converted into an object.
The serialization and deserialization process is platform-independent, it means you can serialize an object in
a platform and deserialize in different platform.
For serializing the object, we call the writeObject() method ObjectOutputStream, and for deserialization we
call the readObject() method of ObjectInputStream class.
We must have to implement the Serializable interface for serializing the object.
It is mainly used to travel object's state on the network (which is known as marshaling).
java.io.Serializable interface
Serializable is a marker interface (has no data member and method). It is used to "mark" Java classes so that
the objects of these classes may get a certain capability. The Cloneable and Remote are also marker
interfaces.
1. import java.io.Serializable;
2. public class Student implements Serializable{
3. int id;
4. String name;
5. public Student(int id, String name) {
6. this.id = id;
7. this.name = name;
8. }
9. }
In the above example, Student class implements Serializable interface. Now its objects can be converted into
stream.
ObjectOutputStream class
The ObjectOutputStream class is used to write primitive data types, and Java objects to an OutputStream.
Only objects that support the java.io.Serializable interface can be written to streams.
Constructor
Important Methods
Method Description
1) public final void writeObject(Object obj) throws writes the specified object to the
IOException {} ObjectOutputStream.
2) public void flush() throws IOException {} flushes the current output stream.
3) public void close() throws IOException {} closes the current output stream.
ObjectInputStream class
Constructor
Important Methods
Method Description
1) public final Object readObject() throws reads an object from the input stream.
IOException, ClassNotFoundException{}
In this example, we are going to serialize the object of Student class. The writeObject() method of
ObjectOutputStream class provides the functionality to serialize the object. We are saving the state of the
object in the file named f.txt.
1. import java.io.*;
2. class Persist{
3. public static void main(String args[]){
4. try{
5. //Creating the object
6. Student s1 =new Student(211,"ravi");
7. //Creating stream and writing the object
8. FileOutputStream fout=new FileOutputStream("f.txt");
9. ObjectOutputStream out=new ObjectOutputStream(fout);
10. out.writeObject(s1);
11. out.flush();
12. //closing the stream
13. out.close();
14. System.out.println("success");
15. }catch(Exception e){System.out.println(e);}
16. }
17. }
success
Example of Java Deserialization
Deserialization is the process of reconstructing the object from the serialized state. It is the reverse operation
of serialization. Let's see an example where we are reading the data from a deserialized object.
1. import java.io.*;
2. class Depersist{
3. public static void main(String args[]){
4. try{
5. //Creating stream to read the object
6. ObjectInputStream in=new ObjectInputStream(new FileInputStream("f.txt"));
7. Student s=(Student)in.readObject();
8. //printing the data of the serialized object
9. System.out.println(s.id+" "+s.name);
10. //closing the stream
11. in.close();
12. }catch(Exception e){System.out.println(e);}
13. }
14. }
211 Gabber
If a class implements serializable then all its sub classes will also be serializable. Let's see the example given
below:
1. import java.io.Serializable;
2. class Person implements Serializable{
3. int id;
4. String name;
5. Person(int id, String name) {
6. this.id = id;
7. this.name = name;
8. }
9. }
1. class Student extends Person{
2. String course;
3. int fee;
4. public Student(int id, String name, String course, int fee) {
5. super(id,name);
6. this.course=course;
7. this.fee=fee;
8. }
9. }
Now you can serialize the Student class object that extends the Person class which is Serializable. Parent
class properties are inherited to subclasses so if parent class is Serializable, subclass would also be.
If a class has a reference to another class, all the references must be Serializable otherwise serialization
process will not be performed. In such case, NotSerializableException is thrown at runtime.
1. class Address{
2. String addressLine,city,state;
3. public Address(String addressLine, String city, String state) {
4. this.addressLine=addressLine;
5. this.city=city;
6. this.state=state;
7. }
8. }
1. import java.io.Serializable;
2. public class Student implements Serializable{
3. int id;
4. String name;
5. Address address;//HAS-A
6. public Student(int id, String name) {
7. this.id = id;
8. this.name = name;
9. }
10. }
Since Address is not Serializable, you can not serialize the instance of Student class.
If there is any static data member in a class, it will not be serialized because static is the part of class not
object.
Rule: In case of array or collection, all the objects of array or collection must be serializable. If any object is
not serialiizable, serialization will be failed.
Externalizable in java
The Externalizable interface provides the facility of writing the state of an object into a byte stream in
compress format. It is not a marker interface.
If you don't want to serialize any data member of a class, you can mark it as transient.
Now, id will not be serialized, so when you deserialize the object after serialization, you will not get the
value of id. It will return default value always. In such case, it will return 0 because the data type of id is an
integer.
SerialVersionUID
The serialization process at runtime associates an id with each Serializable class which is known as
SerialVersionUID. It is used to verify the sender and receiver of the serialized object. The sender and
receiver must be the same. To verify it, SerialVersionUID is used. The sender and receiver must have the
same SerialVersionUID, otherwise, InvalidClassException will be thrown when you deserialize the object.
We can also declare our own SerialVersionUID in the Serializable class. To do so, you need to create a field
SerialVersionUID and assign a value to it. It must be of the long type with static and final. It is suggested to
explicitly declare the serialVersionUID field in the class and have it private also. For example:
1. private static final long serialVersionUID=1L;
1. import java.io.Serializable;
2. class Employee implements Serializable{
3. private static final long serialVersionUID=1L;
4. int id;
5. String name;
6. public Student(int id, String name) {
7. this.id = id;
8. this.name = name;
9. }
10. }
Java Enumerations
Enumerations was added to Java language in JDK5. Enumeration means a list of named constant. In Java,
enumeration defines a class type. An Enumeration can have constructors, methods and instance variables. It
is created using enum keyword. Each enumeration constant is public, static and final by default. Even
though enumeration defines a class type and have constructors, you do not instantiate an enum using new.
Enumeration variables are used and declared in much a same way as you do a primitive variable.
1. An enumeration can be defined simply by creating a list of enum variable. Let us take an example for
list of Subject variable, with different subjects in the list.
//Enumeration defined
enum Subject
{
Java, Cpp, C, Dbms
}
1. Identifiers Java, Cpp, C and Dbms are called enumeration constants. These are public, static and
final by default.
2. Variables of Enumeration can be defined directly without any new keyword.
Subject sub;
3. Variables of Enumeration type can have only enumeration constants as value. We define an enum
variable as enum_variable = enum_type.enum_constant;
sub = Subject.Java;
4. Two enumeration constants can be compared for equality by using the = = relational operator.
Example:
if(sub == Subject.Java) {
...
}
Example of Enumeration
enum WeekDays
{ sun, mon, tues, wed, thurs, fri, sat }
class Test
{
public static void main(String args[])
{
WeekDays wk; //wk is an enumeration variable of type WeekDays
wk = WeekDays.sun; //wk can be assigned only the constants defined under enum type Weekdays
System.out.println("Today is "+wk);
}
}
Today is sun
I AM paninos
Values() and ValueOf() method
All the enumerations predefined methods values() and valueOf(). values() method returns an array of enum-
type containing all the enumeration constants in it. Its general form is,
public static enum-type[ ] values()
valueOf() method is used to return the enumeration constant whose value is equal to the string passed in as
argument while calling this method. It's general form is,
public static enum-type valueOf (String str)
enum Restaurants {
dominos, kfc, pizzahut, paninos, burgerking
}
class Test {
public static void main(String args[])
{
Restaurants r;
System.out.println("All constants of enum type Restaurants are:");
Restaurants rArray[] = Restaurants.values(); //returns an array of constants of type Restaurants
for(Restaurants a : rArray) //using foreach loop
System.out.println(a);
r = Restaurants.valueOf("dominos");
System.out.println("I AM " + r);
}
}
1. Enumerations are of class type, and have all the capabilities that a Java class has.
2. Enumerations can have Constructors, instance Variables, methods and can even implement
Interfaces.
3. Enumerations are not instantiated using new keyword.
4. All Enumerations by default inherit java.lang.Enum class.
class EnumDemo
{
public static void main( String args[] )
{
Student S;
System.out.println("Age of Viraaj is " +Student.Viraaj.getage()+ "years");
}
}
The automatic conversion of primitive data types into its equivalent Wrapper type is known as boxing and
opposite operation is known as unboxing. This is the new feature of Java5. So java programmer doesn't need
to write the conversion code.
No need of conversion between primitives and Wrappers manually so less coding is required.
1.
2. class BoxingExample1{
3. public static void main(String args[]){
4. int a=50;
5. Integer a2=new Integer(a);//Boxing
6.
7. Integer a3=5;//Boxing
8.
9. System.out.println(a2+" "+a3);
10. }
11. }
12.
Output:50 5
The automatic conversion of wrapper class type into corresponding primitive type, is known as Unboxing.
Let's see the example of unboxing:
1.
2. class UnboxingExample1{
3. public static void main(String args[]){
4. Integer i=new Integer(50);
5. int a=i;
6.
7. System.out.println(a);
8. }
9. }
Output:
50
Autoboxing and Unboxing with comparison operators
Autoboxing can be performed with comparison operators. Let's see the example of boxing with comparison
operator:
1.
2. class UnboxingExample2{
3. public static void main(String args[]){
4. Integer i=new Integer(50);
5.
6. if(i<100){ //unboxing internally
7. System.out.println(i);
8. }
9. }
10. }
11.
Output:50
In method overloading, boxing and unboxing can be performed. There are some rules for method overloading
with boxing:
o Widening beats boxing
o Widening beats varargs
o Boxing beats varargs
1.
2. class Boxing1{
3. static void m(int i){System.out.println("int");}
4. static void m(Integer i){System.out.println("Integer");}
5.
6. public static void main(String args[]){
7. short s=30;
8. m(s);
9. }
10. }
11.
Output:int
1.
2. class Boxing2{
3. static void m(int i, int i2){System.out.println("int int");}
4. static void m(Integer... i){System.out.println("Integer...");}
5.
6. public static void main(String args[]){
7. short s1=30,s2=40;
8. m(s1,s2);
9. }
10. }
Output:int int
1.
2. class Boxing3{
3. static void m(Integer i){System.out.println("Integer");}
4. static void m(Integer... i){System.out.println("Integer...");}
5.
6. public static void main(String args[]){
7. int a=30;
8. m(a);
9. }
10. }
Output:Integer
1.
2. class Boxing4{
3. static void m(Long l){System.out.println("Long");}
4.
5. public static void main(String args[]){
6. int a=30;
7. m(a);
8. }
9. }
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