首页 > 编程笔记 > Java笔记 阅读:1

Java泛型类的定义和使用(非常详细)

在 Java 开发中,泛型是一项非常重要的技术。使用泛型技术可以通过类型参数化的方式处理不同类型的对象,同时又能保证编译时的类型安全。在集合中使用泛型,可以省去使用集合数据时要做的类型转换操作。

泛型的本质是参数化类型,是将所操作的数据类型指定为一个参数。

泛型解决了数据类型的安全性问题,在声明类或实例化时需要指定好处理数据的具体类型。这种参数化类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。

Java 泛型可以让程序在编译时有更强的类型检查,解决程序在编译时发出的数据类型警告。同时,可以消除强制类型转换,使代码更加简洁、健壮。

Java泛型类的声明和使用

Java 集合默认情况下会自动将添加的数据转为 Object 类型存储,因此取出数据的时候,需要使用 Object 类的变量来接受。另外,因为无法判断取出的数据原本是什么类型的,所以会导致强制类型转换的时候容易出错。

接下来,通过案例来演示这种情况:
public class Demo {
    public static void main(String[] args) {
        MyCls mycls = new MyCls(); // 创建MyCls对象
        mycls.set("字符串"); // 设置字符串类型的数据
        Integer i = (Integer) mycls.get(); // 取值时强制转换为Integer类型
        System.out.println(i);
    }
}

class MyCls {
    private Object variable;

    public void set(Object variable) {
        this.variable = variable;
    }

    public Object get() {
        return variable;
    }
}
程序运行会报错,提示“ClassCastException”,中文含义是“类型转换异常”,这是因为第 5 行存入了一个 String 类型的值,而第 6 行取出这个值时,将其强制转换为 Integer 类型,出现了类型转换的错误,为了避免这个错误,此时就可以使用泛型。

在定义 MyCls 类时可以使用 <T> 声明参数类型(T 其实就是特定类型的简写字符,这里也可以使用其他字符),然后将 set() 方法的参数类型和 get() 方法的返回值类型都声明为 T。这样在存入元素时,元素的类型就被限定了,容器就被限定只能存入 T 类型的元素。取出元素时,由于元素类型已被限定,因此也无须类型转换。

接下来,通过案例来演示如何自定义泛型:
public class Demo {
    public static void main(String[] args) {
        MyCls<String> mycls = new MyCls<String>(); // 设置字符串类型参数
        mycls.set("字符串"); // 设置字符串类型参数
        String s = mycls.get(); // 获取字符串类型参数
        System.out.println(s);
    }
}

class MyCls<T> { // 创建类时,指定泛型类型为T类型
    T variable;
    public void set(T variable) { // 指定set()方法参数为T类型
        this.variable = variable;
    }
    public T get() { // 指定get()方法返回值为T类型
        return variable;
    }
}
程序的运行结果如下:

字符串

程序中 MyCls 类声明了泛型类型为 T,其中 set() 方法参数类型和 get() 方法返回值类型都为 T。在 main() 方法中创建 MyCls 对象实例时,通过 <String> 将泛型 T 指定为 String 类型,调用 set() 方法存入 String 类型的数据,调用 get() 方法取出的值自然是 String 类型,这样就不需要进行类型转换,使得程序更加健壮。

Java泛型在集合中的使用

在 Java 程序使用集合时,代码中会出现类型安全的警告,其原因是未指定泛型。如果指定了泛型,就不会出现这种警告。

泛型在定义集合类时,使用“<参数化类型>”的方式指定该集合存储的数据类型,语法格式如下:
集合类型<参数化类型> 集合变量 = new 集合类型<参数化类型>();
接下来,通过案例来演示泛型在集合中的使用:
import java.util.ArrayList;

public class Demo {
    public static void main(String[] args) {
        // 创建泛型集合,限定只能添加整型数据
        ArrayList<Integer> list = new ArrayList<Integer>();
        list.add(100); // 添加元素
        list.add(200);
        list.add(300);
        System.out.println(list); // 打印集合
    }
}
程序的运行结果如下:

[100, 200, 300]

程序中创建集合的时候,指定了泛型为 Integer 类型,限制该集合只能添加 Integer 类型的元素,编译文件时,不再出现类型安全警告,这时如果向集合中添加非 Integer 类型的元素,会出现编译时异常。

了解了泛型的定义和基本使用后,下面进一步了解一下泛型通配符的概念。泛型通配符用符号“?”表示。例如,List<?> 表示可以通配 List<String>、List<Object> 等各种具体泛型 List。

接下来,通过案例来演示泛型通配符的使用:
import java.util.*;

public class Demo {
    public static void main(String[] args) {
        List<?> list = null; // 声明List泛型为?
        list = new ArrayList<Integer>(); // 编译时异常
        // list.add(666); // 编译时异常
        list = new ArrayList<String>(); // 编译时异常
        // list.add("AAA软件教育"); // 编译时异常
        // list.add(null); // 添加元素null
        System.out.println(list);
        List<Float> list1 = new ArrayList<Float>();
        List<String> list2 = new ArrayList<String>();
        list1.add(3.1415926f);
        list2.add("梅超风");
        show(list1);
        show(list2);
    }

    static void show(List<?> list) {
        for (Object object : list) {
            System.out.println(object);
        }
    }
}
程序的运行结果如下:

[null]
3.1415925
梅超风

程序中创建 List 对象时声明泛型类型为“?”,泛型类型设为 String 或 Float 时都没有报错,说明泛型通配符的可扩展性。但是,直接向泛型集合中添加元素时会报错,因为 List 集合中的元素类型是不确定的。添加 null 到集合时不会报错,因为 null 是所有类型的成员。

此外,在方法 show() 的参数声明中,List 参数使用了泛型通配符“?”,所以该方法能接收多种参数类型的集合。

相关文章