(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);

    }

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

在这里插入图片描述

class MyArray<T>{
    
    
//<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.取出元素的时候不用强转
(编译的时候完成的)=>擦除机制

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

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

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);
    }
}
//传自定义类
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);
    }

在这里插入图片描述

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

public class MyArray<E extends Number> {
    
    
//擦除成Number
...
}

只接受 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); //<Integer>可以省略,编译器可以根据传入的arr类型进行推导
        System.out.println(ret);
    }
}

通配符

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); 无法修改!
        }

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

通配符上界

在这里插入图片描述

<? extends Number>//可以传入的实参类型是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();
    }

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

通配符下界

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

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

装箱和拆箱

装箱

基本类型->包装类型

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

拆箱

包装类型->基本类型

Integer a=10;
int b=a;
int c=a.intValue();
Integer a = 127;
Integer b = 127;
Integer c = 128;
Integer d = 128;
System.out.println(a == b);
System.out.println(c == d);
//true
//false

装箱会调用valueOf方法

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_63983125/article/details/126906421
今日推荐