Java泛型

本文围绕Java泛型展开,介绍了泛型允许在强类型语言中使用后续指定的类型。阐述了泛型的分类,包括接口、类和方法。还讲解了泛型擦除,即编译后泛型信息被清除,以及擦除的边界。此外,提到泛型与桥接方法的关系,最后指出泛型带来的不支持基本类型、影响重载等问题。

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

java泛型

最近在看hollis的书,对java的泛型好像有了更加深刻的认识。所以特意记录一下。
泛型允许程序员在强类型程序设计语言中编写代码时使用一些以后才指定的类型,在实例化的时候作为参数指明这些类型。

泛型分类和表示

  • 泛型接口 public interface className<类型名称>{} 如 public interface Iterable<T>
  • 泛型类 public class 类名称<类型参数>{} 如 public class ArrayList<E> {}
  • 泛型方法 public <类型参数> 返回值类型 方法名(参数类型,参数列表) 如 public <T> T[] toArray(T[] a){}

泛型擦除

在java语言中,不同的泛型类,经过jvm编译以后,会当成同一个类进行处理。所以,泛型技术实际上是Java语言的语法糖,因为泛型经过编译器处理之后就被擦除了,编译器根本不认识泛型。这个擦除的过程叫做类型擦除,指的是,通过类型参数合并,将泛型类型实例关联到同一份字节码上。编译器只为泛型类型生成一份字节码,并且将其实例关联到这份字节码上。类型擦除的关键在于从泛型类型中清除类型参数的相关信息,并且在必要时添加类型检查和类型转换的方法。

泛型擦除的边界

  • 将所有的泛型参数用其最左边界(顶级的父类型)类型进行替换。
  • 移除所有的类型参数。

泛型与桥接方法

那么简单粗暴的把泛型的信息去掉,会不会有影响呢。


public interface Parent <T>{
    public void set(T t);
}
public class Child implements Parent<String>{
    @Override
    public void set(String s) {
        System.out.println("test");
    }
}

因为存在泛型擦除,那么父类的set(T t)就会变为 set(Object o); 而子类中的set(String s) 和父类就不满足重写关系了, 而是 重载(传入参数不同)。对于这个,JVM的解决方案是 在 子类中生成一个 set(Object o)方法,然后在该方法中调用 set(String s)

泛型带来的问题

  • 泛型不支持基本数据类型
  • 泛型会影响重载 即 public void test(List<String>list){}public void test(List<Integer>list) 因为编译后都是public void test(List list)所以这样的重载会导致编译出错;
  • instanceof不能直接用于泛型比较 如if (obj instanceof T)...
  • List<Integer>不是List<Object>的子类,因为经过泛型擦除后,这两个都会变成 List list
  • 泛型中的静态变量只有一份
public class Holder<T>{
  public static int var =0;
}
public class HolderTest{
  public static void main(String[] args){
    Holder<String> holder1 =new Holder<>();
    holder1.var =1;
    Holder<Integer>holder2 =new Holder<>();
    holder2.var =2;
    System.out.println(holder1.var);
  }
}

这个编译后的结果为2;因为经过泛型擦除,所有的泛型类都指向同一份字节码上。泛型类的所有静态变量是共享的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值