目录

泛型

# 介绍

  • JDK1.5 版本后出现,JDK1.7版本后 new Array<>()可以省略类型,该 <> 称为钻石运算符
  • 本质:参数化类型,把类型作为参数传递
  • 常见形式:泛型类、泛型接口、泛型方法
  • 语法:成为类型占位符,表示一种引用类型,可以写多个逗号隔开
  • 类型:都是引用类型,不能是基本数据类型
  • 好处 1. 提高代码重用性 2. 防止类型转换异常,提高代码安全性

# 不使用泛型缺点

一般存入集合的都是相同类型的数据,但是不适用泛型,无法规定只能使用相同类型的数据,不便于管理。

# 泛型类、泛型接口

  • 实例化时不指定类的泛型,默认为 Object 类型

    ArrayList list = new ArrayList();
    list.add(1); // 既可以添加 Integer 类型
    list.add("abc"); // 也可以添加字符串类型等
    
    1
    2
    3
  • 如果子类继承泛型的父类,不指定父类的泛型,则子类必须也是泛型

    public class Demo1<T>{}
    class Demo2<T> extends Demo1<T>{}
    class Demo3 extends Demo1<Integer>{}
    
    1
    2
    3
  • 不同的泛型的引用类型不可以互相赋值,不可重载

    • 本质都是 Object 类型,只不过操作的数据规定指定类型,两者属于同级关系,无法进行多态,只有子才能转为父
    public void test(ArrayList<String> a){
        
        ArrayList<String> list1 = null;
        ArrayList<Integer> list2 = nulll;
        list1 = list2; // 编译就报错了        
    }
    
    1
    2
    3
    4
    5
    6
  • 泛型类的静态方法不允许出现类的泛型

    • 因为静态修饰的东西会优先类加载到内存中,但是此时泛型还没有指定是什么类型,所以报错
    public class Demo1<T>{
        public static void test(T t){} // 报错
    }
    
    1
    2
    3
  • 不能直接使用 T[] 创建数组

    T[] t = new T[5]; // 报错
    T[] t = (T[]) new Object[5]; // 这样可以,实际就是 Object 类型的数组,不是你要传入的类型数组
    
    1
    2

# 泛型方法

  • 不是带泛型的方法就是泛型方法

  • 方法的泛型和类的泛型无关

  • 需要在返回值前加入泛型符号,与参数的泛型符号一致,否则参数的泛型符号默认为某个类的名字,但是该类不可能存在

public class Demo<T>{
    // 不是泛型方法
    public void a(T t){}
    // 是泛型方法
    public <E> void a(E e){}
}
1
2
3
4
5
6
  • 泛型方法的静态方法允许出现类的泛型

    • 因为静态修饰的东西会优先 ,但是不优先 方法 加载到内存中,所以方法可以加泛型,调用方法再传入泛型

      public class Demo1<T>{
          public static <E> void test(E e){} // 报错
      }
      
      1
      2
      3

# 通配符?

  • ? 是泛型的通配符,可以解决互相赋值,重载问题

  • 使用了通配符,遍历时候使用 Object 获取数据

    public void test(ArrayList<String> a){
        
        ArrayList<String> list1 = null;
        ArrayList<Integer> list2 = nulll;
        list1 = list2; // 编译就报错了
        
        ArrayList<?> list3 = null; // ? 为通配符,可以认为属于所有泛型的父类
        list3 = list1; // 成功
            
    }
    public void test(ArrayList<Integer> a){ // 报错,因为泛型本质都是 Object,所以参数类型一样,不是重载,是复制
        
    }
    public void test(ArrayList<?> a){ // 不会报错,因为?是泛型的通配符,所以参数类型不一样,是重载
        
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
  • 使用通配符,无法添加数据,因为此时不知道泛型的类型是什么

  • 可以获得数据,根据 Object 获取

    public void test(){
        
        ArrayList<?> list = new ArrayList<>(); // ? 为通配符,可以认为属于所有泛型的父类
        list.add("abc"); // 报错,因为此时的 list 不属于任何类型
        
        Obejct value = list.get(1); // 可以,Object 是所有类的父类
    }
    
    
    1
    2
    3
    4
    5
    6
    7
    8

# 泛型受限

上限(? extends XX):只接受 XX 以及 XX 的子类及以下

下限(? super XX):只接受 XX 以及 XX 的父类及以上

class Person(){}
class Student(){}
public class test(){
    public static void main(String[] args){
        // List 本质属于 Object,并列关系,无法彼此直接赋值
        List<Person> person = new ArrayList<>();
        List<Student> student = new ArrayList<>();
        // 泛型上限,只接受 Person 以及 Person 的子类及以下
        List<? extends Person> list1 = null;
        list1 = person;// 可以
        list1 = student;// 可以,因为student属于Person的子类
        // 泛型下限,只接受 Person 以及 Person 的父类及以上
        List<? super Person> list2 = null;
        list2 = person; // 可以
        list2 = student; // 不可以,报错
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

#

更新时间: 2024/01/17, 05:48:13
最近更新
01
JVM调优
12-10
02
jenkins
12-10
03
Arthas
12-10
更多文章>