泛型的自定义和通配符

本文详细介绍了Java中的泛型,包括自定义泛型类、泛型接口、泛型方法的使用,以及泛型的继承、通配符的规则。通过示例代码展示了如何在类、接口和方法中应用泛型,并给出了泛型类DAO的实现,以及相关的单元测试。此外,还涉及到了泛型在集合操作中的应用,如List的泛型限定。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

自定义泛型类

基本语法 class类名<T, R...>{.….表示可以有多个泛型成员 }

注意细节

1)普通成员可以使用泛型(属性、方法)

2)使用泛型的数组,不能初始化

3)静态方法中不能使用类的泛型

4)泛型类的类型,是在创建对象时确定的(因为创建对象时,需要指定确定类型)

5)如果在创建对象时,没有指定类型,默认为Object

class Tiger<E,M,H>{
    //1.该类就称为自定义泛型类;
    //2.E,M,H就是泛型的标识符 ,
    //3.一般情况下是大写的字母
    //4.泛型标识符可以有多个
​
    //5.普通成员可以使用泛型(属性和方法)
    E e;
    M m;
    H h;
    public H play(){
        return h;
    };
    //6.使用泛型的数组,不能初始化(因为最开始并不知道数组是什么类型的,且不知道该开多大的空间)
    //E arr[] = new E[8];  错
    E arr[];
​
    //7.静态的属性和方法不能使用
    //  (因为静态是和类相关的,在类加载时,对象还没有创建,
    // 泛型是在类创建的时候或定义的才会指定的);
    //  static M k;  错
    //public static E what(){}; 错
}

自定义泛型接口

基本语法 interface 接口名 <T,R.…>{ }

注意细节

1)接口中,静态成员也不能使用泛型(这个和泛型类规定一样)

2)泛型接口的类型,在继承接口或者实现接口时确定

3)没有指定类型,默认为Object

//接口USB 泛型E,T
interface USB <E,T>{
    //E e; 错;(因为在接口中成员是静态的)
    E get();
    void hi(T t);
    void sun(E e,T t);
    default T fun(){
        return null;
    }
}
​
//接口u_USB继承USB接口
interface u_USB extends USB<String,Integer>{};
​
//类Play去实现接口u_USB
/*1.当我们实现u_USB接口时,因为u_USB继承了USB接口,指定E 为String T 为Integer
* 2.在实现USB接口的方法时,使用String替换E ,使用 Integer替换 T
* */
class Play implements u_USB{
​
    //实现该接口就必须实现该接口中的所有抽象方法
    @Override
    public String get() {
        return null;
    }
​
    @Override
    public void hi(Integer integer) {
​
    }
​
    @Override
    public void sun(String s, Integer integer) {
​
    }
}
​
/*1.实现接口时,直接指定泛型接口的类型
* 2.E 指定了Double ,T 指定了Float
* 3.在实现USB接口的方法时,使用Double替换E ,使用 Float替换 T
* */
class Dog implements USB<Double,Float>{
​
    @Override
    public Double get() {
        return null;
    }
​
    @Override
    public void hi(Float aFloat) {
​
    }
​
    @Override
    public void sun(Double aDouble, Float aFloat) {
​
    }
}

自定义泛型方法

基本语法 修饰符<T,R.>返回类型方法名(参数列表){ }

注意细节

1.泛型方法,可以定义在普通类中,也可以定义在泛型类 中

2.当泛型方法被调用时,类型会确定

  1. public void eat(E e){},修饰符后没有<T,R..> eat 方法不是泛型方法,而是使用了泛型

    public static void main(String[] args) {
    ​
        Car car = new Car();
        //当调用方法时,传入参数,编译器就会确定类型
        car.Moon("棒棒糖 ",2.5);
    ​
    }
//泛型方法,可以定义在普通类中,也可以定义在泛型中
class Car{//普通类
    public void sun(){//普通方法
    }
​
    //泛型方法
    //<E,T>是泛型;并且是提供给Moon方法使用的
    public <E,T> void Moon(E e,T t){//泛型方法
    }
​
}
​
class Food<E,T>{
    public void fish(){//普通方法
    }
​
    public <M,N> void Pig(M m ,N n){//泛型方法
    }
​
    //fun()方法不是泛型方法;是fun()方法使用了类声明的泛型
    public void fun(T t){};
​
    //泛型方法,既可以使用类声明的泛型,也可以使用自己声明的泛型
    public <H> void duck(E e,H h){}
}

泛型继承和通配符

1)泛型不具备继承性 List<Object> list = new ArrayList<String>0);//错

2)<?>:支持任意泛型类型

3)<? extends A>:支持A类以及A类的子类,规定了泛型的上限

4)<? super A>:支持A类以及A类的父类,不限于直接父类,规定了泛型的下限

public static void main(String[] args) {
​
    List<Object> list01 = new ArrayList<>();
    List<String> list02 = new ArrayList<>();
    List<AA>     list03 = new ArrayList<>();
    List<BB>     list04 = new ArrayList<>();
    List<CC>     list05 = new ArrayList<>();
​
    //1.如果是List<?> c 可以接收任意的泛型类型的
    printCollection01(list01);//Object
    printCollection01(list02);//String
    printCollection01(list03);//AA
    printCollection01(list04);//BB
    printCollection01(list05);//CC
​
    //2.? extends AA 表示:上限 ; 可以接收 AA 或者 AA的子类
    printCollection02(list03);//AA
    printCollection02(list04);//BB
    printCollection02(list05);//CC
​
    //3.? super AA 表示:下限 ; 支持AA类以及AA类的父类,不限于直接父类
    printCollection03(list01);//Object
    printCollection03(list03);//AA
​
}
//1.List<?> 表示 任意的泛型类型都可以接收
public static void printCollection01(List<?> c){
    for(Object object :c){
        System.out.println(object);
    }
}
​
//2. ? extends AA 表示:上限 ; 可以接收 AA 或者 AA的子类
public static void printCollection02(List<? extends AA> c){
    for(Object object :c){
        System.out.println(object);
    }
}
​
//3. ? super AA 表示:下限 ; 支持AA类以及AA类的父类,不限于直接父类
public static void printCollection03(List<? super AA> c){
    for(Object object :c){
        System.out.println(object);
    }
}
//定义三个类,并继承
class AA {}
class BB extends AA{}
class CC extends BB{}

泛型练习题

public static void main(String[] args) {
​
    /*
      1.编程题Homework01.java
      定义个泛型类 DAO<T>,在其中定义一个Map 成员变量,Map 的键为String类型,值为T类型。
      分别创建以下方法:
     (1) public void save(String id,T entity):保存T类型的对象到 Map成员变量中
     (2) public T get(String id):从 map中获取id对应的对象
     (3) public void update(String id,T entity):替换map 中key为id的内容,改为entity对象
     (4) public List<T> list():返回map中存放的所有T对象
     (5) public void delete(String id):删除指定id对象
     定义一个 User 类:
     该类包含: private成员变量 (int类型)id, age; (String 类型)name
     创建 DAO类的对象,分别调用其save、get、update、list、delete方法来操作User对象,
     使用Junit单元测试类进行测试。
    * */
​
}
​
/*1.创建test方法来测试;
 * 2.分别调用其save、get、update、list、delete方法来操作User对象,
 * 3.使用Junit单元测试类进行测试。
 * */
​
@Test
public void test(){
​
    //将类实例化
    DAO<User> dao = new DAO<>();
    //给dao类添加元素
    dao.save("0001",new User(1,15,"张三"));
    dao.save("0010",new User(2,18,"李四"));
    dao.save("0011",new User(3,22,"王五"));
​
    //返回dao中元素
    List<User> userList = dao.list();
    System.out.println("userList:" + userList);
   /* userList:[
    3  22 王五,
    1  15 张三,
    2  18 李四]*/
​
    //修改0001中的元素,为 4,5,"旺财"
    System.out.println("======修改后============");
    dao.update("0001",new User(4,5,"旺财"));
    List<User> userList02 = dao.list();
    System.out.println("userList:" + userList02);
   /* userList:[
            3  22 王五,
            4  5  旺财,
            2  18 李四]*/
​
    //获得00011中的对象
    System.out.println("====================");
    System.out.println(dao.get("0011"));
    //  3  22 王五
​
}
/*定义一个 User 类:
* 该类包含: private成员变量 (int类型)id, age; (String 类型)name
**/
@SuppressWarnings("all")
class User{
    private int id;
    private int age;
    private String name;
​
    public User(int id, int age, String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }
​
    public int getId() {
        return id;
    }
​
    public void setId(int id) {
        this.id = id;
    }
​
    public int getAge() {
        return age;
    }
​
    public void setAge(int age) {
        this.age = age;
    }
​
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    @Override
    public String toString() {
        return "\n" + id + "\t" + age + "\t" + name ;
    }
}
​
//创建 DAO类的对象,分别调用其save、get、update、list、delete方法来操作User对象,
/*定义个泛型类 DAO<T>,在其中定义一个Map 成员变量,Map 的键为String类型,值为T类型。
*/
​
//创建泛型类
@SuppressWarnings("all")
class DAO<T>{
    //map(HashMap)集合,来接收键值数据
    private Map<String ,T> map = new HashMap<>();
​
    //(1) public void save(String id,T entity):保存T类型的对象到 Map成员变量中
    public void save(String id,T entity){
        map.put(id,entity);
    }
​
    //(2) public T get(String id):从 map中获取id对应的对象
    public T get(String id){
        return map.get(id);
    }
​
    //(3) public void update(String id,T entity):替换map 中key为id的内容,改为entity对象
    public void update(String id,T entity){
        map.put(id,entity);
    }
​
    //(4) public List<T> list():返回map中存放的所有T对象
    public List<T> list(){
        //定义一个list类的ArrayList去接收map值的数据
        List<T> list = new ArrayList<>();
        //调用mao的键
        Set<String> keySet = map.keySet();
        //遍历map
        for (String key :keySet) {
            //将遍历出的每一个键对应的值赋给list集合
            list.add(map.get(key));
        }
        return list;
    }
​
    //(5) public void delete(String id):删除指定id对象
    public void delete(String id){
        map.remove(id);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

&jhan

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

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

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

打赏作者

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

抵扣说明:

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

余额充值