Java Tutorial
Operators
Flow Control
String
Number and Date
Built-in Classes
Array
Class and Object
Inheritance and Polymorphism
Exception Handling
Collections, Generics and Enumerations
Reflection
Input/Output Stream
Annotation
Generics were introduced in Java 5 to provide stronger type checks at compile-time and to eliminate the need for typecasting when using collections like List, Set, and Map. Generics allow you to define classes, interfaces, and methods that can work with different data types while maintaining type safety. In this tutorial, we'll discuss the basics of generics in Java and provide examples of their usage.
A generic class is a class that can take one or more type parameters. The type parameters are specified in angle brackets (<T>
, where T
is a type parameter) following the class name.
Example:
public class Box<T> { private T content; public void setContent(T content) { this.content = content; } public T getContent() { return content; } }
In this example, we define a generic Box
class with a single type parameter T
. The setContent
and getContent
methods use the T
type parameter to set and get the content of the box.
To create an instance of a generic class, specify the actual type you want to use in place of the type parameter when declaring the object.
Example:
public class GenericClassExample { public static void main(String[] args) { Box<Integer> intBox = new Box<>(); Box<String> strBox = new Box<>(); intBox.setContent(42); strBox.setContent("Hello, Generics!"); System.out.println("Integer Box: " + intBox.getContent()); System.out.println("String Box: " + strBox.getContent()); } }
In this example, we create two instances of the Box
class with different types: Integer
and String
. The type safety provided by generics ensures that we can only store the specified type in each box.
Similar to classes, you can also define generic interfaces using type parameters.
Example:
public interface Pair<K, V> { K getKey(); V getValue(); }
In this example, we define a generic Pair
interface with two type parameters: K
for the key and V
for the value.
Generic methods allow you to create methods that can work with different types while maintaining type safety. To create a generic method, specify the type parameters before the return type of the method.
Example:
public class GenericMethodExample { public static <T> void displayArray(T[] array) { for (T element : array) { System.out.print(element + " "); } System.out.println(); } public static void main(String[] args) { Integer[] intArray = {1, 2, 3, 4, 5}; String[] strArray = {"A", "B", "C", "D", "E"}; displayArray(intArray); displayArray(strArray); } }
In this example, we define a generic displayArray
method with a single type parameter T
. The method can take an array of any type and display its elements. We then use this method to display the contents of an integer array and a string array.
In conclusion, generics in Java provide a way to create classes, interfaces, and methods that can work with different data types while maintaining type safety. Generics enable stronger type checking at compile-time, eliminate the need for typecasting, and make code more flexible and reusable.
Using generic classes and methods in Java
Generics allow you to create classes and methods that work with different types. Here's a basic example:
public class Box<T> { private T content; public void setContent(T content) { this.content = content; } public T getContent() { return content; } }
Wildcard generics in Java
Wildcards (?
) enable flexibility when dealing with unknown types. For example, a method that works with lists of any type:
public void processList(List<?> list) { for (Object item : list) { System.out.println(item); } }
Generic types and type parameters in Java
Type parameters in generic classes or methods represent the type that will be used at runtime.
public class Pair<T, U> { private T first; private U second; // Constructor and methods }
Bounded type parameters in Java Generics
Bounded type parameters restrict the types that can be used. For example, a method that works with Comparable types:
public <T extends Comparable<T>> T findMax(List<T> list) { // Implementation to find and return the maximum element }
Generic interfaces and classes in Java
You can create generic interfaces and classes to provide a common structure for multiple types.
public interface MyGenericInterface<T> { T process(T input); }
Covariant and contravariant generics in Java
Covariant generics allow more specific types to be used, while contravariant generics allow more general types.
// Covariant example List<? extends Number> numbers = new ArrayList<Integer>(); // Contravariant example List<? super Integer> integerList = new ArrayList<Number>();
Java Generics vs. raw types
Using raw types (without generics) can lead to unchecked type warnings and reduced type safety.
// Using raw type List list = new ArrayList(); list.add("Hello"); int size = (int) list.get(0); // Unchecked warning