In-depth analysis of Java generics

Generics in Java are a powerful programming feature that allow us to write more general and type-safe code. This blog will delve into various aspects of Java generics, including generic classes, generic methods, generic interfaces, and generic wildcards.

1. Generic class

First, let's look at a simple example of a generic class. In the following code, we define a GenericClassgeneric class named, which has a generic parameter Tand contains a constructor method, a method for getting data, and a method for setting data.

public class GenericClass<T> {
    private T data;

    // 构造方法
    public GenericClass(T data) {
        this.data = data;
    }

    // 获取数据的方法
    public T getData() {
        return data;
    }

    // 设置数据的方法
    public void setData(T data) {
        this.data = data;
    }
}

With this generic class we can create instances with different types, for example:

// 使用泛型类,指定类型为String
GenericClass<String> stringGeneric = new GenericClass<>("Hello, Generics!");

// 使用泛型类,指定类型为Integer
GenericClass<Integer> intGeneric = new GenericClass<>(42);

2. Generic methods

Generics are not limited to classes but can also be used for methods. The following code shows a class that contains generic methods MyGeneric, including a method that prints data from the generic class.

public class MyGeneric {

    // 泛型方法
    public <T> void printData(GenericClass<T> generic) {
        System.out.println(generic.getData());
    }

    // 其他泛型方法和示例省略...
}

Through this generic method, we can print different types of data in different contexts, making the code more flexible.

3. Generic interface

Java also supports generic interfaces, which allows us to use generic parameters when defining interfaces. The following code shows a generic interface GenericInterfaceand its implementation class StringContainer.

public interface GenericInterface<T> {
    T getData();

    void setData(T data);
}

public class StringContainer implements GenericInterface<String> {
    private String data;

    @Override
    public String getData() {
        return data;
    }

    @Override
    public void setData(String data) {
        this.data = data;
    }
}

Generic interfaces provide a flexible way to define interfaces that can handle multiple types of data and make implementation classes more versatile.

4. Generic wildcards

Java's generics also support wildcards, where <?>unknown types are represented. The use of wildcards allows us to write code that works with multiple generic types. The following code shows an approach using generic wildcards.

public class MyGeneric {

    // 使用泛型通配符的方法,接受任意泛型类型的参数
    public static void printWildcardData(GenericClass<?> generic) {
        System.out.println("Wildcard data: " + generic.getData());
    }

    // 其他代码和示例省略...
}

Through this method, we can pass parameters of any generic type, which improves the flexibility of the code.

5. Generic record class

Types introduced in Java 14 (? Currently using Java 17) recordalso support generics. The following code shows a generic record class Pair.

public record Pair<T>(T first, T second) {
    // 这里没有额外的方法,因为 record 自动生成了构造方法、getter 方法等
}

recordClasses provide a concise way to define immutable classes and handle different types of data through generic support.

6. Complete code

Insert image description here

package com.lfsun.generic;

// 定义一个泛型类
public class GenericClass<T> {
    private T data;

    // 构造方法
    public GenericClass(T data) {
        this.data = data;
    }

    // 获取数据的方法
    public T getData() {
        return data;
    }

    // 设置数据的方法
    public void setData(T data) {
        this.data = data;
    }
}

package com.lfsun.generic;

// 定义一个泛型接口
public interface GenericInterface<T> {
    T getData();

    void setData(T data);
}

package com.lfsun.generic;

// 定义一个泛型 record 类
public record Pair<T>(T first, T second) {
    // 这里没有额外的方法,因为 record 自动生成了构造方法、getter 方法等
}

package com.lfsun.generic;

// 实现泛型接口的类
public class StringContainer implements GenericInterface<String> {
    private String data;

    @Override
    public String getData() {
        return data;
    }

    @Override
    public void setData(String data) {
        this.data = data;
    }
}

package com.lfsun.generic;

// 定义一个包含泛型方法的类
public class MyGeneric {

    // 泛型方法
    public <T> void printData(GenericClass<T> generic) {
        System.out.println(generic.getData());
    }

    // 泛型方法示例,接受任意类型的数组并打印
    public static <E> void printArray(E[] array) {
        for (E element : array) {
            System.out.print(element + " ");
        }
        System.out.println();
    }

    // 使用泛型通配符的方法,接受任意泛型类型的参数
    public static void printWildcardData(GenericClass<?> generic) {
        System.out.println("Wildcard data: " + generic.getData());
    }

    public static void main(String[] args) {
        // 使用泛型类,指定类型为String
        GenericClass<String> stringGeneric = new GenericClass<>("Hello, Generics!");

        // 使用泛型方法,打印泛型类的数据
        MyGeneric myGeneric = new MyGeneric();
        myGeneric.printData(stringGeneric);

        // 使用泛型接口,实现类存储String类型数据
        StringContainer stringContainer = new StringContainer();
        stringContainer.setData("Generic Interface Example");
        System.out.println("Data from interface: " + stringContainer.getData());

        // 使用泛型方法,打印任意类型的数组
        Integer[] intArray = {1, 2, 3, 4, 5};
        String[] stringArray = {"apple", "banana", "orange"};
        printArray(intArray);
        printArray(stringArray);

        // 使用泛型通配符的方法,打印任意泛型类型的数据
        GenericClass<Double> doubleGeneric = new GenericClass<>(3.14);
        printWildcardData(doubleGeneric);

        // 创建 Pair 实例,指定泛型类型为 String
        Pair<String> stringPair = new Pair<>("Hello", "World");

        // 访问 record 自动生成的 getter 方法
        System.out.println("First: " + stringPair.first());
        System.out.println("Second: " + stringPair.second());
    }
}

Guess you like

Origin blog.csdn.net/qq_43116031/article/details/135397115