- Java Programming Basics
- Java Tutorial
- Java Overview
- Java Environment Setup
- Java Program Structure
- Java Basic Syntax
- Java First Program
- Java Constants
- Java Separators
- Java Keywords
- Java Data Types
- Java Data Types
- Java Integers
- Java Floating Point
- Java Characters
- Java Booleans
- Java Numbers
- Java Programming Variables
- Java Variables
- Java Variable Types
- Java Variable Scope
- Java Type Conversion
- Java Type Casting
- Java Auto Type Promotion
- Java Type Promotion Rules
- Java Programming Arrays
- Java Arrays
- Java One Dimensional Array
- Java Multidimensional Array
- Java Programming Operators
- Java Operators
- Java Arithmetic Operators
- Java Increment Decrement
- Java Bitwise Operators
- Java Left Shift
- Java Right Shift
- Java Relational Operators
- Java Boolean Logical Operators
- Java Ternary(?) Operator
- Java Operator Precedence
- Java Control Statements
- Java Decision Making
- Java if if-else if-else-if
- Java switch Statement
- Java Loops
- Java while Loop
- Java do-while Loop
- Java for Loop
- Java for-each Loop
- Java Nested Loops
- Java break Statement
- Java continue Statement
- Java Class Object Method
- Java Classes and Objects
- Java Class
- Java Object
- Java new Operator
- Java Methods
- Java Constructors
- Java this Keyword
- Java Stack
- Java Overloading Recursion
- Java Method Overloading
- Java Constructor Overloading
- Java Object as Parameter
- Java Call by Value Reference
- Java Returning Objects
- Java Recursion
- Java Modifier Types
- Java Encapsulate Poly String
- Java Encapsulation
- Java Polymorphism
- Java Nested Inner Class
- Java Strings
- Java Command Line Arguments
- Java Variable Length Arguments
- Java Inheritance Abstraction
- Java Inheritance
- Java super Superclass
- Java Multilevel Hierarchy
- Java Method Overriding
- Java Abstraction
- Java Packages Interfaces
- Java Packages
- Java Access Protection
- Java Import Statement
- Java Interfaces
- Java Programming Exceptions
- Java Exception Handling
- Java try catch
- Java throw throws
- Java finally Block
- Java Built In Exceptions
- Java Exception Subclasses
- Java Chained Exceptions
- Java Multithreading
- Java Multithreading
- Java Thread Model
- Java Main Thread
- Java Create Thread
- Java Thread Priorities
- Java Synchronization
- Java Inter Thread Communication
- Java Suspend Resume Stop Thread
- Java Get Thread State
- Java Enum Autobox Annotation
- Java Enumerations
- Java Type Wrappers
- Java Autoboxing
- Java Annotation
- Java Marker Annotations
- Java Single Member Annotation
- Java Built In Annotations
- Java Type Annotations
- Java Repeating Annotations
- Java Data File Handling
- Java Files I/O
- Java Streams
- Java Read Console Input
- Java Write Console Output
- Java PrintWriter Class
- Java Read Write Files
- Java Automatically Close File
- Java Programming Advance
- Java Date and Time
- Java Regular Expressions
- Java Collections Framework
- Java Generics
- Java Data Structures
- Java Network Programming
- Java Serialization
- Java Send Email
- Java Applet Basics
- Java Documentation
- Java Programming Examples
- Java Programming Examples
Java Generics
In Java, the term generics means parameterized types. Parameterized types are important because they enable you to create classes, interfaces, and methods in which the data types upon which they operate is specified as a parameter.
Using generics, it is possible to create a single class, for instance, that automatically works with the different types of data. A class, interface, or method which operates on a parameterized type is called generic, as in generic class or generic method.
Java Generics Example
Following is a simple example of a generic class. This program defines the two classes. The first is the generic class Genrc, and the second is GenrcDemo, which uses Genrc.
/* Java Program Example - Java Generics * This is a simple generic class * Here, T is a type parameter which will be * replaced by a real type when an object of * the type Genrc is created */ class Genrc<T> { T obj; // declare an object of type T /* pass the constructor a reference to an * object of the type T */ Genrc(T o) { obj = o; } /* return obj */ T getobj() { return obj; } /* show type of T */ void showType() { System.out.println("Type of T is " + obj.getClass().getName()); } } /* illustrates the generic class */ class GenrcDemo { public static void main(String args[]) { /* create a Genrc reference for Integers */ Genrc<Integer> iObj; /* create a Genrc<Integer> object and assign its * reference to iObj. * Notice here that the use of autoboxing to encapsulate the * value 88 within an Integer object */ iObj = new Genrc<Integer>(88); /* show the type of data used by iObj */ iObj.showType(); /* get the value in iObj. * Notice that no cast is needed */ int v = iObj.getobj(); System.out.println("value : " + v); System.out.println(); /* create a Genrc object for Strings */ Genrc<String> strObj = new Genrc<String> ("Generics Test"); /* show the type of data used by strObj */ strObj.showType(); /* get the value of strObj. * Again, notice that no cast is needed */ String str = strObj.getobj(); System.out.println("value : " + str); } }
The output produced by the above Java program is shown here:
Now let's examine this program carefully in detail.
First, notice how Genrc is declared by the following line :
class Genrc<T> {
Here, T is the name of type parameter which is used as a placeholder for the actual type that will be passed to the Genrc whenever an object is created. Thus, T is used within Genrc when the type parameter is needed. Notice here that T is contained inside < >. This syntax can be generalized. When a type parameter is being declared, it is specified within angle brackets. Because the Genrc uses type parameter, Genrc is a generic class, which is also called a parameterized type.
Next, T is used to declare an object called obj, as shown below :
T obj; // declare an object of type T
As explained, T is a placeholder for the actual type, will be specified whenever Genrc object is created. Therefore, obj will be an object of the type passed to T. For instance, if type String is passed to T, then in that instance, obj will be of the type String.
Now consider Genrc's constructor:
Genrc(T o) { obj = o; }
Notice that its parameter, o, is of the type T. This means that the actual type of o is determined by the type passed to T when Genrc object is created. Also, as both parameter, o and member variable obj are of the type T, they both will be of the like actual type when Genrc object is created.
The type parameter T can also be used to specify the return type of a method, as in the case with the getobj() method, shown below :
T getobj() { return obj; }
Because obj is also of the type T, its type is compatible with the return type that specified by the method named getobj().
The showType() method displays the type of T by calling the getName() on the Class object returned by the call to the getClass() on obj. The getClass() method is defined by Object and is thus a member of class types. It returns a Class object that corresponds to the type of the class of the object on which it is called. Class defines the getName() method, which returns a string representation of the class name.
The class GenrcDemo illustrates the generic Genrc class. It first creates a version of Genrc for integers, as shown below :
Genrc<Integer> iObj;
Now let's look closely at this declaration. First, notice that the type Integer is specified within the angle brackets after Genrc. In this case, Integer is a type argument that is passed to Genrc's type parameter, T. This effectively creates Genrc variant in which all the references to the T are translated into references to Integer. Thus, for this declaration, obj is of type Integer, and the return type of the getobj() is of type Integer.
Before moving on, it's necessary to state that the Java compiler doesn't actually create different versions of Genrc, or of any other generic class. Although it is helpful to think in these terms, it is not what actually happens. Instead, the compiler removes all the generic type information, replacing the necessary casts, to make your code behave as if a specific version of Genrc were created. Thus, there is truly only one Genrc version that actually exists in your program. The process of removing the generic type information is called erasure
The next line assigns to iObj, a reference to an instance of Integer version of Genrc class:
iObj = new Genrc<Integer>(88);
Notice here that when the Genrc constructor is called, the type argument Integer is specified also. It is because the type of object (iObj in this case) to which the reference is being assigned is of Genrc<Integer> type. Thus, the reference returned by the new operator/keyword must also be of Genrc<Integer> type. If it is not, a compile-time error will result. For example, the following assignment will cause a compile-time error :
iObj = new Genrc<Double>(88.0); // Error!
Because iObj is of type Genrc<Integer>, it can not be used to refer to an object of Genrc<Double>. This type checking is one of the main benefits of generics as it ensures type safety.
As the comments in the program state, the assignment :
iObj = new Genrc<Integer>(88);
makes the use of autoboxing to encapsulate the value 88, which is an int, into an Integer. This works because Genrc<Integer> creates a constructor that takes an Integer argument. Because an Integer is expected, Java will automatically box 88 inside one. Of course, the assignment could also have been written explicitly, like:
iObj = new Genrc<Integer>(new Integer(88));
However, there would be no benefit to using this version.
The program then display the type of obj within iObj, which is Integer.
Next, the program obtains the value of obj by the use of the following line:
int v = iObj.getobj();
Because the return type of the getobj() is T, which was replaced by Integer when iObj was declared, the return type of the getobj() is also Integer, which unboxes into int when assigned to v (that is an int). Therefore, there is no need to cast the return type of the getobj() to Integer.
Of course, it is not necessary to use the auto-unboxing feature. The preceding line could have been written like this, too:
int v = iObj.getobj().intValue(;
However, the auto-unboxing feature makes the code more compact.
Next, GenrcDemo declares an object of type Genrc<String> :
Genrc<String> strObj = new Genrc<String>("Generics Test");
Because the type argument is String, String is replaced for T inside Genrc. This creates conceptually a String version of Genrc, as the remaining lines in the program demonstrate.
« Previous Tutorial Next Tutorial »