深入理解Java泛型:灵活、安全、可重用的编程利器

Java泛型是一项强大的编程特性,为程序员提供了一种灵活、类型安全、可重用的编码方式。通过泛型,我们能够编写更加通用、适应多种数据类型的代码,从而提高了代码的灵活性和可维护性。在这篇博客中,我们将深入探讨Java泛型的各个方面,并通过具体的例子来展示其用法和优势。

1. 泛型类和泛型方法

在以下代码中,printArray 方法使用了泛型类型参数 T,允许我们在运行时指定具体的类型。这种方式使得我们可以编写通用的方法来处理不同类型的数组。

javascript 复制代码
public class Print {
    /**
     * 打印数组
     * @param inputArray
     * @param <T>
     */
    public static <T> void printArray(T[] inputArray) {
        for (T element : inputArray) {
            System.out.printf("%s ", element);
        }
        System.out.println();
    }

    /**
     * 打印整数数组
     * @param inputArray
     */
    public static void IntPrintArray(Integer[] inputArray) {
        for (Integer element : inputArray) {
            System.out.printf("%s ", element);
        }
        System.out.println();
    }
    /**
     * 打印字符串数组
     * @param inputArray
     */
    public static void StrPrintArray(String[] inputArray) {
        for (String element : inputArray) {
            System.out.printf("%s ", element);
        }
        System.out.println();
    }
}

然后,我们通过一个示例程序 Method01 来展示泛型方法的应用:

javascript 复制代码
/**
 * @ClassName: Method01
 * @Description: 方法1 感受泛型的好处,泛型方法
 * @Author: liu
 * @Date: 2024-03-09
 * @Version: 1.0
 **/
public class Method01 {
    public static void main(String[] args) {
        String[] stringArray = {"Hello", "World"};
        Integer[] integerArray = {1, 2, 3, 4, 5};

        System.out.println("字符串数组包含:");
        //StringPrint方法
        Print.StrPrintArray(stringArray);
        //编译失败 类型不一致
        //Print.StrPrintArray(integerArray);
        //泛型方法
        Print.printArray(stringArray);

        System.out.println("\n整数数组包含:");
        //IntegerPrint方法
        Print.IntPrintArray(integerArray);
        //编译失败 类型不一致
        //Print.IntPrintArray(stringArray);
        //泛型方法,提高代码可用性
        Print.printArray(integerArray);
        System.out.println("\n整数数组包含:");
        Object[] objectArray = {1, 2, 3, 4, 5, "Hello", "World"};
        Print.printArray(objectArray);
    }
}

在上述示例中,我们调用了 printArray 方法,分别传递了字符串数组和整数数组。由于泛型的存在,我们能够使用相同的方法处理不同类型的数据,提高了代码的可重用性。

再举个例子

java 复制代码
/**
 * @ClassName: Method03
 * @Description: 方法3 可以存储任意类型的数据
 * @Author: liu
 * @Date: 2024-03-09
 * @Version: 1.0
 **/
public class Method3 {
    public static void main(String[] args) {
        // 创建一个存储整数的 Box 实例
        Box<Integer> integerBox = new Box<>();
        integerBox.setValue(42);
        System.out.println("Integer Value: " + integerBox.getValue());

        // 创建一个存储字符串的 Box 实例
        Box<String> stringBox = new Box<>();
        stringBox.setValue("Hello, Generics!");
        System.out.println("String Value: " + stringBox.getValue());

        // 创建一个存储布尔值的 Box 实例
        Box<Boolean> booleanBox = new Box<>();
        booleanBox.setValue(true);
        System.out.println("Boolean Value: " + booleanBox.getValue());
    }
}
@Data
class Box<T> {
    private T value;
}

2. 泛型上限和下限通配符

首先,让我们来看一个简单的泛型类和泛型方法的例子。考虑到动物(Animals)和猫(Cat)、狗(Dog)的实体类:

java 复制代码
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Animals {
    public String name;
    public Integer age;
}

@Data
public class Cat {
    public String name;
    public Integer age;
    public Say say;

    public Cat(String name, Integer age, Say say) {
        this.name = name;
        this.age = age;
        this.say = say;
        System.out.println("Cat的全参构造执行,猫边唱歌吃鱼");
    }

    public Cat() {
        System.out.println("Cat的无参构造执行,你创建了猫,却一笑而过!");
    }
}

@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Dog extends Animals {
    public String name;
    public Integer age;
}

@Data
public class Say {
    public String say;

    public Say(String say) {
        this.say = say;
        System.out.println("说话" + say);
    }
}

接下来,我们将介绍泛型上限和下限通配符的概念,并通过例子 Method02 进行演示。

java 复制代码
/**
 * @ClassName: Method02
 * @Description: 方法2, 泛型上限和下限通配符
 * @Author: liu
 * @Date: 2024-03-09
 * @Version: 1.0
 **/
public class Method02 {
    public static void main(String[] args) {
/*        Cat cat = new Cat();
        Dog dog1 = new Dog("旺财", 3);
        Cat cat1 = new Cat("小花", 2, new Say("喵喵喵"));
        Animals animal1 = new Animals("小动物", 1);
        List<Dog> dogList = new ArrayList<>();
        List<Cat> catList = new ArrayList<>();
        List<Animals> animalsList = new ArrayList<>();
        animalsList.add(animal1);
        dogList.add(dog1);
        catList.add(cat1);*/

        // 使用菱形操作符和双括号初始化简化代码
        // 在匿名内部类中,Java 并不允许使用 <> 进行菱形操作符的类型推断,还可以使用 Arrays.asList() 方法

        List<Dog> dogList = new ArrayList<Dog>(){
            private static final long serialVersionUID = -3322276720822396481L;

            {
            add(new Dog("狗王", 2));
            add(new Dog("狗王后", 3));
        }};
        List<Cat> catList = Arrays.asList(
                new Cat("猫王", 1, new Say("喵~")),
                new Cat()
        );
        List<Animals> animalsList = new ArrayList<Animals>(){
            private static final long serialVersionUID = 1L;
            {
            add(new Animals("小动物", 1));

        }};
        //reason: no instance(s) of type variable(s) exist so that Cat conforms to Animals
        //extendMethod(catList);// 编译报错
        // 泛型方法调用示例
        extendMethod(dogList);  // 合法,List<Dog> 是 List<? extends Animals> 的子类
        extendMethod(animalsList);  // 合法,List<Animals> 是 List<? extends Animals> 的子类

        System.out.println("=====================================");

        superMethod(dogList);  // 合法
        //编译报错,List<Cat> 不是 List<? super Dog> 的子类
        //superMethod(catList);
        //编译合法,运行报错UnsupportedOperationException
        //superMethod(Collections.unmodifiableList(catList));
        superMethod(animalsList);  // 合法
    }

    public static <T extends Animals> void extendMethod(List<T> list) {
        // 在这里处理只包含数字类型及其子类的列表
        for (T element : list) {
            System.out.println(element);
        }
    }
    public static void superMethod(List<? super Dog> list) {
        // 在这里处理只包含数字类型及其父类的列表
        list.add(new Dog("二狗", 2));
        //list.add(new Animals("Buddy", 2)); // 编译报错
        for (Object element : list) {
            System.out.println(element);
        }
    }
}

在上述代码中,extendMethod 方法接受一个泛型列表,其中的元素必须是 Animals 类型或其子类。而 superMethod 方法则接受一个泛型列表,其中的元素必须是 Dog 类型或其父类。这样的灵活性使得我们能够对不同层次的类进行处理。

Method02 的示例程序中,我们演示了泛型上限和下限通配符的使用:

在这个示例中,我们展示了如何使用泛型上限和下限通配符来处理不同类型的列表,使得我们的代码更具通用性和灵活性。

3. 灵活处理多个泛型参数

在实际的编程场景中,有时我们需要处理多个泛型参数的情况。在这个章节,将探讨如何在Java中灵活地处理多个泛型参数,以满足更为复杂的编码需求。

代码如下:

java 复制代码
/**
 * @ClassName: Method04
 * @Description: 演示带有多个泛型参数的Pair类的使用
 * @Author: 阿水
 * @Date: 2024-03-10
 * @Version: 1.0
 **/
public class Method04 {
    public static void main(String[] args) {
        // 创建一个带有泛型参数的Pair实例
        Pair<Dog, Cat> pair = new Pair<>();
        // 创建狗和猫的实例
        Dog dog = new Dog("旺财", 3);
        Cat cat = new Cat("小花", 2, new Say("喵喵喵"));
        // 设置Pair实例的值
        pair.setFirst(dog);
        pair.setSecond(cat);
        // 打印Pair实例的字符串表示形式以及其中的元素
        System.out.println(pair);
        System.out.println("First Element: " + pair.getFirst().getName());
        System.out.println("Second Element: " + pair.getSecond().getName());
        // 创建带有不同泛型参数的两个Pair实例
        Pair<String, Integer> pair1 = new Pair<>("One", 1);
        Pair<Double, String> pair2 = new Pair<>(6.66, "Pi");
        // 调用泛型方法打印Pair实例的值
        printPair(pair1);
        printPair(pair2);

    }

    /**
     * 打印带有泛型参数的Pair实例的值
     *
     * @param pair 带有泛型参数的Pair实例
     * @param <T>  第一个元素的类型
     * @param <U>  第二个元素的类型
     */
    public static <T, U> void printPair(Pair<T, U> pair) {
        System.out.println("Pair: " + pair.getFirst() + ", " + pair.getSecond());
    }
}

/**
 * @ClassName: Pair
 * @Description: 带有两个泛型参数的Pair类
 * @Author: 阿水
 * @Date: 2024-03-10
 * @Version: 1.0
 **/
@Data
@AllArgsConstructor
@NoArgsConstructor
class Pair<T, U> {
    private T first;
    private U second;
}

运行结果如下:

4.总结

Java泛型是一项强大的编程特性,通过泛型类和泛型方法,我们能够编写通用、灵活的代码。同时,泛型上限和下限通配符使得我们能够更好地处理不同层次的类。通过这篇博客,我们深入理解了Java泛型的灵活性、安全性和可重用性,为我们的编程工作提供了更多的便利和可能性。

相关推荐
我是华为OD~HR~栗栗呀24 分钟前
华为od-22届考研-测试面经
java·c++·python·功能测试·华为od·华为·面试
是梦终空34 分钟前
计算机毕业设计241—基于Java+Springboot+vue的爱心公益服务系统(源代码+数据库+11000字文档)
java·spring boot·vue·毕业设计·课程设计·毕业论文·爱心公益系统
_殊途35 分钟前
项目开发手册-项目结构
java
keke_俩个科36 分钟前
ShardingSphere分库分表基础配置与使用说明
java·数据库·分布式·spring
爬虫程序猿38 分钟前
把“天猫”装进 JVM:Java 关键词商品爬虫从 0 到 1(含完整可运行代码)
java·jvm·爬虫
java_logo40 分钟前
Docker 部署微服务项目保姆级教程
java·运维·docker·微服务·容器·eureka·架构
oak隔壁找我1 小时前
Servlet 三大组件详解
java·后端
南部余额1 小时前
Spring MVC 拦截器interceptor
java·spring·mvc
oak隔壁找我1 小时前
SpringBoot 实现 JWT 认证完整方案
java·后端
wb043072011 小时前
如何开发一个 IDEA 插件通过 Ollama 调用大模型为方法生成仙侠风格的注释
人工智能·语言模型·kotlin·intellij-idea