泛型如何定义和使用?

根据使用的地方分为3种,分别是泛型类,泛型方法和泛型接口。

(1)泛型类

泛型类的定义

在类名的后面加一对尖括号,括号中填写类型参数,参数可以有多个,多个参数之间使用逗号分隔。

下面是一个例子:

java 复制代码
public class GenericTest <E>{
    private E value;
    public E getValue(){
        return value;
    }
    public void setValue(E e){
        this.value = e;
    }
}

Java 还是建议使用单个大写字母来代表类型参数。常见的如:

  1. T 代表Type的意思,表示任意的类。
  2. E 代表 Element 的意思,或者 Exception 异常的意思。
  3. K 代表 Key 的意思。
  4. V 代表 Value 的意思,通常与 K 一起配合使用。
  5. S 代表 Subtype 的意思,文章后面部分会讲解示意。

泛型类的使用

在创建泛型类对象的时候指定相应的类型,如ArrayList<String>。

(2)泛型方法

泛型方法的定义

尖括号那一部分写在返回值之前

下面是一个例子:

java 复制代码
public class GenericTest2 {
    public <E> void set(E e){

    }
}

有一点需要注意:不能使用别的方法中使用本方法中定义的泛型,会报错。可以理解为此泛型的作用范围只有本方法。

泛型方法的使用

java 复制代码
public class GenericDemo2 {
    public static void main(String[] args) {
        GenericTest2 g2 = new GenericTest2();
        g2.set("123");
    }
}

类型推断:编译器会根据调用方法时实参的类型进行推断,所以不用在尖括号中间指定类型。例如,在上述代码中,编译器根据传递的参数"123" 将E指定为String 类型,它发生在编译时。

练习1:定义一个工具类ListUtil,其中有一个静态方法,可以向不同的集合中添加多个元素。

java 复制代码
public class ListUtil {
    private ListUtil(){

    }
    public static <E> void addAll (ArrayList<E> list, E e1, E e2){
        list.add(e1);
        list.add(e2);
    }
}

在调用此方法将list传递过去的时候,会将E指定为String类型。

java 复制代码
public class GenericDemo3 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("1");
        list.add("2");
        list.add("3");
        ListUtil.addAll(list, "3", "4");
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            String s = iterator.next();
            System.out.println(s);
        }
    }
}

细节:而且这个方法可以传递任意的类型过去。

(3)泛型接口

泛型接口的定义

也是在接口的后面加上一对尖括号。

java 复制代码
public interface Iterable<T> {
}

泛型接口的使用

根据实现的时候是否确定类型有两种方式去实现接口。

方式1:在接口后面的尖括号中给出具体类型。

java 复制代码
public class GenericDemo6 implements List<String> {
    @Override
    public int size() {
        return 0;
    }

    @Override
    public boolean isEmpty() {
        return false;
    }

...

}

这里的类GenericDemo6在实现时给出具体的String类型,那么在创建实现类的对象时就不用再给出类型了,并且操作的只能是String类型的数据。

方式2:实现类依然延续泛型,在类名和接口后面都加上一对尖括号,创建对象时再指定类型。

java 复制代码
public class GenericDemo7<E> implements List<E> {
    @Override
    public int size() {
        return 0;
    }

    @Override
    public boolean isEmpty() {
        return false;
    }

...

}

细节:

一个.java文件里可以有多个类。

多个类中只能有一个public类,而且文件名只能是public类的名字;

如果多个类中没有public类,则文件名可以是任意一个类的名字。

相关推荐
Rabitebla21 分钟前
C++11 新特性详解(一):列表初始化、initializer_list 与右值引用
java·开发语言·数据结构·c++·算法·leetcode·list
洋不写bug27 分钟前
JavaComparable、Comparator、Cloneable接口解析,深拷贝浅拷贝详细解析
android·java·开发语言
坐吃山猪39 分钟前
WebFlux_学习Subscriber总结
java·开发语言·学习·webflux
白露与泡影1 小时前
Java面试题及答案整理(2026年金九银十最新版,持续更新)
java·开发语言
geovindu1 小时前
java: Memento Pattern
java·开发语言·后端·备忘录模式·行为模式
xcLeigh1 小时前
Unity基础:Start与Update方法——Unity脚本生命周期初探
java·unity·游戏引擎·教程
zephyr051 小时前
链表实现O(n log n)时间复杂度的排序——归并排序详解
java·数据结构·算法
Zane19941 小时前
JRE 去哪了?一次讲清楚 JDK、JRE、JVM 到底是什么关系?
java·后端
PPPPickup1 小时前
基础知识差缺补漏-面试版持续更新
java·开发语言
深入云栈1 小时前
Nacos 2.x 源码深度解析 (二):通信协议迭代 —— HTTP长轮询到gRPC演进
java