Detailed explanation of generic classes, generic interfaces, and generic methods!

What do those letters in Java generics mean? (E, T, K, V, S)

Detailed explanation of generic classes, generic interfaces, and generic methods!

When defining a class, interface, or method, you can use type parameters (Type Parameters) to represent unknown types, making your code more general and flexible. Examples of classes, interfaces, and methods are given below:

1. Use type parameters in the class:

public class Box<T> {
    
    
    private T value;

    public Box(T value) {
    
    
        this.value = value;
    }

    public T getValue() {
    
    
        return value;
    }

    public void setValue(T value) {
    
    
        this.value = value;
    }
}

In this example, Boxthe class uses a type parameter Tto represent the unknown type, and the concrete type can be specified when the object is created. For example, a Boxobject can be created to store values ​​of integer type:

Box<Integer> integerBox = new Box<>(10);
Integer value = integerBox.getValue(); // 获取整数值

It is also possible to create a Boxobject to store values ​​of type string:

Box<String> stringBox = new Box<>("Hello");
String value = stringBox.getValue(); // 获取字符串值

2. Use type parameters in the interface:

public interface List<T> {
    
    
    void add(T element);
    T get(int index);
}

In this example, Listthe interface uses type parameters Tto represent unknown types, and concrete types can be specified when implementing the interface. For example, a list of integers can be implemented:

public class IntegerList implements List<Integer> {
    
    
    private List<Integer> elements = new ArrayList<>();

    @Override
    public void add(Integer element) {
    
    
        elements.add(element);
    }

    @Override
    public Integer get(int index) {
    
    
        return elements.get(index);
    }
}

A list of strings can also be implemented:

public class StringList implements List<String> {
    
    
    private List<String> elements = new ArrayList<>();

    @Override
    public void add(String element) {
    
    
        elements.add(element);
    }

    @Override
    public String get(int index) {
    
    
        return elements.get(index);
    }
}

3. Use the type parameter in the method:

public <T> T findMax(T[] array) {
    
    
    if (array == null || array.length == 0) {
    
    
        return null;
    }
    T max = array[0];
    for (int i = 1; i < array.length; i++) {
    
    
        if (array[i].compareTo(max) > 0) {
    
    
            max = array[i];
        }
    }
    return max;
}

In this example, findMaxthe method uses type parameters Tto represent unknown types, and specific type parameters can be passed in when calling the method. For example, this method can be called to find the largest value in an array of integers:

Integer[] numbers = {
    
    1, 5, 3, 9, 2};
Integer max = findMax(numbers); // 获取整数数组中的最大值

This method can also be called to find the largest value in an array of strings:

String[] strings = {
    
    "apple", "banana", "cherry", "date"};
String max = findMax(strings); // 获取字符串数组中的最大值

By using type parameters, classes, interfaces, and methods can represent unknown types at definition time, making code more general and flexible to accommodate different types of data. This is widely used in the framework, here are a few practical examples:

practical example

1. Generics in the Java collection framework:

Many interfaces and classes in the Java collection framework use generics to represent the types of elements in the collection, for example, , ArrayList, LinkedListand HashMapso on. By using generics, these collection classes can support different types of elements at runtime and provide type safety checks at compile time, thus avoiding the possibility of type conversion errors at runtime.

ArrayList<Integer> numbers = new ArrayList<Integer>(); // 创建一个整数列表
numbers.add(1);
numbers.add(2);
numbers.add(3);
int firstNumber = numbers.get(0); // 获取列表中的第一个整数
ArrayList<String> names = new ArrayList<String>(); // 创建一个字符串列表
names.add("Alice");
names.add("Bob");
names.add("Charlie");
String firstName = names.get(0); // 获取列表中的第一个字符串

2. Generics in the Spring Framework:

The Spring Framework is a powerful framework for building Java applications in which generics are used extensively to achieve flexible and extensible functionality. For example, in Spring, generics can be used in scenarios such as dependency injection, data access, and transaction management.

public interface CrudRepository<T, ID extends Serializable> {
    
    
    T save(T entity); // 保存实体

    T findById(ID id); // 根据ID查询实体

    void delete(T entity); // 删除实体

    // ...
}

In this example, CrudRepositorythe interface uses two generic parameters Tand ID, representing entity type and ID type respectively. By using generics, CrudRepositoryspecific entity types and ID types can be specified when implementing the interface, thereby realizing support for different entity and ID types.

public class UserRepositoryImpl implements CrudRepository<User, Long> {
    
    
    // 实现User实体的数据访问操作
    // ...
}

In this example, UserRepositoryImplthe class implements CrudRepositorythe interface, and specifies the entity type as User, and the ID type as Long, thus realizing Userthe data access operation on the entity.

By using generics, general, flexible and extensible functions can be implemented in the framework, thereby improving code reusability and maintainability.

3. Generics in the custom framework:

In a custom framework or library, generics can also be used to achieve general and flexible functions. For example, suppose we are building a general data access layer framework that can support data access operations of different entity types through generics.

public interface CrudRepository<T, ID> {
    
    
    T save(T entity); // 保存实体

    T findById(ID id); // 根据ID查询实体

    void delete(T entity); // 删除实体

    // ...
}

In this example, we define a generic CrudRepositoryinterface, where the generic parameter Trepresents the entity type and IDrepresents the ID type. By using generics, we can CrudRepositoryspecify specific entity types and ID types when implementing the interface, thereby realizing data access operations on different entities and ID types.

public class UserRepositoryImpl implements CrudRepository<User, Long> {
    
    
    // 实现User实体的数据访问操作
    // ...
}

In this example, UserRepositoryImplthe class implements CrudRepositorythe interface, and specifies the entity type as User, and the ID type as Long, thus realizing Userthe data access operation on the entity.

By using generics in a custom framework, common functions can be realized, and users can flexibly specify different types of parameters when using the framework, so as to meet different business needs. Such a design can improve the reusability and flexibility of the framework, while avoiding the possibility of type conversion errors and runtime exceptions.

4. Generics in methods:

Using generics in a method can make the method more general and can handle multiple types of input parameters and return values. For example, many methods in the collections framework in Java use generics.

public class CollectionUtils {
    
    
    public static <T> T getFirstElement(List<T> list) {
    
    
        if (list != null && !list.isEmpty()) {
    
    
            return list.get(0);
        }
        return null;
    }
}

In this example, we define a static method getFirstElementthat takes a generic parameter of type List<T>, and returns type of T. This means that this method can handle any type List, such as List<Integer>, List<String>etc.

A method using generics can perform type inference based on the actual parameter type when calling, thereby avoiding type conversion errors, and can provide better type safety and code reuse.

In the Spring framework, generics are also widely used to achieve common functions. For example, in Spring's JdbcTemplate class, generics are used to support different types of database operations, thereby reducing repetitive code and improving flexibility.

public class JdbcTemplate {
    
    
    public <T> T queryForObject(String sql, RowMapper<T> rowMapper) {
    
    
        // 执行SQL查询,并将结果映射到实体对象
        // ...
    }

    // ...
}

In this example, queryForObjectthe method uses a generic parameter Tto indicate the entity type of the query result mapping, and receives a RowMapper<T>parameter for the result mapping. In this way, query operations on different RowMapperentity types can be realized by passing in different implementation classes, thus providing better flexibility and versatility.

Summarize:

In Java, generics are a powerful feature that can be used in classes, interfaces, methods, etc. to achieve general, flexible, and type-safe functions. It is also widely used in the framework, which can provide common functions, reduce duplication of code, improve flexibility and type safety, thereby improving code quality and development efficiency.

Guess you like

Origin blog.csdn.net/qq_45796667/article/details/130347416