泛型的使用

发布时间:2023年12月28日

泛型

泛型的概念

Java泛型是一种在编译时期进行类型检查和类型安全的机制,它可以让我们在编写代码时指定参数或返回值的类型,从而提高代码的可读性和可维护性。

孩童的智商可能还不足以理解泛型的具体概念和实现细节,但是我们可以通过类比的方式来帮助他们理解。

可以将泛型比喻为一个容器,这个容器可以存放不同类型的对象。就像一个玩具箱,可以放入不同种类的玩具,但是每个玩具都有自己的特点和功能。

孩童可以将泛型看作是一个多功能的盒子,可以根据需要放入不同类型的对象。比如,可以有一个盒子专门放玩具车,另一个盒子专门放娃娃。这样,当孩童需要玩具车时,就可以从玩具车盒子中取出玩具车,而不会取出其他类型的玩具。

在Java中,泛型的使用方式类似于上面的例子。我们可以定义一个泛型类或泛型方法,然后在使用时指定具体的类型。这样,编译器会在编译时期进行类型检查,确保我们只能使用指定类型的对象。

例如,我们可以定义一个泛型类Box,用来存放不同类型的对象:

public class Box<T> {
    private T item;

    public void setItem(T item) {
        this.item = item;
    }

    public T getItem() {
        return item;
    }
}

然后,孩童可以将Box看作是一个玩具箱,可以放入不同类型的玩具:

Box<Car> carBox = new Box<>();
carBox.setItem(new Car());

Box<Doll> dollBox = new Box<>();
dollBox.setItem(new Doll());

在上面的例子中,carBox是一个Box对象,它只能存放Car类型的对象;dollBox是另一个Box对象,它只能存放Doll类型的对象。这样,孩童就可以根据需要选择不同类型的玩具箱,并确保只能取出相应类型的玩具。

通过这种类比的方式,孩童可以初步理解Java泛型的概念和用法,尽管可能还不完全理解其中的技术细节。随着孩童的成长和学习,他们可以逐渐深入理解泛型的原理和更复杂的用法。

泛型的格式

  • <类型>:指定一种类型的格式,这里的类型可以看成是形参

  • <类型1, 类型2……>:指定多种类型的格式,多种类型之间用逗号隔开。这里的类型可以看成是形参

  • 将来具体调用时,给定的类型可以看成是实参,并且实参的类型只能是引用数据类型

泛型的好处

  • 把运行时期的问题提到了编译期间

  • 避免了强制数据类型转换的问题

泛型类的定义和使用

  • 泛型类的定义格式

    • 格式:修饰符 class 类名<类型>{}

    • 范例:public class Generic<T>{}

      此处 T 可以是任意标识符,常见的有 T、E、K、V 等形式的参数,常用于表示泛型

demo:

创建一个泛型类

package com.itxiaosi.demo01;

/**
 * @Classname : Generic
 * @Description : TODO 泛型类
 * @Author : lin_refuel@qq.com
 */
public class Generic<T> {
    private T t;

    public T getT() {
        return t;
    }

    public void setT(T t) {
        this.t = t;
    }
}

定义一个学生类

package com.itxiaosi.demo01;

/**
 * @Classname : Student
 * @Description : TODO 学生类
 * @Author : lin_refuel@qq.com
 */
public class Student {
    //学生类的两个基本属性
    private String name; //姓名
    private int age; // 年龄

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

测试泛型类

package com.itxiaosi.demo01;

/**
 * @Classname : GenericTest
 * @Description : TODO 泛型类测试
 * @Author : lin_refuel@qq.com
 */
public class GenericTest {
    public static void main(String[] args) {
        //TODO 泛型括号里面的类型必须是引用数据类型
        //1.String类型放入
        Generic<String> strG = new Generic<>();
        strG.setT("我是一个字符串");
        String str = strG.getT();
        System.out.println(str); // 我是一个字符串
        System.out.println("====================");
        //2.Integer类型放入
        Generic<Integer> intG = new Generic<>();
        intG.setT(9527);
        Integer interG = intG.getT();
        System.out.println(interG); // 9527
        System.out.println("===================");
        //3.定义的学生类放入
        Generic<Student> StuG = new Generic<>();
        StuG.setT(new Student("小肆",20));
        Student Stud = StuG.getT();
        System.out.println(Stud);
    }
}

运行结果:
在这里插入图片描述

泛型方法

  • 泛型方法的定义格式

    • 格式:修饰符 <类型> 返回值类型 方法名(类型名 变量名){}

    • 范例:public <T> void show(T t)

个人理解泛型方法,可以避免同一个方法多次重载

package com.itxiaosi.demo02;

/**
 * @Classname : Generic
 * @Description : TODO 泛型方法
 * @Author : lin_refuel@qq.com
 */
public class Generic {
    //泛型方法
    public <T> void show(T t){
        System.out.println(t);
    }
}

泛型方法测试

package com.itxiaosi.demo02;

import com.itxiaosi.demo01.Student;

/**
 * @Classname : GenericTest
 * @Description : TODO 泛型方法测试类
 * @Author : lin_refuel@qq.com
 */
public class GenericTest {
    public static void main(String[] args) {
        Generic Gen = new Generic();
        Gen.show("莲");
        Gen.show(1231);
        Gen.show(new Student("小肆",12));
    }
}

运行结果:
在这里插入图片描述

泛型接口

  • 泛型接口的定义格式

    • 格式:修饰符 interface 接口名<类型>{}

    • 范例:public interface Generic<T>{}

demo:
在这里插入图片描述

泛型接口实现类

在这里插入图片描述

泛型接口测试

在这里插入图片描述

运行结果
在这里插入图片描述

泛型通配符

为了表示各种泛型 List 的父类,可以使用类型通配符

  • 类型通配符:<?>

  • List<?> :表示类型未知的 List,它的元素可以匹配 任意类型

  • 这种带通配符的 List 仅表示它是 各种泛型 List 的父类,并不能把元素添加到其中

如果说我们不希望 List<?> 是任何泛型 List 的父类, 只希望他代表某一泛型 List 的父类,可以使用类型通配符的上限

  • 类型通配符上限:<? extends 类型>

  • List<? extends Number> :它表示类型是 Number 或者其子类型

除了可以指定类型通配符的上限,我们还可以指定类型通配符的下限

  • 类型通配符的下限:<? super 类型>

  • List<? super Number> :它表示的类型是 Number 或者其父类型

可以理解为泛型限制符,不能随意写入

package com.itxiaosi.demo04;

import com.itxiaosi.demo01.Student;

import java.util.ArrayList;
import java.util.List;

/**
 * @Classname : demo01
 * @Description : TODO 泛型通配符(泛型的限制)
 * @Author : lin_refuel@qq.com
 */
public class demo01 {
    public static void main(String[] args) {
        //<?> : 尖括号里面的?等同于是 Object ,是所有类的父类,可以随意写入
        List<?> list = new ArrayList<Object>();
        //可以随意放入其他引用数据类型
        List<?> list01 = new ArrayList<Integer>();
        List<?> list02 = new ArrayList<String>();
        List<?> list03 = new ArrayList<Student>();
        //****************************************************
        //<? extends> // 表示继承的上限例如 <? extends Number> 写入泛型只能写入 Number和继承Number的子类
        List<? extends Number> list07 = new ArrayList<Number>();
        List<? extends Number> list04 = new ArrayList<Integer>();
        List<? extends Number> list05 = new ArrayList<Float>();
        List<? extends Number> list06 = new ArrayList<Double>();
        //例如:写入一个没有继承Number的类或者Number的类则是超过上限,出现异常
       // List<? extends Number> list08 = new ArrayList<Object>();
       // List<? extends Number> list08 = new ArrayList<Student>();
       //********************************************************
        //<? super>//表示泛型的下限,例如 <? super Number> 可以写入 Number和Number的父类,不能写入Number的子类
         List<? super Number> list09 = new ArrayList<Object>();
         List<? super Number> list10 = new ArrayList<Number>();
         // Integer是Number的子类,超过了Number的下限,
        // List<? super Number> list11 = new ArrayList<Integer>();
    }
}

可变的参数

可变参数有称为参数个数可变,用作方法的参数出现,那么方法参数的可数就是可变的

  • 格式:修饰符 返回值类型 方法名(数据类型...变量名)

  • 范例:public static int sum(int...a)

注意:

  • 可变参数实际上是一个数组

  • 如果普通参数和可变参数结合使用的话,可变参数需要放到形参列表的最后

demo

package com.itxiaosi.demo05;

/**
 * @Classname : demo01
 * @Description : TODO 可变长的参数
 * @Author : lin_refuel@qq.com
 */
public class demo01 {
    public static void main(String[] args) {
        // 定义一个两个数相加方法,输出两个数的相加后的值
        System.out.println(Myadd(1,2));
        //TODO 通过可变长参数实现
        System.out.println(Myadd2(1,2,3,4,5,6));
    }

    /**
     *  可变长参数的使用
     * @param a 可变长的参数
     * @return 结果
     */
    private static int Myadd2(int ...a) {
        int sum = 0;
        for(int i : a){
            sum+=i;
        }
        return sum;
    }
    /**
     * 两个数相加
     * @param a 第一个数
     * @param b 第二个数
     * @return 结果
     */
    private static int Myadd(int a, int b) {
        return a+b;
    }
}

可变长参数的使用

所属类方法名说明
Arrayspublic static <T> List <T> asList(T...a)返回由可变长组成的固定大小的列表
Listpublic static <E> List <E> of(E...e)返回包含任意数量元素的不可变列表
Setpublic static <E> Set <E> of(E...e)返回一个包含任意数量元素的不可变集合

list.of和Set.of是jdk9之后才有

demo:

package com.itxiaosi.demo05;

import java.util.Arrays;
import java.util.List;

/**
 * @Classname : demo02
 * @Description : TODO 可变参数的使用
 * @Author : lin_refuel@qq.com
 */
public class demo02 {
    public static void main(String[] args) {
        // 调用方法 aslist(可变参数)
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5); // 返回的是一个list集合
        System.out.println(list); // 1,2,3,4,5
        // *************************************
        // asList返回的集合是否可以进行 TODO 删除,增加,修改
      //  list.add(6);//不能增加
       // list.remove(2);//不能删除一个值
        list.set(2,1314);// 可以修改里面的值
        System.out.println(list);
    }
}
文章来源:https://blog.csdn.net/2301_81153022/article/details/135245899
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。