泛型类、泛型接口、泛型方法详解!

Java泛型中的那些字母是什么意思?(E、T、K、V、S)

泛型类、泛型接口、泛型方法详解!

当定义类、接口或方法时,可以使用类型参数(Type Parameters)来表示未知的类型,从而使代码更加通用和灵活。下面分别给出类、接口和方法的例子:

1. 类中使用类型参数:

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;
    }
}

在这个例子中,Box 类使用类型参数 T 来表示未知的类型,可以在创建对象时指定具体的类型。例如,可以创建一个 Box 对象来存储整数类型的值:

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

也可以创建一个 Box 对象来存储字符串类型的值:

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

2. 接口中使用类型参数:

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

在这个例子中,List 接口使用类型参数 T 来表示未知的类型,可以在实现接口时指定具体的类型。例如,可以实现一个整数列表:

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);
    }
}

也可以实现一个字符串列表:

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. 方法中使用类型参数:

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;
}

在这个例子中,findMax 方法使用类型参数 T 来表示未知的类型,可以在调用方法时传入具体的类型参数。例如,可以调用该方法来查找整数数组中的最大值:

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

也可以调用该方法来查找字符串数组中的最大值:

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

通过使用类型参数,类、接口和方法可以在定义时表示未知的类型,从而使代码更加通用和灵活,适应不同类型的数据。这在框架中的运用非常广泛,下面举几个实际的例子:

实际的例子

1. Java集合框架中的泛型:

Java集合框架中的诸多接口和类都使用了泛型来表示集合中元素的类型,例如 ArrayListLinkedListHashMap 等。通过使用泛型,这些集合类可以在运行时支持不同类型的元素,并在编译时提供类型安全的检查,从而避免了在运行时发生类型转换错误的可能性。

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. Spring框架中的泛型:

Spring框架是一个用于构建Java应用程序的强大框架,其中广泛使用了泛型来实现灵活和可扩展的功能。例如,在Spring中,泛型可以用于依赖注入、数据访问、事务管理等场景。

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

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

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

    // ...
}

在这个例子中,CrudRepository 接口使用了两个泛型参数 TID,分别表示实体类型和ID类型。通过使用泛型,可以在实现 CrudRepository 接口时指定具体的实体类型和ID类型,从而实现对不同实体和ID类型的支持。

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

在这个例子中,UserRepositoryImpl 类实现了 CrudRepository 接口,并指定了实体类型为 User,ID类型为 Long,从而实现了对 User 实体的数据访问操作。

通过使用泛型,可以在框架中实现通用、灵活和可扩展的功能,从而提高代码的复用性和可维护性。

3. 自定义框架中的泛型:

在自定义的框架或库中,也可以使用泛型来实现通用和灵活的功能。例如,假设我们正在构建一个通用的数据访问层框架,可以通过泛型来支持不同实体类型的数据访问操作。

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

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

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

    // ...
}

在这个例子中,我们定义了一个通用的 CrudRepository 接口,其中的泛型参数 T 表示实体类型,ID 表示ID类型。通过使用泛型,我们可以在实现 CrudRepository 接口时指定具体的实体类型和ID类型,从而实现对不同实体和ID类型的数据访问操作。

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

在这个例子中,UserRepositoryImpl 类实现了 CrudRepository 接口,并指定了实体类型为 User,ID类型为 Long,从而实现了对 User 实体的数据访问操作。

通过在自定义框架中使用泛型,可以实现通用的功能,并且允许用户在使用框架时灵活地指定不同类型的参数,从而满足不同业务需求。这样的设计可以提高框架的复用性和灵活性,同时避免了类型转换错误和运行时异常的可能性。

4. 方法中的泛型:

在方法中使用泛型可以使方法更加通用,可以处理多种类型的输入参数和返回值。例如,Java中的集合框架中的许多方法都使用了泛型。

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

在这个例子中,我们定义了一个静态方法 getFirstElement,它接收一个泛型参数为 List<T>,并返回类型为 T。这意味着这个方法可以处理任何类型的 List,例如 List<Integer>List<String> 等。

使用泛型的方法可以在调用时根据实际的参数类型进行类型推断,从而避免了类型转换错误,并且可以提供更好的类型安全性和代码重用性。

在Spring框架中,也广泛使用了泛型来实现通用的功能,例如在Spring的JdbcTemplate类中,使用了泛型来支持不同类型的数据库操作,从而减少了重复的代码和提高了灵活性。

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

    // ...
}

在这个例子中,queryForObject 方法使用了泛型参数 T 来表示查询结果映射的实体类型,同时接收一个 RowMapper<T> 参数来进行结果映射。这样,可以通过传入不同的 RowMapper 实现类来实现对不同实体类型的查询操作,从而提供了更好的灵活性和通用性。

总结:

在Java中,泛型是一种强大的特性,可以用于类、接口、方法等地方,用于实现通用、灵活和类型安全的功能。在框架中的运用也非常广泛,可以提供通用的功能、减少重复的代码、提高灵活性和类型安全性,从而提升代码质量和开发效率。

猜你喜欢

转载自blog.csdn.net/qq_45796667/article/details/130347416