# 数据结构前置知识---泛型

数据结构前置知识—泛型

一、包装类

1.1什么是包装类

简单来说,包装类型就是基本数据类型的plus版本,也可以说包装类就是引用数据类型,它可以更好的支持面向对象。

基本数据类型包装类
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean

1.2装箱和拆箱

装箱指将基本数据类型给包装(引用)类型,反之,拆箱就是将包装(引用)数据类型给基本数据类型。

1.3自动装箱和自动拆箱

自动装箱也称隐式装箱,就是不调用valueOf方法。反之,显示的就是调用valueOf方法,显示装箱的类型根据自己需要改变,如:Byte a = Byte.valueOf();同理显示拆箱也一样,如:Byte a = c.byte()。

public class Test {
    //自动装箱
    Integer a = 100;
    //自动拆箱
    int b = a;
    //显示装箱
    int dd = 15;
    Integer ee = Integer.valueOf(dd);
    //显示拆箱
    Integer cc = 77;
    int aa = cc.intValue();
}

面试题
以下代码的输出结果

		Integer a = 100;
        Integer b = 100;


        Integer c = 200;
        Integer d = 200;
        System.out.println(a==b);
        System.out.println(c==d);
结果:true  false

原因
我们知道包装类的底层是调用valueOf方法,那么我们首先应该想到去看这个方法的源代码。

在这里插入图片描述

这段代码的意思是,如果i在[low,high]范围内([-128,127]),那么就返回i + (-IntegerCache.low)下标的值,如果不在这个范围,就new一个新对象,即产生一个新地址,返回新地址的值。

在这里插入图片描述

例如:i=-128,在范围内,那么就返回下标为-128+(-(-128))的值,即返回下标为0的值,就是128。因此,上述代码中100在范围内,所以返回同样下标的值,就相等,而200不在范围内,两个变量就会分别产生新对象即新地址,值不一样,就不相等。

二、泛型

2.1什么是泛型

泛型简单来说就是一种语法。

2.2引出泛型

思考下面的题
实现一个类,类中包含一个数组成员,使得数组中可以存放任何类型的数据,也可以根据成员方法返回数组中某个下标的值?
思路

2.2.1Object类

既然是存放任意类型的数组,那么我们就定义一个Object类型的数组

class MyArray {
    public Object[] array = new Object[10];
    public Object getPos(int pos) {
        return this.array[pos];
    }
    public void setVal(int pos,Object val) {
        this.array[pos] = val;
    }
}


public class Test {
    public static void main(String[] args) {
        //创建一个可以放任意数据类型的数组
        //1.Object类数组
        MyArray myArray = new MyArray();
        myArray.setVal(0,10);
        myArray.setVal(1,"hello");//字符串也可以存放
//      String ret =  myArray.getPos(1);//编译报错 因为向下转型要强转
        String ret = (String) myArray.getPos(1);
        System.out.println(ret);
    }
}
结果:hello

所以这种方法是可行的,当前数组任何数据都可以存放,会显得很杂乱,并且每次要获取都要强转很麻烦,所以我们还是希望他只能够持有一种数据类型。而不是同时持有这么多类型。所以,泛型的主要目的:就是指定当前的容器,要持有什么类型的对象。让编译器去做检查。此时,就需要把类型,作为参数传递。需要什么类型,就传入什么类型。

2.2.2泛型

语法

class 泛型类名称<类型形参列表> {
// 这里可以使用类型参数
}
class ClassName<T1, T2, ..., Tn> {
}
//可以是任意字母 只是一个占位符 表示是一个泛型类

此时上述代码可以改写为

class MyArray <T>{
    //泛型写法
//public [T] array = ([T])new Object[10];
//T[] array = new T[10];这两种写法都是不对的
    public Object[] array = new Object[10];
    public void setVal(int pos,T val) {
        this.array[pos] = val;
    }
    public T getPos(int pos) {
        return (T) this.array[pos];
    }
}
public class Test {
    public static void main(String[] args) {
         //2.泛型
        MyArray<Integer> myArray = new MyArray<>();//2
        myArray.setVal(0,10);
        myArray.setVal(1,12);
        int ret = myArray.getPos(1);//3
        System.out.println(ret);
        
        
        MyArray<String> myArray1 = new MyArray<>();
        myArray1.setVal(2,"bit");//4
        String ret1 = myArray1.getPos(2);
        System.out.println(ret1);

    }
}

从以上代码可以看出泛型的主要功能就是可以传递类型
T[] array = new T[10];这种写法是因为,泛型概念只是在编译的时候有,当运行到JVM时,就没有泛型概念那么就无法知道这个泛型具体指哪个类型
public [T] array = ([T])new Object[10];

2.2泛型工作机制

在编译时,将T擦除为Object。

三、泛型上界

3.1语法

class 泛型类名称<类型形参 extends 类型边界> {

}

3.2举例

//1.泛型上界
//表示可以传Number或是Number子类的数据 即包装类 传String就不行
//class Person{
//
//}
可以传Person和Student类型 因为Student是子类
//class Student extends Person{
//
//}
//class Myarray<T extends Person>{
//
//}
public class Test {
//        public static void main1(String[] args) {
//        //1.泛型上界
//        MyArray <Number> myArray = new MyArray<>();
//        MyArray <Integer> myArray1 = new MyArray<>();
//        System.out.println("============");
//        Myarray <Person> array = new Myarray();
//        Myarray <Student> arrays = new Myarray<>();
//    }

3.3复杂的例子

比较出数组的最大值

class MyArray<T>{
    //表示这个T类型实现了Comparable接口
    public Object[] array = new Object[10];
    //比较方法
    public T FindMax(T array[]){
        T max = array[0];
        for (int i = 1; i <array.length; i++) {
            //因为T类型一定是包装类型 包装类型都实现了Comparable接口
            if(max<array[i]){//这里报错
                max = array[i];
            }
        }
        return max;
    }
}

报错原因:1.首先传入的T一定是引用数据类型,引用数据类型在比较的时候,是实现了Comparable接口,然后调用compareTo方法,但是T在编译时被擦除为Object,而Object没有实现Comparable接口,因此如法进行比较。所以要让T实现这个接口。

在这里插入图片描述

2.修改之后,依然报错是因为,实现了接口以后,就可以调用Compare方法进行比较。

class MyArray<T extends Comparable<T>>{
    //表示这个T类型实现了Comparable接口
    public Object[] array = new Object[10];
    //比较方法
    public T FindMax(T array[]){
        T max = array[0];
        for (int i = 1; i <array.length; i++) {
            //因为T类型一定是包装类型 包装类型都实现了Comparable接口
            if(max.compareTo(array[i])<0){//前面的小于后面的 返回0 更新max
                max = array[i];
            }
        }
        return max;
    }
}

3.分别传入两个类型,一个Integer类,一个Person类

class MyArray<T extends Comparable<T>>{
    //表示这个T类型实现了Comparable接口
    //比较方法
    public T FindMax(T array[]){
        T max = array[0];
        for (int i = 1; i <array.length; i++) {
            //因为T类型一定是包装类型 包装类型都实现了Comparable接口
            if(max.compareTo(array[i])<0){
                max = array[i];
            }
        }
        return max;
    }
}

  public static void main(String[] args) {
        //2.举例 比较出数组的最大值
        MyArray <Integer> myArray = new MyArray<>();
        Integer[] array ={8,15,6,19,77};
        System.out.println(myArray.FindMax(array));
        System.out.println("============");
        MyArray<Person> myArray1 = new MyArray<>();//报错

    }
    结果:77
**报错原因:<T extends Comparable<T>>这个的意思是,传入的引用类型一定实现了Comparable接口,但是Person没有实现这个接口,要想不报错,就要让Person实现这个接口,并且重写CompareTo方法。**


class Person implements Comparable<Person>{
    @Override
    public int compareTo(Person o) {
        return 0;
    }
}

3.4泛型方法

class MyArray{
    public T FindMax(T array[]){
        T max = array[0];
        for (int i = 1; i <array.length; i++) {
            //因为T类型一定是包装类型 包装类型都实现了Comparable接口
            if(max.compareTo(array[i])<0){
                max = array[i];
            }
        }
        return max;
    }
}
报错,原因是类是普通类,而方法是泛型方法,在new一个对象时,没有传入指定类型,所以不知道T是什么,因此改为

class MyArray{
    public <T extends Comparable<T>>T FindMax(T array[]){
        T max = array[0];
        for (int i = 1; i <array.length; i++) {
            //因为T类型一定是包装类型 包装类型都实现了Comparable接口
            if(max.compareTo(array[i])<0){
                max = array[i];
            }
        }
        return max;
    }
}

 public static void main(String[] args) {
        //3.泛型方法
        MyArray myArray = new MyArray();
        Integer[] array ={8,15,6,19,77};
        //这里的Integer可传可不传 不传 那么就根据传入的实参类型推导出T的类型 传了 直接确定T的类型
        System.out.println(myArray.<Integer>FindMax(array));

    }

3.5静态泛型方法

在方法前加static 调用时用类名.直接调用 就不用实例化对象
```
  public static void main(String[] args) {
        //3.泛型方法
        Integer[] array ={8,15,6,19,77};
        System.out.println(MyArray.<Integer>FindMax(array));

}
```

ray));

}
### 3.5静态泛型方法
    在方法前加static 调用时用类名.直接调用 就不用实例化对象
    ```
      public static void main(String[] args) {
            //3.泛型方法
            Integer[] array ={8,15,6,19,77};
            System.out.println(MyArray.<Integer>FindMax(array));
    
    }
    ```




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值