Effective Java(3rd)-Item30 优先使用泛型方法

  不仅是类可以被泛化,方法也可以。静态工具方法上的参数化类型通常是泛型。所有Collections(比如binarySearch和sort)“算法”方法都是泛型。
  编写泛型方法与编写泛型类型相似。考虑这个有缺点的方法,它返回了两个set的合集:


image.png

  这个方法编译成功了,但是会有两个警告:


image.png

  要修复这些警告并使方法类型安全,修改其声明以声明一个类型参数,便是三个set的元素类型(两个参数和返回值),并在整个方法中使用此类型参数。声明类型参数的类型参数列表介于方法的修饰符和返回类型之间。在这个例子中,类型参数列表是<E>,返回类型是Set<E>。类型参数的命名约定对于泛型方法和泛型类型是相同的(item29

image.png

  至少对于简单的泛型方法来说,这就是全部。此方法编译时不发生任何警告,并提供类型安全性以及易使用。这里有一个简单的程序来练习这个方法。这个程序不包含错误或警告的强制转换和编译:


image.png

  当你运行这个程序的时候,它会打印 [Moe, Tom, Harry, Larry, Curly, Dick]。(输出的元素的顺序取决于实现)。
  union方法的一个限制是,所有三个集合(两个输入参数和返回值)的类型必须完全相同。你可以使用有界通配符类型item31 ),使方法更加灵活。
  有时,你需要创建一个不可变但适用于许多不同类型的对象。由于泛型是通过擦除( item28)实现得,所以可以使用单个对象进行所有必需得类型参数化,但需要编写一个静态工厂方法来重复为每个请求的类型参数化分配对象。该模式称为泛型单例工厂,用于函数对象( item42 ),如Collections.reverseOrder,以及Collections.emptySet。
  假设你想要编写一个标识函数分发器。标准库提供了Function.identity,所以没有理由写你自己的(item51 )。但这是由教育意义的。创建一个新的标识函数对象是浪费时间的,因为它是无状态的。如果Java的泛型被具体化了,那么每种类型都需要一个标识函数,但是他们被擦除了,一个泛型的单例就足够了。如下是它的外观:

image.png

  IDENTITY_FN强制转换(UnaryFunction<T>)会生成一个未经检查的强制转换警告,因为UnaryOperator<Object>不是每个T都能转换的。但是恒等函数是特殊的:它不加修改地返回了它的参数,所以我们知道,无论T的值是什么,它都是一个UnaryOperator<T>.所以,我们可以自信地抑制该强制转换生成的未经检查的强制转换警告。一旦我们这样坐,代码编译就不会有错误或警告。
  下面是一个示例程序,使用泛型单例作为UnaryOperator<String>和UnaryOperator<Number>。与往常一样,它编译时没有错误或警告:


image.png

  允许类型参数被包含该类型参数本身的某个表达式所限制,虽然相对较少。这就是所谓的递归类型绑定。递归类型界的一种常见用法是与可比较的接口相关联,该接受定义了类型的自然排序。( item14)。这里显示了该接口:

image.png

  类型参数T定义实现类型的元素的类型Comparable<T>可被比较。实际上,几乎所有类型都只能与它们自己类型的元素进行比较。因此,例如,String实现了Comparable<String>,Integer实现了Comparable<Integer>,等等。
  许多方法采用实现类似排序的元素集合,计算其最小或最大值,等等。要做到这些,要求集合中的每个元素都可以与其中的每个其他元素进行比较,换句话说,列表中的元素必须是可以相互比较的。下面是如何表示该约束:

image.png

  类型界<E extends Comparable<E>>可以被读作”任何类型E可以被它自己比较“,它或多或少符合相互可比性的概念。
  下面是一个与前一个声明一起使用的方法。它根据元素的自然顺序计算集合中的最大值,并且编译时没有错误或警告:


image.png

   注意到如果这个list是空的,会抛出IllegalArgumentException。一个更好的替代方法是返回Optional<E>(item55 ).
  递归类型界可以变得更灵活,但是幸运的是,他们很少这么做。如果你理解这个术语,它的通配符变体(item31) ,以及自模拟的术语(item2),你能够处理实践中遇到的大多数递归类型界。
  总之,泛型 方法和泛型类型一样,比要求客户端对输入参数和返回值进行显示转换的方法更安全,更容易使用。和类型一样,你应该确保不用强制转换就可以使用你的方法,这通常意味着它们是通用的。和类型一样,你应该泛化使用需要强制转换的现有方法。这使新使用者更好的不破坏已存在的客户端(item26
本文写于2019.6.27,历时1天

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,133评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,682评论 3 390
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,784评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,508评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,603评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,607评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,604评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,359评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,805评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,121评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,280评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,959评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,588评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,206评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,193评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,144评论 2 352

推荐阅读更多精彩内容