Java Generic Methods Examples

Introduction

Generic methods in Java allow you to define methods with type parameters, enabling them to operate on objects of various types while providing compile-time type safety. Generic methods can be defined in both generic and non-generic classes and interfaces. They provide a powerful way to write flexible and reusable code.

Table of Contents

  1. What are Generic Methods?
  2. Syntax of Generic Methods
  3. Benefits of Using Generic Methods
  4. Example: Simple Generic Method
  5. Bounded Type Parameters
  6. Example: Bounded Generic Method
  7. Type Inference in Generic Methods
  8. Restrictions on Generic Methods
  9. Example Programs
  10. Conclusion

1. What are Generic Methods?

Generic methods introduce their own type parameters, which are independent of any type parameters defined by the class. They can be used to define methods that operate on different types while ensuring type safety at compile time.

2. Syntax of Generic Methods

A generic method is defined with a type parameter, which appears before the method's return type and can be used within the method's body.

Syntax:

public <T> void methodName(T param) {
    // method body
}

3. Benefits of Using Generic Methods

  • Type Safety: Generic methods ensure that the type of objects passed to and returned by the method is consistent.
  • Reusability: A single generic method can be used with different types, reducing code duplication.
  • Flexibility: Generic methods can be used in both generic and non-generic classes.

4. Example: Simple Generic Method

Example:

public class GenericMethodExample {
    // Generic method to print any type of array
    public static <T> void printArray(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 = {"Hello", "Generics", "in", "Java"};

        printArray(intArray);  // Output: 1 2 3 4 5
        printArray(strArray);  // Output: Hello Generics in Java
    }
}

Output:

1 2 3 4 5
Hello Generics in Java

5. Bounded Type Parameters

You can restrict the types that can be used as type arguments by using bounded type parameters. Bounded type parameters allow you to specify that a type must be a subclass (or implementor) of a specific class (or interface).

Syntax:

public <T extends SuperClass> void methodName(T param) {
    // method body
}

6. Example: Bounded Generic Method

Example:

public class BoundedGenericMethodExample {
    // Generic method with a bounded type parameter
    public static <T extends Number> void printDoubleValue(T value) {
        System.out.println(value.doubleValue());
    }

    public static void main(String[] args) {
        printDoubleValue(10);       // Integer
        printDoubleValue(3.14);     // Double
        printDoubleValue(5.67f);    // Float
    }
}

Output:

10.0
3.14
5.670000076293945

Explanation:

  • The printDoubleValue method accepts any type that extends Number.
  • It prints the double value of the passed argument.

7. Type Inference in Generic Methods

Java's compiler can infer the type parameters of a generic method from the context in which it is called. This feature is known as type inference.

Example:

public class TypeInferenceExample {
    public static <T> void display(T param) {
        System.out.println("Parameter: " + param);
    }

    public static void main(String[] args) {
        display(123);            // Compiler infers T as Integer
        display("Hello World");  // Compiler infers T as String
    }
}

Output:

Parameter: 123
Parameter: Hello World

8. Restrictions on Generic Methods

There are several restrictions on generic methods in Java:

  1. Cannot Instantiate Generic Types with Primitive Types:

    // This is not allowed
    public static <T> void genericMethod(T param) {
        T[] array = new T[10];  // Compile-time error
    }
    
  2. Cannot Create Instances of Type Parameters:

    public static <T> void genericMethod(T param) {
        // T obj = new T();  // Compile-time error
    }
    
  3. Cannot Declare Static Fields Whose Types are Type Parameters:

    class GenericClass<T> {
        // This is not allowed
        // static T obj;
    }
    
  4. Cannot Use Casts or instanceof with Parameterized Types:

    public static <T> void genericMethod(Object obj) {
        // if (obj instanceof T) { }  // Compile-time error
    }
    
  5. Cannot Create Arrays of Parameterized Types:

    // This is not allowed
    public static <T> void genericMethod(T param) {
        // T[] array = new T[10];  // Compile-time error
    }
    

9. Example Programs

Example 1: Generic Method for Swapping Elements

Example:

public class SwapElementsExample {
    // Generic method to swap two elements in an array
    public static <T> void swap(T[] array, int index1, int index2) {
        T temp = array[index1];
        array[index1] = array[index2];
        array[index2] = temp;
    }

    public static void main(String[] args) {
        Integer[] intArray = {1, 2, 3, 4, 5};
        swap(intArray, 0, 4);
        for (int i : intArray) {
            System.out.print(i + " ");
        }
        System.out.println();

        String[] strArray = {"A", "B", "C", "D"};
        swap(strArray, 1, 3);
        for (String s : strArray) {
            System.out.print(s + " ");
        }
    }
}

Output:

5 2 3 4 1
A D C B

Example 2: Generic Method for Finding Maximum Element

Example:

import java.util.Arrays;
import java.util.List;

public class MaxElementExample {
    // Generic method to find the maximum element in a list
    public static <T extends Comparable<T>> T findMax(List<T> list) {
        T max = list.get(0);
        for (T element : list) {
            if (element.compareTo(max) > 0) {
                max = element;
            }
        }
        return max;
    }

    public static void main(String[] args) {
        List<Integer> intList = Arrays.asList(1, 2, 3, 4, 5);
        System.out.println("Max Integer: " + findMax(intList));

        List<String> strList = Arrays.asList("Apple", "Orange", "Banana", "Peach");
        System.out.println("Max String: " + findMax(strList));
    }
}

Output:

Max Integer: 5
Max String: Peach

10. Conclusion

Generic methods in Java provide a powerful way to create flexible, reusable, and type-safe methods. By using type parameters, you can write methods that operate on different types while ensuring type safety at compile time. Bounded type parameters further enhance the flexibility of generic methods by allowing you to specify constraints on the types that can be used as arguments.

By understanding and utilizing generic methods, you can create more robust and maintainable Java applications.

Happy coding!

Comments