• (Java数据结构)泛型


    泛型的使用

    泛型是在JDK1.5引入的新的语法,泛型:就是适用于许多许多类型。从代码上讲,就是对类型实现了参数化

    类和接口总览
    在这里插入图片描述
    在这里插入图片描述
    对类型实现了参数化,这是什么意思?

    在这里插入图片描述

    两个类之间可以转,但是两个数组之间不行。

    class MyArray{
        Object[] obj=new Object[10];
        public void setVal(int pos,Object val){
            obj[pos]=val;
        }
        public Object getPos(int pos){
            return obj[pos];
        }
    }
    public class Test {
    
        public static void main(String[] args) {
            MyArray myArray=new MyArray();
            myArray.setVal(0,10);
            myArray.setVal(1,"苹果");
            myArray.setVal(2,10.5);
            String str=(String) myArray.getPos(1);
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    可以发现:在存放元素的时候任何类型的元素都可以存放。但是在取出元素的时候要判断元素的类型(要强转).

    在这里插入图片描述

    class MyArray<T>{
    //是占位符,表示当前类是泛型类
        public T[] obj=(T[]) new Object[10];//这种写法是不太好的
        public void setVal(int pos,T val){
            obj[pos]=val;
        }
        public T getPos(int pos){
            return obj[pos];
        }
    }
    public class Test {
        public static void main(String[] args) {
            MyArray<Integer> myArray=new MyArray<Integer>();
            myArray.setVal(0,10);
            myArray.setVal(1,2);
            myArray.setVal(2,6);
            int a =myArray.getPos(1);//类型不用进行强转
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    总结一下:
    泛型的作用:
    1.存元素的时候进行类型检查
    2.取出元素的时候不用强转
    (编译的时候完成的)=>擦除机制

    擦除机制:在编译时期把T都擦除成了Object

    public T[] obj=(T[]) new Object[10];//这种写法是不太好的
    //原因:擦除机制使T->Object,如果写一个返回数组的方法,用一个Int[]类型数组接收,跟上面说的一样会报错。
    
    • 1
    • 2
    //正确写法:
    public MyArray(Class<T> clazz, int capacity) {
    array = (T[])Array.newInstance(clazz, capacity);
    }
    //这样在存元素传入类型后擦除机制使T->指定的类型(非Object),这样数组之间转换就是正常的
    
    • 1
    • 2
    • 3
    • 4
    • 5

    T是一个引用类型,引用类型包括类、接口、委托和装箱值类型。

    泛型的上界

    写一个泛型类,类中有一个泛型方法,可以求数组的最大值。

    //传Integer类型
    class Alg<T extends Comparable<T>>{
    //Object类中没有Comparable接口,没有compareTo方法
        public T findMax(T[] array){
            T max=array[0];
            for(int i=1;i< array.length;i++){
                if(max.compareTo(array[i])<0){
                //当传入Integer时,Integer中有compareTo方法,不用重写
                    max=array[i];
                }
            }
            return max;
        }
    }
    public static void main1(String[] args) {
            Alg<Integer> alg=new Alg<>();
            Integer[] arr={1,2,3,4};
            Integer ret=alg.findMax(arr);
            System.out.println(ret);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    //传自定义类
    class Person implements Comparable<Person>{
        public int age;
    
        public Person(int age) {
            this.age = age;
        }
    
        @Override
        public int compareTo(Person o) {
            return this.age-o.age;
        }
    
        @Override
        public String toString() {
            return "Person{" +
                    "age=" + age +
                    '}';
        }
    }
    public static void main(String[] args) {
            Alg<Person> alg=new Alg<>();
            Person[] people={new Person(10),new Person(15)};
            Person ret=alg.findMax(people);
            System.out.println(ret);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    在这里插入图片描述

    在定义泛型类时,有时需要对传入的类型变量做一定的约束,可以通过类型边界来约束。

    public class MyArray<E extends Number> {
    //擦除成Number
    ...
    }
    
    • 1
    • 2
    • 3
    • 4

    只接受 Number 的子类型(包括Number)作为 E 的类型实参

    泛型的方法

    class Alg2{
        public static <T extends Comparable<T>>T findMax(T[] array){
            T max=array[0];
            for(int i=1;i< array.length;i++){
                if(max.compareTo(array[i])<0){
                    max=array[i];
                }
            }
            return max;
        }
    
    }
    public class Test2 {
        public static void main(String[] args) {
            Integer[] arr={1,2,3,4};
            Integer ret=Alg2.<Integer>findMax(arr); //可以省略,编译器可以根据传入的arr类型进行推导
            System.out.println(ret);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    通配符

    class Message<T> {
        private T message ;//消息
    
        public T getMessage() {
            return message;
        }
    
        public void setMessage(T message) {
            this.message = message;
        }
    
    }
    public class Test {
        public static void main1(String[] args) {
            Message<String> message = new Message<>() ;
            message.setMessage("比特就业课欢迎您");
            fun(message);
        }
    
        public static void main(String[] args) {
            Message<Integer> message = new Message<>() ;
            message.setMessage(10);
            fun(message);
        }
        public static void fun(Message<?> temp){
            System.out.println(temp.getMessage());
            //temp.setMessage(100); 无法修改!
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    通配符"?"可以接收所有的泛型类型,但是又不能够让用户随意修改。
    在这里插入图片描述

    通配符上界

    在这里插入图片描述

    //可以传入的实参类型是Number或者Number的子类
    class Food {
    
    }
    class Fruit extends Food {
    
    }
    class Apple extends Fruit {
    
    }
    class Banana extends Fruit {
    
    }
    
    class Plate<T> { // 设置泛型 shift+f6
        private T plate ;
    
        public T getPlate() {
            return plate;
        }
    
        public void setPlate(T plate) {
            this.plate = plate;
        }
    }
    public static void main1(String[] args) {
            Plate<Apple> plate1 = new Plate<>();
            plate1.setPlate(new Apple());
            fun1(plate1);
    
            Plate<Banana> plate2 = new Plate<>();
            plate2.setPlate(new Banana());
            fun1(plate2);
        }
    
        public static void fun1(Plate<? extends Fruit> temp){
            /*
            不能放东西
            temp.setPlate(new Apple());//如果里面是Banana不行
            temp.setPlate(new Banana());//如果里面是Apple不行
            temp.setPlate(new Fruit());//如果里面是Banana和Apple都不行,向下转型
            */
            Fruit fruit = temp.getPlate();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    通配符的上界,不能写入数据,只能读取数据。

    通配符下界

    //代表 可以传入的实参的类型是Integer或者Integer的父类

    可以写入数据,不能取数据
    比如可以写入fruit的子类,不能取不知道用什么来接收。

    装箱和拆箱

    装箱

    基本类型->包装类型

    Integer b=new Integer(1);
    Integer c=2;
    Integer d=Integer.valueOf(3);
    
    • 1
    • 2
    • 3

    拆箱

    包装类型->基本类型

    Integer a=10;
    int b=a;
    int c=a.intValue();
    
    • 1
    • 2
    • 3
    Integer a = 127;
    Integer b = 127;
    Integer c = 128;
    Integer d = 128;
    System.out.println(a == b);
    System.out.println(c == d);
    //true
    //false
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    装箱会调用valueOf方法

    在这里插入图片描述

  • 相关阅读:
    6.qml中js的object,array数据更新不通知页面刷新问题解析
    python基础教程:print()函数知识点总结
    spring boot零配置
    使用ceph-deploy部署Ceph集群
    SimpleServletHandlerAdapter类简介说明
    【力扣刷题】回文链表、环形链表、合并两个有序链表
    大数据_HDFS原理
    NodeJs实战-待办列表(2)-待办列表增删
    【图像分类】Swin Transformer理论解读+实践测试
    基于GBDT+Tkinter+穷举法按排队时间预测最优路径的智能导航推荐系统——机器学习算法应用(含Python工程源码)+数据集(四)
  • 原文地址:https://blog.csdn.net/qq_63983125/article/details/126906421