Java泛型最全详解(万字图文总结)

Java泛型最全详解(万字图文总结)-mikechen

Java泛型对于Java非常的重要,也是Java面试必问的内容,下面我就来全面详解Java泛型@mikechen

Java泛型定义

Java泛型是Java语言中的一个重要特性,它提供了在编译时期进行类型检查和类型转换的功能,以保证代码的类型安全性。

 

Java泛型作用

Java泛型的作用:主要就是提高程序的类型安全性和可读性,以及避免在运行时期出现类型转换错误。

通过使用泛型,我们可以在编译时期检查数据类型的正确性,如下图所示:

Java泛型最全详解(万字图文总结)-mikechen

上图的ArrayList<String>,String即给类型指定一个字符参数,那样这个类型就固定了,避免了在运行时期出现类型转换错误的问题。

此外,泛型还可以使代码更加清晰易读,因为我们可以通过类型参数清晰地表达代码的意图。

 

Java泛型使用

Java泛型有三种使用方式,分别为:泛型类、泛型接口和泛型方法。

如下图所示:

Java泛型最全详解(万字图文总结)-mikechen

1、泛型类

泛型类:把泛型定义在类上,定义泛型类时需要在类名后面使用尖括号来声明一个或多个类型参数。

泛型类语法,如下图所示:

Java泛型最全详解(万字图文总结)-mikechen

public class 类名 <泛型类型1,...> {
    
}

注意事项:泛型类型必须是引用类型(非基本数据类型)。

泛型类示例:

public class MyList<T> {
    private List<T> list = new ArrayList<>();

    public void add(T t) {
        list.add(t);
    }

    public T get(int index) {
        return list.get(index);
    }
}

MyList<Integer> list = new MyList<>(); // 实例化泛型类时需要传入类型参数的具体类型
list.add(1);
list.add(2);
int n1 = list.get(0);

 

2、泛型接口

泛型接口是指:在接口的定义中使用了泛型类型参数的接口。

如下图所示:

Java泛型最全详解(万字图文总结)-mikechen

和泛型类类似,泛型接口也可以使用类型参数来定义接口中的方法的参数和返回值类型。

泛型接口,语法格式如下:

public <泛型类型> 返回类型 方法名(泛型类型 变量名) {
    
}

泛型接口使用示例:

public interface MyList<T> {
    void add(T t);
    T get(int index);
}

public class MyArrayList<T> implements MyList<T> {
    private List<T> list = new ArrayList<>();

    public void add(T t) {
        list.add(t);
    }

    public T get(int index) {
        return list.get(index);
    }
}

MyList<Integer> list = new MyArrayList<>(); // 实现泛型接口时需要传入类型参数的具体类型
list.add(1);
list.add(2);
int n1 = list.get(0);

在实现泛型接口时需要指定类型参数的具体类型。

 

3、泛型方法

Java泛型方法是指:在方法的定义中使用了泛型类型参数的方法。

如下图所示:

Java泛型最全详解(万字图文总结)-mikechen

泛型方法,语法格式:

修饰符 <代表泛型的变量> 返回值类型 方法名(参数){ }

 

泛型方法示例:

public class Utils {
    public static <T> T identity(T arg) { // 在泛型方法中使用泛型类型
        return arg;
    }
}

String s = Utils.identity("hello"); // 调用泛型方法时需要传入类型参数的具体类型
Integer n2 = Utils.identity(123);

 

Java泛型通配符

Java泛型通配符主要有以下三类:分别是:无边界的通配符、固定上边界的通配符、固定下边界的通配符。

Java泛型最全详解(万字图文总结)-mikechen

1. 无边界的通配符

无边界的通配符是指使用”?”来表示一个未知类型的占位符,没有任何约束条件。

它的语法形式为:

public void methodName(List<?> list) {
    // ...
}

其中,List<?>表示可以接受任意类型的List对象。

 

2. 固定上边界的通配符

Java中的泛型通配符可以使用extends关键字指定一个上边界,这种通配符被称为固定上边界通配符。

语法格式:

? extends T

“? extends T”来表示:一个上界为T的通配符,它可以匹配T类型或T的任何子类。

例如:

public void someMethod(List<? extends Number> list) {
    // 方法体
}

在上面的代码中,我们使用了泛型通配符? extends Number来表示Number类及其子类。

使用固定上边界通配符的好处是可以确保泛型参数的类型满足一定的限制,从而使程序更加类型安全。

 

3. 固定下边界的通配符

Java中的泛型通配符可以使用super关键字指定一个下边界,这种通配符被称为固定下边界通配符。

语法格式:

? super T

? super T表示:一个下界为T的通配符,它可以匹配T类型或T的任何父类。

例如:

public void someMethod(List<? super Integer> list) {
    // 方法体
}

在上面的代码中,我们使用了泛型通配符? super Integer来表示Integer类及其父类。

 

Java泛型原理

Java泛型的实现原理主要是通过类型擦除来实现的,也就是Java泛型擦除

Java泛型擦除会在编译时期,Java编译器会将所有的泛型类型,擦除成它们的上界类型(或者Object类型)。

下面是一个示例来说明Java泛型擦除的示例:

public class MyList<T> {
    private List<T> list = new ArrayList<>();

    public void add(T t) {
        list.add(t);
    }

    public T get(int index) {
        return list.get(index);
    }
}

在编译时期,Java编译器会将泛型类型T擦除成它的上界类型Object。

如下所示:

public class MyList {
    private List list = new ArrayList();

    public void add(Object t) {
        list.add(t);
    }

    public Object get(int index) {
        return list.get(index);
    }
}

可以看到,所有的泛型类型都被擦除了,并且在运行时期只能访问到Object类型的元素。

 

Java泛型应用场景

Java泛型主要应用于以下几个场景:

1.Java集合框架

Java集合框架中的各种集合类,如ArrayListLinkedListHashMap等,都使用泛型来规定集合中元素的类型。

使用泛型可以避免在运行时出现类型转换异常,并可以提高代码的可读性和可维护性。

2.类型安全的容器

使用泛型可以创建类型安全的容器,可以在编译时期避免向容器中添加不正确的类型。这样可以提高代码的可靠性和安全性。

3.泛型方法

在方法中使用泛型可以使方法更加灵活,可以接受多种类型的参数,而不必为每一种类型都写一个方法。

4.泛型接口

Java接口中可以使用泛型来规定接口中的方法返回值类型、参数类型等,从而使得接口更加灵活。

以上就是Java泛型详解,更多Java内容请查看:Java基础全面总结,强烈建议大家收藏!

陈睿mikechen

10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。

关注「mikechen」公众号,获取更多技术干货!

后台回复面试即可获取《史上最全阿里Java面试题总结》,后台回复架构,即可获取《阿里架构师进阶专题全部合集

评论交流
    说说你的看法