Generics in Java provide a way to create classes, interfaces, and methods that operate on objects of various types while providing type safety. This feature is crucial for writing flexible and reusable code. In this tutorial, we will explore generic classes, generic methods, bounded type parameters, and wildcards.
Java generics allow you to define classes, interfaces, and methods that can work with objects of different types without compromising type safety. This is particularly useful in collections where you want to store a list of elements of any specific type. Generics help prevent runtime errors related to type mismatches and improve code readability and maintainability.
A generic class is defined by using angle brackets (<>) after the class name. The type parameter represents the type that will be used when an object of the class is created.
1// Box.java2public class Box<T> {3private T content;45public void setContent(T content) {6this.content = content;7};89public T getContent() {10return content;11}12}
In this example, T is a type parameter that represents the type of the object stored in the Box. You can create instances of Box for different types.
1// Main.java2public class Main {3public static void main(String[] args) {4Box<String> stringBox = new Box<>();5stringBox.setContent("Hello");6System.out.println(stringBox.getContent());78Box<Integer> integerBox = new Box<>();9integerBox.setContent(123);10System.out.println(integerBox.getContent());11}12}
Hello 123
In this example, we create a Box for String and Integer types. The type parameter T is replaced with String and Integer, respectively.
A generic method can be defined within a non-generic class or within a generic class. It allows you to specify the type of the parameters and return type at the time of method invocation.
1// Util.java2public class Util {3public static <T> void printArray(T[] array) {4for (T element : array) {5System.out.println(element);6}7}8}
In this example, printArray is a generic method that takes an array of any type and prints its elements.
1// Main.java2public class Main {3public static void main(String[] args) {4String[] strings = {"Apple", "Banana", "Cherry"};5Util.printArray(strings);67Integer[] integers = {1, 2, 3};8Util.printArray(integers);9}10}
Apple Banana Cherry 1 2 3
In this example, we use the printArray method to print arrays of String and Integer types.
Bounded type parameters allow you to restrict the types that can be used as type arguments in a generic class or method. This is done by using an extends keyword followed by a type bound.
1// Box.java2public class Box<T extends Number> {3private T content;45public void setContent(T content) {6this.content = content;7}89public T getContent() {10return content;11}12}
In this example, the type parameter T is bounded to Number, meaning it can only be a subclass of Number.
1// Main.java2public class Main {3public static void main(String[] args) {4Box<Integer> integerBox = new Box<>();5integerBox.setContent(123);6System.out.println(integerBox.getContent());78Box<Double> doubleBox = new Box<>();9doubleBox.setContent(45.67);10System.out.println(doubleBox.getContent());11}12}
123 45.67
In this example, we create a Box for Integer and Double types, which are both subclasses of Number.
Wildcards in generics allow you to write more flexible code that can work with different types without specifying the exact type. There are three types of wildcards:
?): Represents any type.<? extends T>): Represents a type that is a subclass of T.<? super T>): Represents a type that is a superclass of T.1// Util.java2public class Util {3public static void printList(List<?> list) {4for (Object element : list) {5System.out.println(element);6}7}8}
In this example, the method printList accepts a list of any type.
1// Util.java2public class Util {3public static void printNumberList(List<? extends Number> list) {4for (Number element : list) {5System.out.println(element);6}7}8}
In this example, the method printNumberList accepts a list of any type that is a subclass of Number.
1// Util.java2public class Util {3public static void addNumbers(List<? super Integer> list) {4list.add(10);5list.add(20);6}7}
In this example, the method addNumbers accepts a list of any type that is a superclass of Integer.
Let's create a practical example that combines all the concepts we have learned. We will create a generic class for a stack data structure and demonstrate its usage with different types.
1// Stack.java2public class Stack<T> {3private List<T> elements = new ArrayList<>();45public void push(T element) {6elements.add(element);7}89public T pop() {10if (elements.isEmpty()) {11throw new IllegalStateException("Stack is empty");12}13return elements.remove(elements.size() - 1);14}1516public boolean isEmpty() {17return elements.isEmpty();18}19}
1// Main.java2public class Main {3public static void main(String[] args) {4Stack<String> stringStack = new Stack<>();5stringStack.push("Hello");6stringStack.push("World");78while (!stringStack.isEmpty()) {9System.out.println(stringStack.pop());10}1112Stack<Integer> integerStack = new Stack<>();13integerStack.push(10);14integerStack.push(20);1516while (!integerStack.isEmpty()) {17System.out.println(integerStack.pop());18}19}20}
World Hello 20 10
In this example, we create a Stack for String and Integer types. The stack operations work seamlessly with different types.
| Concept | Description |
|---|---|
| Generic Classes | Define classes that can operate on objects of various types without compromising type safety. |
| Generic Methods | Define methods that can take parameters and return types of any specified type at the time of invocation. |
| Bounded Type Parameters | Restrict the types that can be used as type arguments in a generic class or method. |
| Wildcards | Allow writing more flexible code that can work with different types without specifying the exact type. |
Now that you have a solid understanding of Java generics, you are ready to explore regular expressions in Java. Regular expressions provide powerful tools for pattern matching and text manipulation. Continue your journey by learning about Java RegEx.