Effective Java笔记(30)优先考虑泛型方法

详解几种常见设计模式Singleton、Factory、Strategy在项目中的应用 本文转载自:详解几种常见设计模式Singleton、Factory、Strategy在项目中的应用 一、前言 前几天阅读一框架文档,里面有一段这样的描述 “从对象工厂中………” ,促使写下本文。尽管一些模式简单和简单,但是常用、有用。 结合最近一个项目场景回顾一下里面应用到的一些模式<Singleton、Factory、Strategy>。 Singleton:创建型模式,负责创建... 阅读详情

        正如类可以从泛型中受益一般 ,方法也一样。静态工具方法尤其适合于泛型化 。 Collections 中的所有“算法”方法(例如 binarySearch 和 sort )都泛型化了 。

        编写泛型方法与编写泛型类型相类似 。 例如下面这个方法,它返回两个集合的联合 :

public static Set union(Set s1, Set s2) {
    Set result = new HashSet(s1);
    result.addAll(s2);
    return result;
}

        这个方法可以编译,但是有两条警告 :

        为了修正这些警告,使方法变成是类型安全的,要将方法声明修改为声明一个类型参数( type parameter ),表示这三个集合的元素类型(两个参数和一个返回值),并在方法中使用类型参数。 声明类型参数的类型参数列表,处在方法的修饰符及其返 回值之间 。 在这个示例中,类型参数列表为< E >,返回类型为 Set<E > 。 类型参数的命名惯例与泛型方法以及泛型的相同: 

public static <E> Set<E> union(Set<E> s1, Set<E> s2) {
    Set<E> result = new HashSet<>(s1);
    result.addAll(s2);
    return result;
}

        至少对于简单的泛型方法而言,就是这么回事了 。 现在该方法编译时不会产生任何警告,并提供了类型安全性,也更容易使用 。 以下是一个执行该方法的简单程序 。 程序中不包含转换,编译时不会有错误或者警告 :

public static void main(String[] args) {
    Set<String> guys = Set.of("Tom", "Dick", "Harry");
    Set<String> stooges = Set.of("Larry","Moe", "Curly");
    Set<String> af1Cio = union(guys, stooges); .
    System.out.println(af1Cio);
}

        运行这段程序时,会打印出[ Moe, Harry , Tom , Curly , Larry , Dick ] 。 (元素的输出顺序是独立于实现的 。 )

        union 方法的局限性在于三个集合的类型(两个输入参数和一个返回值)必须完全相同 。利用有限制的通配符类型( bounded wildcard type )可以使方法变得更加灵活 。

        有时可能需要创建一个不可变但又适用于许多不同类型的对象 。由于泛型是通过擦除实现的,可以给所有必要的类型参数使用单个对象,但是需要编写一个静态工厂方法,让它重复地给每个必要的类型参数分发对象 。 这种模式称作泛型羊例工厂(generic singleton factory ),常用于函数对象,如 Collections.reverse Order ,有时也用于像 Collections.emptySet 这样的集合 。

        假设要编写一个恒等函数( identity function)分发器。 类库中提供了 Function.identity,因此不需要自己编写,但是自己编写也很有意义 。 如果在每次需要的时候都重新创建一个 ,这样会很浪费,因为它是无状态的( stateless ) 。 如果 Java 泛型被具体化了,每个类型都需要一个恒等函数,但是它们被擦除后,就只需要一个泛型单例 。 请看以下示例 :

private static UnaryOperator<Object> IDENTITY_FN = (t) -> t;

@SuppressWarnings ("unchecked")
public static <T> UnaryOperator<T> identi tyFunction() {
    return (UnaryOperator<T>) IDENTITY_FN;
}

        IDENTITY_FN 转换成( UnaryFunction<T>),产生了一条未受检的转换警告,因为UnaryFunction<Object >对于每个 T 来说并非都是个 UnaryFunction<T > 。 但是恒等函数很特殊 : 它返回未被修改的参数,因此我们知道无论 T 的值是什么,用它作为 Unary ­Function<T >都是类型安全的 。 因此,我们可以放心地禁止由这个转换所产生的未受检转换警告 。 一旦禁止,代码在编译时就不会出现任何错误或者警告 。

        下面是一个范例程序,它利用泛型单例作为 UnaryFunction<String >和 Unary­Function<Number > 。 像往常一样,它不包含转换,编译时没有出现错误或者警告 :

public static void main(String[] args) {
    String[] strings = { "jute", "hemp", "nylon" };
    UnaryOperator<String> sameString = identityFunction();
    for (String s : strings)
        System.out.printIn(sameString.apply(s));
    
    Number[] numbers = { 1,2.0, 3L };
    UnaryOperator <Number> sameNumber = identityFunction();
    for (Number n : numbers)
        System.out.println(sameNumber . apply(n)) ;
}

        虽然相对少见,但是通过某个包含该类型参数本身的表达式来限制类型参数是允许的 。这就是递归类型限制( recursive type bound ) 。 递归类型限制最普遍的用途与 Comparable接口有关,它定义类型的自然顺序 。 这个接口的内容如下 :

public interface Comparable<T> {
    int compareTo(T o);
}

        类型参数 T 定义的类型,可以与实现 Cornparable<T >的类型的元素进行比较 。 实际上,几乎所有的类型都只能与它们自身的类型的元素相比较 。 例如 String实现 Comparable<String>, Integer 实现 Comparable< Integer>,等等 。

        有许多方法都带有一个实现 Comparable 接口的元素列表,为了对列表进行排序,并在其中进行搜索,计算出它的最小值或者最大值,等等 。 要完成这其中的任何一项操作,都要求列表中的每个元素能够与列表中的每个其他元素相比较,换句话说,列表的元素可以互相比较( mutually comparable ) 。 下面是如何表达这种约束条件的一个示例 :

public static <E extends Comparable<E>> E max(Col1ection<E> C) ;

        类型限制< E extends Cornparable<E>>,可以读作“针对可以与自身进行比较的每个类型 E ”,这与互比性的概念或多或少有些一致 。

        下面的方法就带有上述声明 。 它根据元素的自然顺序计算列表的最大值,编译时没有出现错误或者警告:

pub1ic static <E extends Comparable<E>> E max(Collection<E> c) {
    if(c.isEmpty())
        throw new IllegalArgumentException("Empty collection");
    E result = null;
    for(E e:c)
        if (result == null || e.compareTo(result) > 0)
    result = Objects.requireNonNull(e);
    return result;
}

        注意,如果列表为空,这个方法就会抛出 IllegalArgumentException 异常 。 更好的替代做法是返回一个 Optional<E>  。

        递归类型 限制可能比这个要复杂得多 ,但幸运的是,这种情况并不经常发生 。 如果你理解了这种习惯用法和它的通配符变量,以及模拟自类 型( simulated selιtype )习惯用法 , 就能够处理在实践中遇到的许多递归类型限制了 。

        总而言之,泛型方法就像泛型一样,使用起来比要求客户端转换输入参数并返回值的方法来得更加安全,也更加容易 。 就像类型一样 ,你应该确保方法不用转换就能使用 ,这通常意味着要将它们泛型化 。 并且就像类型一样,还应该将现有的方法泛型化,使新用户使用起来更加轻松 ,且不会破坏现有 的客户端。

《Effective Java》第30条:优先考虑泛型方法 原文P106:为了修正这些警告,使方法变成是类型安全的,要将方法声明修改为声明一个类型参数,表示这三个集合的元素类型(两个参数和一个返回值),并在方法中使用类型参数。这里解释下为什么第10行的警告可以被忽略,是因为恒等式返回的就是原本的参数,未做任何类型的修改,所以无论T是什么,返回的都还是T,能保证UnaryOperator 是类型安全的。这里又给出了一个概念:递归类型限制,什么是递归类型限制:类型参数的限制条件里,包含了类型参数本身(像递归一样自我引用)。同学们也可以参照书上的代码测试下。 阅读详情

相关推荐

《Effective Java》第29条:优先考虑泛型

这种方式会消除错误,但是会得到一条非受检的警告(详见27条),我们自己能确定该代码是安全的,且强转不回会危及程序的安全,因为 elements 数组是一个private的,且没有提供访问该数组的方法,该数组获取的值都来自于push方法,该方法的参数类型为 E,所以该强转不会有危害。原文P106:绝大多数泛型就像我们的 Stack 示例一样,因为它们的类型参数没有限制:你可以创建 Stack、Stack、Stack>,或者任何其他对象弓用类型的 Stack。只要时间允许,就把现有的类型都泛型化。

TD_FAlmK的博客 772

第二十七条:优先使用泛型方法

一、泛型方法的优点(一) 优点:泛型方法能够推断出输入参数中的参数类型 例: public E getType(E type){ return type; }//当使用该方法的时候,虚拟机能够推断出输入的参数的类型是什么,并返回该类型。 举例:合并两个Set列表,用原生类型方法与泛型方法比较 //原生类型方法 public Set union(Set set1,Set set2){

chen19960724的博客 571

Win10本地账户密码遗忘?巧用指纹/PIN快速重置(家庭版/专业版通用指南)

本文提供了一份详细的Win10本地账户密码遗忘自救指南,适用于家庭版和专业版用户。核心方法是利用已登录的指纹或PIN码权限,通过创建新的管理员账户或使用系统工具,安全重置遗忘的本地账户密码,无需第三方工具或重装系统,有效保护个人数据。

e6f7g8h9i的博客 578

建议:优先考虑泛型方法。

就如类可以从泛型中受益一般,方法也一样。静态工具方法尤其适合于泛型化。Collections中的所有“算法”方法(例如binarySearch和sort)都泛型化了。 编写泛型方法与编写泛型类型相类似。例如下面这个方法,它返回两个集合的联合: // Use raw types - unacceptable! (Item 23) public static ...

孤芳不自赏 1999

psasp和matlab,PSASP与Matlab/SimPowerSystems联合仿真接口方法研究

[1]李亚楼,吴中习.Matlab模型接入PSASP暂态稳定计算模块的方法[J].电网技术,2008,32(19):31-36.Li Yalou,Wu Zhongxi.An Approach to Interface Matlab Model with PSASP Transient Stability Module [J].Power System Technology,2008,32(19):...

weixin_39636245的博客 1082

当我们谈论Unidbg时我们在谈什么

文章目录一、前言二、使用Unidbg的工作量是什么三、补环境补的是什么3.1 运行环境缺失3.2 上下文缺失四、Unidbg 不是所有情况下最优的解决方案五、Unidbg在大多数情况下是好的方案六、Unidbg和风控无关七、尾声 一、前言 这是一篇漫谈Unidbg的文章,我对Unidbg的使用和理解都还很浅,日后会更新或修改看法,欢迎大佬指点,也期待同侪讨论。 二、使用Unidbg的工作量是什么 我们常规使用Frida + IDA的动静态分析中,工作可能是这样的 找线索→Frida Hook验证→验证成功继

lilac的博客 5788

【笔记30】优先考虑泛型方法

就如类可以从泛型中受益一般,方法也一样。静态工具方法尤其适合于泛型化。Collections中的所有“算法”方法(例如binarySearch和sort)都泛型化了。 编写泛型方法与编写泛型类型相类似。例如下面这个方法,它返回两个集合的联合: public static Set union(Set s1, Set s2) { Set result =...

u013773608的博客 402

Codex 团队如何用自己的产品构建产品——整个 Spec 只有 10 个要点

OpenAI Codex团队采用极简产品开发模式,整个产品规格仅10个要点。团队50-100人长期仅1名PM,设计师代码量已超过工程师。产品负责人Alexander Embiricos透露,团队几乎不写详细文档,仅在需要协调时写简短要点。OpenAI采用独特规划哲学:只做8周内短期或长期方向性规划,拒绝中期路线图。2025年GPT-5.2 Codex发布后,模型能力突破催生了桌面应用开发。团队强调"让离代码最近的人做决策",PM角色转变为"填空者",设计师与工程师界限

348

第27条 泛型——优先考虑泛型方法

术语:  递归类型限制:通过某个包含该类型参数本身的表达式来限制类型参数。         考虑如下的方法,它的作用是返回两个集合的联合: [java] view plain copy // Users raw types - unaccepable!   public static Set union(Set s1,

Xi__Yuan的专栏 2751

FPGA+CUYSB3014实现USB3.0功能

CYUSB3014是赛普拉斯在近几年推出的新一代USB3.0的外设控制器,可以解决USB2.0带宽限制,或者单独开发USB协议和驱动的难题。赛普拉斯将CYUSB3014简称为EZ-USB FX3,具有高度的灵活特性,开发人员只需要下载FX3的固件库,就能使用USB3.0的功能。目前在一些电子产品中,使用主控器加PHY芯片最流行的方式是用FPGA+FX3这种搭配来实现USB3.0接口。......

D_Katter的博客 7065

ML307R OpenCPU TCP使用

实现现象 平台下发数据,板子在收到数据之后,马上再发送到平台,通过串口助手可以看到已经接收到数据。ML307R TCP 是使用LWIP的标准的socket通信,具体TCP流程可以自行百度。实验目的:实现把接收的数据再发送到服务端。因为是4G,所以必须用外网的。

面朝大海春暖花开 2232

《Effective Java》学习笔记——第5部分 泛型的使用

Effective Java》共有多个章节,每个章节提供了若干条建议或最佳实践,整理了对应章节关键的实践内容,用于自己后续代码开发过程中,参考对照,自查代码习惯,从而提升输出的代码质量。《Effective Java》第5部分“泛型”主要讲如何在 Java 中正确有效地使用泛型。泛型是 Java 5 引入的重要特性,它增强了类型安全性、减少了类型转换的需求,并且使得代码更加通用和灵活。但是,泛型的使用不当也可能导致程序的错误或性能问题。掌握泛型的使用技巧和最佳实践,对于提升个人代码能力非常重要。

weixin_37693760的博客 812

DSP2837X CLA开发实战教程

摘要: 本文详细解析TI C2000 DSP中CLA协处理器的开发流程,以TMS320F28377D的cla_divide案例为例,展示浮点除法验证的实现方法。从基础配置(消息RAM管理、任务触发)到高级调试(ePWM计时、断点设置),涵盖全流程开发要点。重点分析CLA编程约束(禁用标准库、数学优化)、多任务调度及常见问题解决方案(如死锁、数据同步)。提供FPGA协同加速、电机控制等扩展方向,并推荐官方例程与硬件平台(如创龙TL2837xF-EVM)。开发时需注意.cla文件语法支持及调试技巧,以充分发挥C

6760

Effective Java学习笔记--第29、30条优先考虑泛型和泛型方法

这两条主要讲述了泛型对于类与方法的构建能起到很多积极的作用。

weixin_50353846的博客 960

openbmc mctp i3c适配步骤

本文介绍了在Intel OKS平台下,BMC作为I3C从设备如何适配MCTP over I3C的实现方法。主要内容包括:1)关键术语解释,如MDB(Mandatory Data Byte)值为0xAE,DCR(Device Characteristics Register)和BCR(Bus Characteristics Register)的设置;2)适配流程说明,包括BMC作为控制器主节点分配地址后成为MCTP端点,CPU作为总线所有者的角色转换;3)测试验证步骤,展示通过mctp-client工具发送指

wit_yuan的专栏 132

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Effective Java 泛型 第27条:优先考虑泛型方法

就如类可以从泛型中受益一般,方法也一样。静态工具方法尤其适合于泛型化。 编写泛型方法与编写类型类型相类似。 例:他返回两个集合的联合: // Users raw types - unaccepable! public static Set union(Set s1, Set s2) { Set result = new HashSet(s1); result.addAll...

yancyang的博客 6263

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Effective Java 泛型 第26条:优先考虑泛型

一般来说,将集合声明参数化,以及使用JDK所提供的泛型和泛型方法,这些都不太困难,编写自己的泛型会比较困难一些,但是值得花些时间去学习如何编写。 考虑第6条中这个简单的堆栈实现: // Object -based Collection - a prime candidate for generics public class Stack{ private Object[] elem...

yancyang的博客 6264

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

《Effective Java》泛型

《Effective Java》第四章 泛型

qq_43350524的博客 682

Java:Effective java学习笔记之 优先考虑泛型和泛型方法

Java优先考虑泛型和泛型方法优先考虑泛型参考 优先考虑泛型 参考 1、建议:优先考虑泛型方法。 2、Effective Java 优先考虑泛型 3、Effective Java笔记第四章泛型第四节优先考虑泛型

JMW1407的博客 545

effective java 第27条 优先考虑泛型方法

第27条 优先考虑泛型方法 package .fanxing27; public class UnaryFunctionClass { private static UnaryFunction<Object> IDENTY_FUNCTION= new UnaryFunction<Object>() { @Override public Objec...

y41992910的博客 274

《Effective Java》解读第30条:优先考虑泛型方法

类可以是泛型的(如List),方法也可以是独立的泛型方法。泛型方法意味着该方法可以独立于其所在类,拥有自己的类型参数,从而在更广泛的输入类型上安全地工作。

Cosmoshhhyyy的博客 403

Effective Java 学习笔记之泛型

1.不要在新代码中使用原生态类型1) 声明中具有一个或者多个类型参数的类或者接口就是泛型类或接口 例如List<E>(读作‘E的列表’) 泛型类和接口统称作泛型2)每个泛型都定义一个原生态类型,即不带任何实际类型参数的泛型名称。例如List<E>相对应的原生态类型是List3)使用原生态类型,如果放入的类型不一致,在编译和运行时不会报错,直到从其中取出元素的时候才会收到提示 List

Heqianqian的博客 1112

effective Java-泛型

泛型 26. 请不要使用原生态类型 泛型类和泛型接口统称为泛型generic 每一种泛型定义一组参数化的类型parameterized type 每一种泛型都定义一个原生态类型raw type:即不带任何实际类型参数的泛型名称,如List原生类型是List,主要为了泛型出现之前的代码进行兼容。 如果使用原生态类型,就失掉了泛型在安全性和描述性方面的所有优势 原生态类型List和参数化的类型List...

white_while的博客 425

【总结】Effective java经验之谈,泛型

对于泛型这一章,在起始写框架的时候,并没有注意细节,造成了很多方法或者类的错误设计。这本书在这点上弥补了我一个短板。大概的总结如下。

阿利在努力 2010

《Effective Java 3rd》读书笔记——泛型

不要使用原生类型 声明中具有一个或多个类型参数的类或者接口就是泛型类或接口。泛型类和接口统称为泛型。 每一种泛型都定义一个原生(态)类型,即不带任何实际类型参数的泛型名称。例如,与List<E>相对应的原生类型是List。 private final Collection<Stamp> stamps = ...; 通过这条声明,编译器知道stamps应该只包含Stamp实...

日积月累,天道酬勤 832

学习记录:Effective Java-优先考虑泛型

在Java中,泛型是一种强大的特性,可以提高代码的类型安全性和可读性。因此,在编写代码时应该优先考虑使用泛型。

weixin_36639192的博客 533
上一篇: Effective Java笔记(29)优先考虑泛型
下一篇: Effective Java笔记(31)利用有限制通配符来提升 API 的灵活性
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值