Effective Java笔记(33)优先考虑类型安全的异构容器

Effective Java 泛型 第29条:优先考虑类型安全的异构容器 泛型最常用于集合,如 Set 和 Map ,以及单元素的容器。 如 ThreadLocal 和 AtomicReference 。在这些用法中,它都充当被参数化了的容器。这样就限制你每个容器只能有固定数目的类型参数。一般来说,这种情况正是你想要的。一个 Set 只有一个类型参数,表示它的元素类型;一个 Map 有两个类型参数,表示它的键和值类型;诸如此类。但是,有时候你会需要更多的灵活性。例如,数... 阅读详情

        泛型最常用于集合,如 Set<E >和 Map<K ,V>,以及单个元素的容器 ,如 ThreadLocal<T>和 AtomicReference<T> 。 在所有这些用法中,它都充当被参数化了的容器 。 这样就限制每个容器只能有固定数目的类型参数。 一般来说 ,这种情况正是你想要的 。 一个 Set只有一个类型参数,表示它的元素类型; 一个 Map 有两个类型参数,表示它的键和值类型.......

        但是,有时候你会需要更多 的灵活性 。 例如,数据库的行可以有任意数量 的列,如果能以类型安全的方式访问所有列就好了 。 幸运 的是,有一种方法可以很容易 地做到这一点 。这种方法就是将键( key )进行参数化而不是将容器( container )参数化 。 然后将参数化的键提交给容器来插入或者获取值 。 用泛型系统来确保值的类型与它的键相符 。

        下面简单地示范一下这种方法:以 Favorites 类为例,它允许其客户端从任意数量的其他类中,保存并获取一个“最喜爱”的实例 。Class 对象充当参数化键的部分 。 之所以可以这样, 是因为类 Class 被泛型化了 。 类的类型从字面上来看不再只是简单 的 Class,而是 Class<T> 。 例如 ,String.class 属于 Class<String >类型,Integer.class属于 Class<Integer >类型 。 当一个类的字面被用在方法 中,来传达编译时和运行时的类型信息时,就被称作类型令牌。

        Favorites 类的 API 很简单 。 它看起来就像一个简单 的映射 ,除了键(而不是映射)被参数化之外 。 客户端在设置和获取最喜爱 的实例时提交 Class 对象 。 下面就是这个 API:

public class Favorites {
    public <T> void putFavorite(Class<T> type, T instance);
    public <T> T getFavorite(Class<T> type);
}

        下面是一个示例程序,检验一下 Favorites 类,它将保存、获取并打印一个最喜爱的 String 、Integer 和 Class 实例 :

public static void main(String[] args) {
    Favorites f = new Favorites();
    f.putFavorite(String.class, "Java");
    f.putFavorite(Integer.class, 0xcafebabe);
    f.putFavorite(Class.class, Favorites.class);
    String favoriteString = f.getFavorite(String.class);
    int favoriteInteger = f.getFavorite(Integer.class);
    Class<?> favoriteClass = f.getFavorite(Class.class);
    System.out.printf("%s %x %s%n", favoriteString,
        favoriteInteger, favoriteClass.getName()) ;
}

        正如所料,这段程序打印出的是 Java cafebabe Favorites 。 注意,有时 Java 的printf 方法与 C 语言中的不同,C 语言中使用\n的地方,在 Java 中应该使用 %n 。 这个知会产生适用于特定平台的行分隔符,在许多平台上是\n,但是并非所有平台都是如此 。

        Favorites 实例是类型安全( typesafe )的 :当你向它请求 String 的时候 , 它从来不会返回一个 Integer 给你 。 同时它也是异构的( heterogeneous ): 不像普通的映射,它的所有键都是不同类型的 。 因此,我们将 Favorites 称作类型安全的异构容器( typesafe heterogeneous container)。

        Favorites 的实现小得出奇 。 它的完整实现如下:

public class Favorites {
    private Map<Class<?>, Object> favorites = new HashMap<>();

    public <T> void putFavorite(Class<T> type, T instance) {
        favorites.put (Objects.requireNonNull(type), instance);
    }

    public <T> T getFavorite(Class<T> type) {
        return type.cast(favorites.get(type)); 
    }
}

        这里面发生了一些微妙的事情 。 每个 Favorites 实例都得到一个称作 favorites 的私有 Map<Class<?>,Object >的支持 。 你可能认为由于无限制通配符类型的关系,将不能把任何东西放进这个 Map 中,但事实正好相反 。 耍注意的是通配符类型是嵌套的 : 它不是属于通配符类型的 Map 的类型,而是它的键的类型 。 由此可见,每个键都可以有一个不同的参数化类型:一个可以是 Class<String >,接下来是 Class<Integer >等 。 异构就是从这里来的 。

        第二件要注意的事情是,favorites Map 的值类型只是 Object 。 换句话说,Map 并不能保证键和值之间的类型关系,即不能保证每个值都为它的健所表示的类型(通俗地说,就是指键与值的类型并不相同一一译者注) 。 事实上,Java 的类型系统还没有强大到足以表达这一点 。 但我们知道这是事实,并在获取 favorite 的时候利用了这一点 。

        putFavorite 方法的实现很简单:它只是把(从指定的 Class 对象到指定的 favorite 实例) 一个映射放到 favorites 中 。 如前所述 ,这是放弃了键和值之间的“类型联系 ” ,因此无法知道这个值是键的一个实例 。 但是没关系,因为 getFavorites 方法能够并且的确重新建立了这种联系 。

        getFavorite 方法 的 实 现比 pu tFavorite 的更难一些 。 它先从 favorites 映射中获得与指定 Class 对象相对应的值 。 这正是要返回的对象引用,但它的编译时类型是错误的 。 它的类型只是 Object (favorites 映射的值类型),我们需要返回一个 T 。因此,getFavorite 方法的实现利用 Class 的 cast 方法,将对象引用动态地转换( dynamicallycast )成了 Cl ass 对象所表示自由类型。

        cast 方法是 Jav a 的转换操作符的动态模拟 。 它只检验它的参数是否为 Class 对象所表示的类型的实例 。 如果是,就返回参数;否则就抛出 ClassCastException 异常 。 我们知 道 getFavorite 中的 cast 调用永远不会抛出 ClassCastException 异常,并假设客户端代码正确无误地进行了编译 。 也就是说,我们知道 favor 工 tes 映射 中的值会始终与键的类型相匹配 。

        假设 cast 方法只返回它的参数,那它能为我们做什么呢?cast 方法的签名充分利用了 Class 类被泛型化的这个事实 。 它的返回类型是 Class 对象的类型参数 :

        这正是 getFavorite 方法所需要的,也正是让我们不必借助于未受检地转换成 T 就能确保 Favorites 类型安全的东西 。

        总而言之,集合 API 说明了泛型的一般用法,限制 每个容器只 能有固定数目的类型参数 。 你可以通过将类型参数放在键上而不是容器上来避开这一限制 。 对于这种类型安全的异构容器,可以用 Class 对象作为键 。 以这种方式使用的 Class 对象称作类型令牌 。 你也可以使用定制的键类型 。 例如,用一个 DatabaseRow 类型表示一个数据库行(容器),用泛型 Column<T>作为它的键 。

SAP PP工艺路线Routing保姆级配置指南:从CA01创建到替代/并行顺序实战 本文详细解析SAP PP模块中工艺路线(Routing)的配置与应用,从基础创建(CA01)到高级功能如替代顺序和并行顺序的实战操作。通过真实案例演示,帮助用户掌握SAP PP工艺路线的精细化管理,提升生产流程效率。 阅读详情

相关推荐

SECS/GSM 测试工具 SecsExpress 的配置与实战应用

本文详细介绍了半导体设备通讯测试工具SecsExpress的配置与实战应用。作为专业的SECS/GSM协议调试工具,它能模拟Host与设备端进行双向测试,帮助工程师快速部署、验证通讯链路,并高效排查与RMS系统或真实设备间的联调问题,是提升半导体工厂设备集成与维护效率的利器。

yhn456789的博客 298

残差连接residual connection

残差连接residual connection,假设神经网络某一层对input x进行了一个F操作,变为F(x),那么正常的神经网络输出为F(x),而加入残差连接以后,输出为x+F(x) 那么残差结构有什么好处呢?显而易见:因为增加了一项,那么该层网络对x求偏导的时候,多了一个常数项,所以在反向传播过程中,梯度连乘,也不会造成梯度消失。 ...

Dzwfvz的博客 5309

Mamba-ST实战:用状态空间模型实现艺术风格迁移的5个关键步骤

本文详细介绍了如何使用Mamba-ST状态空间模型实现高效的艺术风格迁移,涵盖环境配置、数据预处理、模型架构、训练策略和推理优化等5个关键步骤。Mamba-ST基于SSM(状态空间模型)构建,在保持生成质量的同时显著降低计算复杂度,为风格迁移领域提供了新的解决方案。

weixin_29163581的博客 355

优先考虑类型安全的异构容器

在Java中,异构容器是一种可以存储不同类型元素的容器。为了提高类型安全性,可以使用泛型和类型安全的异构容器,而不是传统的非类型安全容器。下面是一个例子,演示如何使用类型安全的异构容器。类型的容器,使用类型安全的异构容器可以更安全地处理异构数据,并且提供更好的开发体验。方法,你可以从容器中安全地获取元素,并且无需进行手动类型转换。方法,你可以将不同类型的元素放入容器;对象,以实现类型安全的异构容器。

wcg_jishuo的专栏 496

基于yolo11的BGA图像目标检测

15.YOLOv8的n/s版本(如YOLOv8n-1280),或通过TensorRT量化压缩模型。3.使用自适应batch_size(如根据GPU显存动态调整),推荐16-32。为采集分辨率整数倍(如原图2592×1944,训练时缩放为640×480),保持宽高比。14.采用余弦退火学习率(cos_lr)和早停(patience=50),防止过拟合。1.模型标注后,少量标注全部人工校验,大量数据抽检,部分人工检验。13.部署模型后持续收集困难样本(如模棱两可的预测结果),定期迭代更新模型。

qq_47798402的博客 1205

Android HTTPS抓包证书配置全解:Proxyman实战避坑指南

HTTPS抓包本质是中间人(MITM)通信的可信建立过程,其核心在于客户端对代理根证书的信任链配置。在Android平台,自7.0起系统默认不信任用户安装的CA证书,必须通过Network Security Config显式声明trust-anchors,将Proxyman导出的PEM格式根证书纳入App级信任锚点。这一机制区别于iOS和桌面浏览器,导致大量开发者卡在‘证书已安装却无法解密’的误区。技术价值在于打通开发调试闭环:精准定位SSLHandshakeException、绕过证书固定、支持React

weixin_32175665的博客 650

Java异构容器

Java异构容器与同构容器

weixin_44453385的博客 410

企业和个人 AI 编程工具怎么选?2025 年 12 款主流工具(Claude/Cursor 等)核心能力 + 收费对比

2025 年最火的 12 款 AI 编程工具,像 Claude、Cursor 这些热门款,我把它们的核心能力、收费标准全扒得明明白白,看完这篇你不用再瞎琢磨,直接就能挑到对的!再说说 Cursor,美国 Cursor Labs 做的,还拿过红杉资本投资,2022 年推出后,2024 年收入直接涨了 6400%,势头很猛。总之,不管你是企业技术管理者、程序员,还是刚入门的 AI 小白,按自己的需求(语言、合规、预算)挑,保准能找到最适合的 AI 编程工具!最后给大家划重点,不同需求直接对号入座:?

hundred98的博客 2801

建议:优先考虑类型安全的异构容器。

泛型最常用于集合,如Set和Map,以及单元素的容器,如ThreadLocal和Atomic Reference。在这些用法中,他都充当被参数化了的容器。这样就限制你每个容器只能有固定数目的类型参数。一般来说,这种情况正是你想要的。一个Set只有一个类型参数,表示它的元素类型;一个Map有两个类型参数,表示他的键和值类型;诸如此类。 但是,有时候你会需要更多的灵活...

孤芳不自赏 676

高等数学/概率论/数理统计/线性代数/离散数学面试-核心概念-问题理解

特征值与特征向量是线性代数中的概念,它们与线性变换有关。在线性变换中,如果存在非零向量 v ,使得当该向量通过变换后,其方向不变,只是长度发生了变化,那么这个向量 v 就是特征向量。而这个长度变化的比例因子,即变换前后向量长度的比值,称为特征值。数学公式表示:通俗易懂的解释:想象一下,你有一个可以伸缩的橡皮筋,这个橡皮筋可以代表一个向量。现在,你有一个特殊的机器,它可以改变橡皮筋的形状,但不会改变它延伸的方向。当你把橡皮筋放入机器中,机器会拉伸或压缩橡皮筋,但橡皮筋的方向保持不变。

m0_64198455的博客 2292

基于STM32的汽车主门电动窗开关系统设计方案

以下是基于 STM32CubeMX 和 HAL 库的示例代码,可实现基本的功能。

weixin_42300449的博客 995

【笔记33】优先考虑类型安全的异构容器

泛型最常用于集合,如Set和Map,以及单元素的容器,如ThreadLocal和Atomic Reference。在这些用法中,他都充当被参数化了的容器。这样就限制你每个容器只能有固定数目的类型参数。 但是,有时候你会需要更多的灵活性。例如,数据库行可以有任意多的列,如果能以类型安全的方式访问所有列就好了。幸运的是,有一种方法可以很容易地做到这一点。这种想法就是将键...

u013773608的博客 293

《唤醒你的AI同事:WorkBuddy从零上手》004:与其他 AI 工具的对比

把 WorkBuddy 与聊天机器人、办公套件内置 AI、自动化工具逐维对比,并按当前版本补充四项新差距:结果交付、连接器广度、资料库与多模态产出。

LuckyHanMo的博客 673

Effective Java笔记:优先考虑类型安全的异构容器

指能够存储不同类型对象的容器(与普通泛型容器如List<T>只能存储单一类型T不同)。而则是在编译时就能保证存储和获取对象的类型一致性,避免运行时的实现。这类容器在依赖注入、序列化框架、配置管理等场景中广泛应用,其核心价值是在灵活存储多类型对象的同时,通过编译期检查规避类型错误。

eclipseC的博客 1383

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

《Effective Java》解读第33条:优先考虑类型安全的异构容器

这是经典且高级的技巧,突破一个容器只能固定一种或几种类型参数”的限制,实现了在同一个容器中安全地存放和取出多种不同类型的对象。

Cosmoshhhyyy的博客 696

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Effective java 优先考虑类型安全的异构容器

泛型最常用于集合,如Set和Map<K, V>,以及单元素容器,例如ThreadLocal 和AtomicReference 。在这些用法中,它都充当被参数化了的容器。这样就限制你没个容器只能有固定数目的类型参数。一般来说,这种情况正是你想要的。一个Set只有一个类型参数,表示它的元素类型;一个Map有两个类型参数,表示它的键和值类型;诸如此类。   但是,有时候你会需要更多的灵活性。例如,数据库行可以有任意多的列,如果能以类型安全的方式访问所有列就好了。幸运的是,有一种方法可以很容易地做到这

菜园子丶For丨丶Tomorrow的博客 193

跟我学(Effective Java 2)第29条:优先考虑类型安全的异构容器

第29条:优先考虑类型安全的异构容器 泛型最常用于集合,它充当被参数化的容器,这样就限制你每个容器只能有固定数目的类型参数。一般来说,这正是你想要的。 但是,有的时候,我们需要更多的灵活性,比如,我们想安全的访问数据库的所有列,有一种方法可以容易做到这一点。这种想法是将键(key)进行参数化而不是将容器进行参数化。 然后将参数化的键交给容器,来插入或者获取值。用泛型系统来确保值的类型与它的键相符。...

Dullon_jiang的博客 228

Effective Java笔记第四章泛型第七节优先考虑类型安全的异构容器

Effective Java笔记第四章泛型 第七节优先考虑类型安全的异构容器 1.泛型最常用于集合,如Set和Map,以及单元素的容器,如ThreadLocal和AtomicReference。在这些用法中,它都充当被参数化了的容器。这样就限制了你每个容器只能有固定数目的类型参数。一般来说,这种情况正是我们想要的。例如:一个Set只有一个类型参数,表示他的元素类型;一个Map有两个类型参数,表示他的键和值类型。 2.有时候会需要更多的灵活性,这时候就有一种方法可以很容易的做到,就是将键进行参数化而不是将容器

zh123456_789的博客 214

effectivejava 第33条 优先考虑类型安全的异构器

1.当一个类的字面被用在方法中,来传达和运行时的类型信息时,就被称作类型令牌(type token),如public <T> void putFavorite(Class<T> type, T instance); --Class<T> type就是类型令牌。 2.集合api说明了泛型的一般用法,限制每个容器只能有固定数目的类型参数。你可以通过将类型参数放在键...

u012864294的博客 175

Effective Java(第三版) 学习笔记 - 第五章 泛型 Rule26~Rule33

本文主要介绍泛型相关内容

weixin_44453385的博客 2207

《Effective Java》泛型

《Effective Java》第四章 泛型

qq_43350524的博客 682

Effective Java 第三版 中文翻译

effective-java-third-edition 介绍 Effective Java 第三版全文翻译,纯属个人业余翻译,不合理的地方,望指正,感激不尽! 目录 推荐序 前言 致谢 第一章 引言 第二章 创建和销毁对象   本章涉及创建和销毁对象,包括何时以及如何创建它们,何时以及如何避免创建它们,如何确保它们被及时销毁,以及如何管理在销毁之前必须进行的清理操作。 第1项:考虑静态工...

Coloured_Glaze的博客 3861

【Effective Java】第5章 读书笔记

第5章 泛型 26,请不要使用原生态类型 原生态类型:List,不带任何实际类型参数的的泛型名称 使用原生态类型是合法的,但是会失去泛型在安全性和描述性方面的所有方式。 List:不推荐,没有类型检查, List < Object >:可行,明确告诉编译器,可以接受任何类型 List < String >:可行,可以传给List,但是不能传给 List 泛型有子类型化规则。 无限制通配类型:Set <?>,不确定或者不关心实际类型参数 Set 与 Set<?&gt

qq_45050687的博客 230

effective Java-泛型

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

white_while的博客 425

【Effective Java】8、优先考虑类型安全的异构容器

有的时候我们一个容器只有一个类型或几个类型并不能满足我们的要求,比如set中存放的元素类型都是同一种,map也就指定的两种 这里我们可以将键进行参数化,而不是将容器参数化,也就是我们可以给容器传一个键的类型,然后value用来放对应的实例,这样就可以存放多个不同的类型了 如: package cn.xf.cp.ch02.item29; import java.util....

weixin_30446197的博客 107

Effective Java读书笔记

第一章 引言 本文用来记录Effective Java学习过程中的各个知识点,受此时能力所限,有些点可能讲的不太清楚,或者理解有错误的地方,请多多指教! 第二章 创建和销毁对象 第一条 用静态工厂方法代替构造器 可参考文章:https://blog.youkuaiyun.com/u014129886/article/details/89670049 总而言之,静态工厂方法和共有构造器各有各的用处,我们需要理解他们各自的长处,静态工厂经常更加合适。 此处的静态工厂方法与设计模式中的工厂模式不同,这里是一种构造

逆水行舟,不进则退 1441

Effective Java之泛型 总结

第23条 请不要在新代码中使用原生态类型 如果使用原生态类型 就失掉了泛型在安全性和表述性方面的所有优势 在类文字(class literal)中必须使用原生态类型 分类 术语 示例 参数化的类型 List&amp;lt;String&amp;gt; 实际类型参数 String 泛型 List&amp;lt;E&amp;gt; 形式类型参数 E 无限制通配符类型 List&a

勤劳的搬运工 285
上一篇: 2023软考系统架构设计师论文写作要点
下一篇: Kubernetes(K8s)入门
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值