JAVA学习-泛型

什么是泛型?

        定义类、接口、方法时,同时声明了一个或者多个类型变量(如:ArrayList<E>、HashMap<K,V>),称为泛型 类、泛型接口,泛型方法、它们统称为泛型。

        作用:

                泛型提供了在编译阶段约束所能操作的数据类型,并自动进行检查的能力!

        原理:

                使用泛型时会用具体的数据类型替代泛型变量

泛型类、接口的写法:

 
public class ArrayList<E>{
     . . .
}

public interface Comparator<E>{
     . . .
}

        注意:类型变量建议用大写的英文字母,常用的有:E、T、K、V 等

泛型方法的写法:

public static <T> void test(T t){

}

        案例:打印任意类型的数组

                要求: 1. 在测试类中,定义一个printArr方法

                            2. 该方法可以打印任意数据类型的数组

                            3. 要求使用泛型来代表该方法支持的数据类型

/*
 * 测试利用泛型打印任意类型数组
 */
public class printArrTest {

    public static void main(String[] args) {
        String[] arr = {"a","b","c"};
        printArr(arr);

        //泛型不支持基本数据类型
//        int[] arr1 = {1,2,3};
//        printArr(arr1);
        System.out.println(" ");

        //泛型支持包装类
        Integer[] arr1 = {1,2,3};
        printArr(arr1);
    }

    // 泛型方法
    public static <T> void printArr(T[] arr){
        //遍历数组
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }

}

案例:自定义MyArrayList类,模拟ArrayList的增删改成方法

        要求:

        1.自定义一个类MyArrayList,使用泛型限定它能处理的数据类型,在该类中,添加add remove set get方法,方法内的逻辑可以忽略

import java.util.ArrayList;

/*
 * 泛型演示
 */
public class MyArrayList<E>{

    private ArrayList<E> list = new ArrayList<>();

    public void add(E e){
        list.add(e);
        System.out.println("添加成功");
    }
    public void remove(int index){
        list.remove(index);
        System.out.println("删除成功");
    }
    public void set(int index, E e){
        list.set(index, e);
        System.out.println("修改成功");
    }
    public E get(int index){
        if(list.get(index) == null){
            System.out.println("查询失败");
            return null;
        }
        System.out.println("查询成功");
        return list.get(index);
    }
}

        2.定义测试类,创建MyArrayList时,给泛型变量传入具体的数据类型,调用四个模拟方法

import java.util.ArrayList;

public class MyArrayListTest {
    public static void main(String[] args) {

        test1();
        System.out.println("--------------------------");
        test2();
    }
    public static void test1(){
        //创建集合
        MyArrayList list1 = new MyArrayList();
        list1.add("张三");
        list1.add(123);
        list1.add(true);


        list1.remove(1);

        list1.set(1,"王二");

        System.out.println(list1.get(1));

        //泛型, 指定集合中存储的数据类型为 String
        MyArrayList<String> list2 = new MyArrayList<>();
        list2.add("李四");
//        list2.add(123);
//        list2.add(true);
    }
    public static void test2(){
        // 创建集合, 指定集合中存储的数据类型为 String
        ArrayList<String> list1 = new ArrayList<>();
        list1.add("张三");
        list1.add("李四");
        list1.add("王五");
        list1.add("赵六");

        //遍历集合
        list1.forEach(s -> System.out.print(" "+s));

        System.out.println(" ");
        System.out.println("------------------------------");

        //删除集合
        list1.remove(2);
        list1.forEach(s -> System.out.print(" "+s));

        System.out.println(" ");
        System.out.println("------------------------------");

        //修改集合
        list1.set(0,"Hello world");
        list1.forEach(s -> System.out.print(" "+s));

        System.out.println(" ");
        System.out.println("------------------------------");

        //获取集合中的数据
        System.out.println(list1.get(0));
        System.out.println(list1.get(1));

    }
}

通配符和上下限:

        通配符 :就是 “?” ,可以在“使用泛型”的时候代表一切类型; E T K V 是在定义泛型的时候使用。

        泛型的上下限:

                泛型上限: : ? 代表能接收的必须是Car或者其子类 。

                泛型下限: : ? 代表能接收的必须是Car或者其父类。

        案例: 要求:

                1. 定义一个方法printList,该方法的形参可以接收Animal类型的集合

                2. 测试,当有Animal的子类Dog、Cat的集合时,是否可以调用该方法,如果不能调用那么该方法该如何修改?

        首先定义Animal及其子类Dog、Cat。


//Animal类
public class Animal {
    public void s(){
        System.out.println("动物叫");
    }
}


//Dog类
public class Dog extends Animal{
    public void s()
    {
        System.out.println("汪汪汪");
    }
}

//Cat类
public class Cat extends Animal{
    public void s() {
        System.out.println("喵喵喵");
    }
}

        测试代码:

import java.util.ArrayList;
import java.util.List;
/*
 * 泛型通配符
 */
public class AnimalListTest {

    public static void main(String[] args) {

        // 创建集合猫
        List<Cat> list1 = new ArrayList<>();
        list1.add(new Cat());
        list1.add(new Cat());
        list1.add(new Cat());

        // 创建集合狗
        List<Dog> list2 = new ArrayList<>();
        list2.add(new Dog());
        list2.add(new Dog());
        list2.add(new Dog());

        // 创建集合动物
        List<Animal> list3 = new ArrayList<>();
        list3.add(new Animal());
        list3.add(new Animal());
        list3.add(new Animal());

        System.out.println("泛型上限:");
        printList(list1);
        System.out.println("--------------------------------");
        printList(list2);
        System.out.println("--------------------------------");
        printList(list3);

        System.out.println("--------------------------------");
        System.out.println("泛型下限:");
        printList1(list1);
        System.out.println("--------------------------------");
        printList1(list3);

    }

    // 泛型上限通配符 ? extends Animal
    // 泛型通配符上限,表示只能是Animal或者Animal的子类
    public static void printList(List<? extends Animal> list){
        //遍历集合
        for (int i = 0; i < list.size(); i++) {
            Animal animal = list.get(i);
            animal.s();
        }
    }

    // 泛型下限通配符 ? super Cat
    // 泛型通配符下限,表示只能是Cat或者Cat的父类
    public static void printList1(List<? super Cat> list){
        //遍历集合
        for (int i = 0; i < list.size(); i++) {
            Animal animal = (Animal)list.get(i);
            animal.s();
        }
    }

}

        输出结果:

泛型上限:
喵喵喵
喵喵喵
喵喵喵
--------------------------------
汪汪汪
汪汪汪
汪汪汪
--------------------------------
动物叫
动物叫
动物叫
--------------------------------
泛型下限:
喵喵喵
喵喵喵
喵喵喵
--------------------------------
动物叫
动物叫
动物叫

Process finished with exit code 0

包装类:

        因为泛型不支持基本数据类型,只能支持对象类型(引用数据类型)。

        为什么不支持基本数据类型?

                泛型是jdk1.5推出的新特性,在JVM运行前会进行泛型擦除,将所有泛型都替换为Object

        什么是包装类?

                包装类就是把基本类型的数据包装成对象的类型,这个过程一般是自动的。

基本数据类型对应的包装类分别是:

基本数据类型 对应的包装类(引用数据类型)

byte          Byte

short         Short

int           Integer

long          Long

char          Character

float         Float

double        Double

boolean       Boolean

        自动装箱:基本数据类型可以自动转换为包装类型。 

        自动拆箱:包装类型可以自动转换为基本数据类型。

包装类具备的其他功能:

        可以把基本类型的数据转换成字符串类型。

public static String toString(double d) 

public String toString()

        可以把字符串类型的数值转换成数值本身对应的真实数据类型。

public static int parseInt(String s) 

public static Integer valueOf(String s)

案例

        自动装箱范围在 -128~127 之间

                在 : 不会创建新的对象, 而是从底层数组中直接获取

                不在 : 重新 new 出新的 Integer对象

public class IntegerDemo {
    public static void main(String[] args) {
        // -128~127缓存范围内的数字,使用同一个对象
        Integer i1 = 127;
        Integer i2 = 127;

        // -128~127缓存范围外,创建新的对象
        Integer i3 = 128;
        Integer i4 = 128;

        //比较的是地址
        System.out.println(i1 == i2);
        System.out.println(i3 == i4);

    }
}

-----------------------

true
false

#学无止尽    #记录并分享我的学习日常

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南枫知我意~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值