第九章 泛型

泛型背景

  • Java集合会忘记元素的数据类型,再次取出对象时编译类型会变成Object
  • 集合对元素类型没有限制,可能会导致异常,丢失了对象的状态信息,取出后需要强制类型转换
  • Java5引入参数化类型的概念,允许程序在创建集合时指定集合元素的泪洗过,这种参数化类型被成为泛型,使集合记住元素的类型
  • Java7允许构造器后不需要带完整的泛型信息Map<String, Integer> scores = new HashMap<>();菱形语法

泛型类、接口

  • 泛型就是允许在定义类、接口、方法时使用类型形参,这个类型形参在声明变量、创建对象、调用方法时动态指定
  • 任何类、接口都可以增加泛型声明,加了泛型声明的类在创建对象时传入一个类型实参,看起来是生成了无数多个逻辑上的子类,但并不存在
  • 创建带泛型声明的类时,构造器名还是原来的类名,不要增加泛型声明
  • 实现或继承带有泛型声明的接口和类时,使用接口和类时不能包含类型形参,必须传入实际类型或不传入实际类型不带泛型声明,后者会有警告
public class A extends Apple<T>{}//错
public class A extends Apple<String>{}//对
public class A extends Apple{}//对
  • 从传入实际类型的类派生子类需要替换所有类型形参为实际类型,当需要调用父类方法时,要重写父类方法,替换所有类型形参
  • 不存在泛型类,不管为泛型传入哪一种类型实参,都会当成同一个类处理,在内存中只占用一块内存空间
  • 静态方法、静态初始化块、静态变量的声明和初始化中不允许使用类型形参,instanceof运算符后也不能使用泛型类因为不是真正的类

类型通配符

  • 如果F使B的子类型,G是具有泛型声明的类或接口,G<F>不是G<B>的子类型,不允许G<F>对象赋值给G<B>变量
  • List<?>表示它是各种泛型List的父类,并不能把元素加入到其中因为不能确定集合中元素的类型,add()有类型参数作为集合元素类型,所以传给add()的参数必须是其对象或其子类的对象,但不能确定是什么类型
  • get()返回一个未知类型但总是一个Object,可以赋值给Object类型的变量
  • 只希望代表某一类泛型的父类可以设定类型通配符的上限List<? extends Shape>
  • 同样可以设定类型形参的上限public class Apple<T extends Number>,Apple类的类型形参T传入的实际类型参数只能是Number或Number的子类,多个上限(至多一个父类继承上限,可以有多个接口实现上限)public class Apple<T extends Number & java.io.Serializable>
  • 给类型形参设置多个上限时接口要位于类上限之后

泛型方法

  • Java5提供了对泛型方法的支持,static <T> void f (T[] a, Collection<T> c)
  • 调用泛型方法时无需显式传入实际类型参数,编译器能根据方法实参推断类型参数,但是不能不顾及类型地乱传参数,会编译错误
  • 大多情况下都可以使用泛型方法来代替类型通配符
  • 当类型形参只使用了一次,且唯一效果是在不同的调用点传入不同的实际类型,此时应该使用通配符。
  • 如果泛型方法的类型形参没有表示一个或多个参数之间的类型依赖关系或方法返回值与参数之间的依赖关系,就不该使用泛型方法
  • 允许在构造方法的签名中声明类型形参,产生所谓泛型构造器
  • 定义泛型构造器后,就可以显式地为构造器中的类型形参指定实际类型
public <T> f(T t){}//泛型构造器
...
new f("aaa");//隐式指定类型参数的实际类型
new <String>f("aaa");//显示指定类型参数的实际类型
  • 如果程序显式指定了类型形参的实际类型,则不可用菱形语法
new f<>(5);  //正确
new <String>f<String>("aaa");  //正确
new <String>f<>("aaa");  //编译错误
  • 通配符下限<? super T>,这个通配符表示是T本身或是T的父类
  • public static <T> void copy(Collection<T>dest, Collection<? extends T> src){...}
    public static <T> void copy(Collection<? super T>dest, Collection<T> src){...}同时定义不会发生错误,但是copy(dest, src);调用时会发生编译错误,编译器无法确定调用哪个copy()方法
  • Java8改进类型推断,可以通过返回值和参数推断类型参数的实际类型
  • 但是泛型推断不是万能的有些还是推断不出

擦除和转换

  • 如果没有为泛型类指定实际的类型参数,则把该类型参数称作raw tyoe原始类型,默认时声明该类型参数时制定的第一个上限类型
  • 把一个具有泛型信息的对象赋值给一个没有泛型信息的变量时,泛型信息会被擦出。对于集合,检查类型全部变成类型参数的上限。
  • 可以把Xxx对象直接赋值给一个Xxx<Xxx>变量,编译器仅提示未经检查的转换,但是当把变量集合中的元素当作Xxx取出时会运行异常

泛型与数组

  • 数组元素的类型不能包含类型变量或类型形参,除非是无上限的类型通配符,但可以声明元素类型包含类型变量或类型形参的数组
  • 可以将正常数组对象赋值给泛型数组声明变量,会出现编译警告,完全可能再出现异常
  • 允许创建无上限的通配符泛型数组,此时再强制类型转换时需要用instanceof运算符保证数据类型,但是哟与类型变量再运行时并不存在,无法确定实际类型,所以编译器会再报错
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,128评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,316评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,737评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,283评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,384评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,458评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,467评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,251评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,688评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,980评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,155评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,818评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,492评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,142评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,382评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,020评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,044评论 2 352

推荐阅读更多精彩内容

  • 写在开头:本人打算开始写一个Kotlin系列的教程,一是使自己记忆和理解的更加深刻,二是可以分享给同样想学习Kot...
    胡奚冰阅读 1,427评论 1 3
  • 14.1 泛型与集合 JDK1.5增加了泛型支持。增加泛型后的集合,可以让代码更加简洁,程序更加健壮。Ja...
    王毅巽阅读 531评论 0 0
  • object 变量可指向任何类的实例,这让你能够创建可对任何数据类型进程处理的类。然而,这种方法存在几个严重的问题...
    CarlDonitz阅读 912评论 0 5
  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy阅读 9,514评论 1 51
  • 国庆放假前,和他最后一次见面,我提出了分手。 出乎意外的是他没有挽留,没有像往常一样拉着我的手,原来他也疲惫了,我...
    二四伍酱阅读 179评论 0 2