你了解泛型嘛

泛型

为什么要有泛型?

集合容器类在设计阶段/声明阶段不能确定这个容器到底实际存的是什么类型的对象,
所以在JDK1.5之前只能把元素类型设计为Object,JDK1.5之后使用泛型来解决。
因为这个时候除了元素的类型不确定,其他的部分是确定的,例如关于这个元素如何
保存,如何管理等是确定的,因此此时把元素的类设计成一个参数,这个类型参数
叫做泛型。

在这里插入图片描述

什么是泛型

所谓泛型,就是允许在定义类、接口时通过一个标识表示类中某个属性的类
型或者是某个方法的返回值及参数类型。这个类型参数将在使用时( 例如,
继承或实现这个接口,用这个类型声明变量、创建对象时)确定(即传入实
际的类型参数,也称为类型实参)。Collection<E>, List<E>, 
ArrayList<E> 这个<E>就是类型参数,即泛型。

泛型类

class Myclass<T> {
//T代表类型参数,指代任何类型(不包括基本类型8种,要使用其包装类),常用单个大写字母表示,
    private T t;
}
public class Test1 {
    public static void main(String[] args) {
        Myclass<String> myclass1=new Myclass<String>();
        Myclass<Integer> myclass2=new Myclass<Integer>();
    }
}
  • 泛型类可以接受多个类型参数
class Mclass<T,E> {
    private T t;
    private E e;
}
public class Test1 {
    public static void main(String[] args) {
        Mclass<String,Integer> mclass=new Mclass<String, Integer>();
    }
}
  • 引入泛型后,一个泛型类的类型在使用时已经确定好,因此无需向下转型
泛型类的使用-通配符(Wildcards)
? 用于在泛型的使用,即为通配符
public class MyArrayList<E> {...}
// 可以传入任意类型的 MyArrayList
public static void printAll(MyArrayList<?> list) {
...
} /
/ 以下调用都是正确的
printAll(new MyArrayList<String>());
printAll(new MyArrayList<Integer>());
printAll(new MyArrayList<Double>());
printAll(new MyArrayList<Number>());
printAll(new MyArrayList<Object>());
  • 通配符-上界
<? extends 上界>
// 可以传入类型实参是 Number 子类的任意类型的 MyArrayList
public static void printAll(MyArrayList<? extends Number> list) {
...
}
  • 通配符-下界
<? super 下界>
// 可以传入类型实参是 Integer 父类的任意类型的 MyArrayList
public static void printAll(MyArrayList<? super Integer> list) {
...
}

泛型方法

在方法声明时用<T>表示的方法,<T>中的T称为类型参数,而方法中的T被称为参数
化类型,他不是运行时真正的参数
public <T> void fun(T t) {
        System.out.println(t);
    }
     public <T> T test(T t) { //<T>泛型方法的定义,表示该方法为泛型方法。第二个T表示返回类型是T,第三个T表示参数类型是T.
        return t;//类型参数也可以做返回值
    }
  • 当泛型类与泛型方法共存时,泛型方法始终与自己定义的类型为准、定义时让泛型类和泛型方法的类型不同名,来避免混淆
class Myclass2<T> {
    public <T> T func(T t) {
        return t;
    }
}
public class Test1 {
    public static void main(String[] args) {
        Myclass2<String> myclass2=new Myclass2<>();
        System.out.println(myclass2.func(12));
        System.out.println(myclass2.func("123"));
    }
}

泛型接口

interface ISubject<T> {
    void fun(T t);
    
}
  • 子类在实现接口时有两种实现方式
    1)此时子类实现接口时就确定类型
class SujectImpl implements ISubject<String> {
    @Override
    public void fun(String s) {

    }
}

2)子类实现接口时仍然保留泛型

class SubjectImpl2<T> implements ISubject<T> {
    @Override
    public void fun(T t) {

    }
}

类型擦除、

泛型是作用在编译期间的一种机制,实际上运行期间是没有这么多类的,那运行期间
是什么类型呢?这里就是类型擦除在做的事情

jdk 1.5引入 泛型只存在于编译阶段,在进入JVM之前,与泛型有关的信息会被完全擦除 泛型类再进行类型擦除时,未指定泛型的上限,泛型相关信息会被擦除位Object类型,如果有上限,擦除为对应类型的上限。

class Myclass<T,E extends Number> {
      public T t;
      public E e;
}
T>>>Object
E>>>Number

泛型的注意点

  1. 泛型类型参数不支持基本数据类型
  2. 无法实例化泛型类型的对象
  3. 无法使用泛型类型声明静态的属性
  4. 无法使用 instanceof 判断带类型参数的泛型类型
  5. 无法创建泛型类数组
  6. 无法 create、catch、throw 一个泛型类异常(异常不支持泛型)
  7. 泛型类型不是形参一部分,无法重载
  8. 泛型代码与JVM ① 虚拟机中没有泛型,只有普通类和方法。 ② 在编译阶段,所有泛型类的类型参数都会被Object或者它们的限定边界来替换。(类型擦除) ③ 在继承泛型类型的时候,桥方法的合成是为了避免类型变量擦除所带来的多态灾难。 无论我们如何定义一个泛型类型,相应的都会有一个原始类型被自动提供。原始类型的名字就是擦除类型参数的泛型类型的名字。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值