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

Java Generics

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.

  • Generic Classes

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.

  • Using a Generic Class

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.

  • Generic Interfaces

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

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.

  1. 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;
        }
    }
    
  2. 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);
        }
    }
    
  3. 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
    }
    
  4. 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
    }
    
  5. 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);
    }
    
  6. 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>();
    
  7. 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