01_泛型

泛型

参数化类型。

在这里插入图片描述

泛型的好处

  • 省去了类型强转的麻烦(比如:Object类、interface接口等都需要类型强转)
  • 运行期遇到的问题转移到了编译期

泛型类

所谓泛型类, 就是把泛型定义在类上

格式

class 类名<泛型类型1,...> {
}

注意事项

  • 默认类型
    • 定义了泛型,但是未写在<>中,会将其直接当做Object使用。
      eg:
// 如果我们有一个使用了泛型写法的地方,  当我们使用这段代码的时候需要传入泛型, 
// 如果没有传, 这个泛型默认为Object类型

Holder2 holder3 = new Holder2(new AutoCar());
Object o = holder3.get();
  • 泛型的使用写法
    eg:
// jdk1.5版本的时候写法: 前后尖括号都要指明类型
User<String> user1 = new User<String>();

// jdk1.7版本的时候, 对jdk1.5写法的简化, 本质上等价的
User<String> user1 = new User<>();
  • 泛型类可以定义多个泛型
    • 可以定义多个泛型,但不建议超过两个
    • 定义多个泛型,使用时,要么全部指定类型,要么全部不指定类型
      eg:
class User<T, E>{
	T data;
	E info;
}

User<int, String> user = new User<>(2024 , "hello");
  • 定义了多个泛型,也可以不使用
    eg:
class User3 <T, E, K> {
    T name;
    E age;
}
  • 泛型标识符

    • 使用单个大写字母。比如:E、T、K、V、R
      • E:element;
      • T:type;
      • K:key;
      • V:value;
      • R:return
  • 泛型必须使用引用类型,不能使用基本类型
    eg:

User<int> user = new User<>(); // 报错: 泛型必须使用引用类型

User<Integer> user = new User<>();
  • 泛型类, 定义了泛型之后, 泛型的作用域

      1. 在自己的类中间,会起作用。但是在子类中,不起作用。
      1. 在自己的类上面(指public class User<T> extends Person<E, E>),就是在自己的类定义这一行,可以使用这个泛型。
  • 泛型在父子继承关系上的表现

    • 如果继承时,未指定父类泛型,则为默认类型。Object
      • class Son1 extends Father{}
    • 如果继承时,指定了父类类型,则为指定类型,无论子类定义泛型与否。
      • class Son2 extends Father<String>{} --> 父类变量类型为String
      • class Son3<E> extends Father<Integer>{} --> 父类变量类型为Integer
    • 如果继承时,传入了子类指定的泛型,则父类与子类变量类型一致
      • class Son4<E> extends Father<E>{}

eg:

public class Father<T> {
    T ft;
}

class Son1 extends Father {

}

class Son2 extends Father<Integer> {

}

class Son3<E> extends Father<String> {

}

class Son4<T> extends Father<T> {

}

class Son5<E> extends Father<E>{

}


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

        // 定义类的时候,没有指定Father的类型,所有默认类型为Object
        Son1 son1 = new Son1();
        Object ft = son1.ft;

        // Son2 定义时,未指定泛型,指定了 Father泛型为Integer,所以ft为Integer
        Son2 son2 = new Son2();
        Integer ft1 = son2.ft;

		// 如果继承时,指定了父类类型,则为指定类型,无论子类定义泛型与否
        Son3<Integer> son3 = new Son3();
        String ft4 = son3.ft;

        // Son4 定义时,指定泛型T,指定了 Father泛型为T,所以ft类型和子类一致
        Son4<Integer> son4 = new Son4<>();
        Integer ft2 = son4.ft;

        // Son5 指定E,表示与符号无关
        Son5<String> son5 = new Son5<>();
        String ft3 = son5.ft;
    }
}

泛型接口

所谓泛型接口, 就是把泛型定义在接口上

格式

interface 接口名<泛型类型1...>

举例


interface Player<T,E> {
    E play(T data);
}


// 在什么时候能指定它的类型?

// 1. 实现接口的时候没有指定类型,则泛型的类型为默认的Object
class YoungPlayer implements Player{

    @Override
    public Object play(Object data) {
        return null;
    }
}

// 2. 如果实现时,指定为什么类型,则是什么类型
class OldPlayer implements Player<String, Integer>{

    @Override
    public Integer play(String data) {
        return null;
    }
}

// 3. 如果子类也有泛型,则与子类一致
class BigPlayer<K,V> implements Player<K,V>{

    @Override
    public V play(K data) {
        return null;
    }
}

eg:


// 转换器的接口,把一个类型转换成另外一个类型
interface Converter<T, R> {
    R converter(T t);
}

public class String2Date implements Converter<String, Date> {

    @Override
    public Date converter(String s) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date parse = null;
        try {
            parse = simpleDateFormat.parse(s);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        return parse;
    }
}


泛型方法

所谓泛型方法, 把泛型定义在方法上

格式

 <泛型类型> 返回类型 方法名(泛型类型...)

eg:

public class Demo {
    public static void main(String[] args) {
        A a = new A();
        Integer t = a.getT(10);
        String s = a.getT("hello");
    }
}

class A{
    <T> T getT(T data){
        return data;
    }
}

注意事项
方法上没有定义泛型,只是使用了泛型,不叫泛型方法。


泛型的通配

(看到源码,能明白含义即可。)

泛型不允许协变, 又想产生类似协变的效果, 又不想引入协变带来的问题(类型不匹配问题)

协变与逆变

  • 协变就是,允许接收该类及该类的子类
    • 数组是支持协变的。
  • 逆变就是,允许接收该类及该类的父类

格式

  • 泛型通配符<?>
    • 任意类型,如果没有明确,那么就是Object以及任意的Java类了
    • public void print(User<?> user)
  • ? extends E
    • 向下限定,E及其子类
    • public void print(User<? extends Number> user)
  • ? super E
    • 向上限定,E及其父类

泛型的擦除

  • Java中的泛型并不是真的泛型, Java的泛型只存在于编译之前
  • 当Java中的泛型编译之后, 会把泛型编译成Object以及类型强转

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

coo1heisenberg

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

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

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

打赏作者

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

抵扣说明:

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

余额充值