Java 理论与实践: 伪typedef反模式-Java基础-Java-编程开发

apache-ignite-1.5.0.final apache-ignite-1.5.0.final Windows安装板,本地使用极其方便 立即下载
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>

将泛型添加到 Java语言中增加了类型系统的复杂性,提高了许多变量和方法声明的冗长程度。因为没有提供 “typedef” 工具来定义类型的简短名称,所以有些开发人员转而把扩展当作 “穷人的 typedef”,结果收到了良好的效果。

对于 Java 5.0 中新增的泛型工具,一个常见的抱怨就是,它使代码变得太冗长。原来用一行就够的变量声明不再存在了,与声明参数化类型有关的重复非常讨厌,特别是还没有良好地支持自动补足的 IDE。例如,如果想声明一个 Map,它的键是 Socket,值是 Future ,那么老方法就是:

Map socketOwner = new HashMap();

比新方法紧凑得多:

Map >socketOwner = new HashMap >();

当然,新方法内置了更多类型信息,减少了编程错误,提高了程序的可读性,但是确实带来了更多声明变量和方法签名方面的前期工作。类型参数在声明和初始化中的重复看起来尤其没有必要;Socket 和 Future 需要输入两次,这迫使我们违犯了 “DRY” 原则(不要重复自己)。

合成类似于 typedef 的东西

添加泛型给类型系统增加了一些复杂性。在 Java 5.0 之前,“type” 和 “class” 几乎是同义的,而参数化类型,特别是那些绑定的通配类型,使子类型和子类的概念有了显著区别。类型 ArrayList 、ArrayList 和 ArrayList 是不同的类型,虽然它们是由同一个类 ArrayList 实现的。这些类型构成了一个层次结构;ArrayList 是 ArrayList 的超类型,而 ArrayList 是 ArrayList 的超类型。

对于原来的简单类型系统,像 C 的 typedef 这样的特性没有意义。但是对于更复杂的类型系统,typedef 工具可能会提供一些好处。不知是好还是坏,总之在泛型加入的时候,typedef 没有加入 Java 语言。

有些人用作 “穷人的 typedef” 的一个(坏的)做法是一个小小的扩展:创建一个类,扩展泛型类型,但是不添加功能,例如 SocketUserMap 类型,如清单 1 所示:

清单 1. 伪 typedef 反模式 —— 不要这么做

public class SocketUserMap extends HashMap >{ } SocketUserMap socketOwner = new SocketUserMap();

我将这个技巧称为伪 typedef 反模式,它实现了将 socketOwner 定义简化为一行的这一(有问题的)目标,但是有些副作用,最终成为重用和维护的障碍。(对于有明确的构造函数而不是无参构造函数的类来说,派生类也需要声明每个构造函数,因为构造函数没有被继承。)

伪类型的问题

在 C 中,用 typedef 定义一个新类型更像是宏,而不是类型声明。定义等价类型的 typedef,可以与原始类型自由地互换。清单 2 显示了一个定义回调函数的示例,其中在签名中使用了一个 typedef,但是调用者提供给回调的是一个等价类型,而编译器和运行时都可以接受它:

清单 2. C 语言的 typedef 示例

// Define a type called "callback" that is a function pointer typedef void (*Callback)(int); void doSomething(Callback callback) { } // This function conforms to the type defined by Callback void callbackFunction(int arg) { } // So a caller can pass the address of callbackFunction to doSomething void useCallback() { doSomething(&callbackFunction); }

扩展不是类型定义

用 Java 语言编写的试图使用伪 typedef 的等价程序就会出现麻烦。清单 3 的 StringList 和 UserList 类型都扩展了一个公共超类,但是它们不是等价的类型。这意味着任何想调用 lookupAll 的代码都必须传递一个 StringList,而不能是 List 或 UserList。

清单 3. 伪类型如何把客户限定在只能使用伪类型

class StringList extends ArrayList { } class UserList extends ArrayList { } ... class SomeClass { public void validateUsers(UserList users) { ... } public UserList lookupAll(StringList names) { ... } }

这个限制要比初看上去严格得多。在小程序中,可能不会有太大差异,但是当程序变大的时候,使用伪类型的需求就会不断地造成问题。如果变量类型是 StringList,就不能给它分配普通的 List ,因为 List 是 StringList 的超类型,所以不是 StringList。就像不能把 Object 分配给类型为 String 的变量一样,也不能把 List 分配给类型为 StringList 的变量(但是,可以反过来,例如,可以把 StringList 分配给类型为 List 的变量,因为 List 是 StringList 的超类型。)

同样的情况也适用于方法的参数;如果一个方法参数是 StringList 类型,那么就不能把普通的 List 传递给它。这意味着,如果不要求这个方法的每次使用都使用伪类型,那么根本不能用伪类型作为方法参数,而这在实践当中就意味着在库 API 中根本就不能使用伪类型。而且大多数库 API 都源自本来没想成为库代码的那些代码,所以 “这个代码只是给我自己的,没有其他人会用它” 可不是个好借口(只要您的代码有一点儿用处,别人就有可能会使用它;如果您的代码臭得很,那您可能是对的)。

[1] [2]

M2DGR数据集在主流SLAM框架中的实战配置指南:从ORB-SLAM到FAST-LIO的完整流程 本文提供了M2DGR多传感器数据集在主流SLAM框架中的实战配置指南。详细介绍了从ORB-SLAM、VINS-Mono等视觉/视觉惯性框架,到A-LOAM、FAST-LIO等激光/激光惯性框架的完整配置流程、参数调整要点及常见问题解决方案。通过实际测试对比,分析了各算法在M2DGR数据集上的表现,为机器人定位与建图研究提供了宝贵的实战经验。 阅读详情

相关推荐

STM32F4用FSMC驱动AX58100 EtherCAT从站芯片,保姆级配置流程与避坑指南

本文详细介绍了STM32F4通过FSMC接口驱动AX58100 EtherCAT从站芯片的完整配置流程,包括硬件连接、时序优化、协议栈移植及TwinCAT主站集成。针对工业自动化场景,提供高性价比的实时控制解决方案,特别适合机械臂、CNC机床等精确同步应用,并分享关键调试技巧与性能优化方法。

weixin_27869497的博客 308

OpenClaw 2026开源AI框架部署与优化指南

AI智能体框架是现代人工智能应用开发的核心基础设施,通过模块化架构实现功能组件的灵活组合。其技术原理基于微服务架构和容器化部署,能够显著提升开发效率和系统可扩展性。OpenClaw作为开源AI框架的典型代表,2026版本在性能优化和跨平台支持方面有重大改进,特别适合金融分析、智能客服等场景。该框架采用Docker容器化部署方案,支持主流大语言模型接入,通过合理的资源配置和参数调优可以充分发挥硬件性能。内存管理和GPU加速是部署时需要重点考虑的技术要点,合理的日志管理和备份策略则能确保系统长期稳定运行。

weixin_34146805的博客 538

13 万字 C 语言从入门到精通保姆级教程2021 年版

13 万字C语言保姆级教程,从入门到精通。

李南江 61万+

Ignite(五)-报错class org.apache.ignite.IgniteCheckedException: No network addresses found-解决方法

Ignite-报错class org.apache.ignite.IgniteCheckedException: No network addresses found原因调试使用代码 具体报错如下: 八月 13, 2019 11:30:46 上午 org.apache.ignite.logger.java.JavaLogger error 严重: Failed to start manager: ...

DRD 7505

从零到一:QT for OpenHarmony 开发环境实战搭建与踩坑指南

本文是一份详尽的QT for OpenHarmony开发环境搭建实战指南。文章手把手教你如何在Windows和macOS系统上,从环境准备、核心工具(DevEco Studio与社区版QT SDK)安装配置,到创建首个QT Quick项目、解决构建部署中的常见问题,最终实现应用在OpenHarmony设备上运行。内容涵盖关键配置修改、资源管理及深度踩坑经验,旨在帮助开发者高效开启跨平台开发之旅。

weixin_29190573的博客 327

基于JavaFX的Http Server模拟器

源码地址 GitHub - DayRain/http-server-simulator: http server 模拟器 功能描述 HttpServer模拟器,通过简单的配置即可模拟第三方服务端,用于接收和响应HTTP请求。 支持同时模拟多个服务、动态添加接口、动态配置返回值。 使用说明 运行 exe运行 编译代码后,点击exe直接运行 代码运行 下载好代码后,运行主类ApplicationStarter即可 新建服务 主界面如下 点击 文件-新建 创建新的服务 ...

小楼夜听雨的博客 2536

java中typedef,在Java中实现typedef

I have a type Time32 that is used in generics as Work so i made a class Time32.I also have to implementtypedef UInt(5) Time32Here UInt means the unsigned int. Java doesn't have unsigned int, so i mad...

weixin_33737167的博客 864

OpenOCD入门到精通:第28章 综合实战:RISC-V 调试

RISC-V调试实战摘要 本文介绍了RISC-V调试规范及其在OpenOCD中的实现。主要内容包括: RISC-V Debug规范的两个版本(0.11和0.13)及其差异,OpenOCD通过自动检测DTMCS寄存器版本号选择对应驱动实现。 RISC-V调试架构的分层设计,包含DTM、Debug Module、Program Buffer等核心组件,以及三种内存访问方式(progbuf、sysbus、abstract)。 以GD32VF103为例的实战调试配置,包括硬件连接、OpenOCD配置文件编写和GDB

从事嵌入式linux android驱动开发,拥有全栈能力 285

java typedef的用法,typedef

之前用typedef的时候大多是用在把一个很长的名字改成一个很短的名字比如usigned int 取个别名叫uint这种,今天查了一下发现用途远不止这些。。typedef四个用途用途一:定义一种类型的别名,而不只是简单的宏替换,可以用作同时声明指针型的多个对象。char *pa,pb;//这样只声明了一个指向字符变量的指针和一个字符变量(这样写可能会觉得是声明了char * 类型的两个指针,其实并...

weixin_31974659的博客 3393

电磁场仿真软件:Sonnet_(1).Sonnet软件概述

根据特定需求自定义仿真流程,如多频率点仿真、多边界条件仿真等。

kkchenjj的博客 1452

AUTOSAR AP——SM模块

对AUTOSAR AP中状态管理模块SM,从模块定义、总结等多方面进行了介绍。

weixin_43627682的博客 285

软件测试工程师面试全攻略:核心考点与实战解析

软件测试是保障软件质量的关键环节,其核心在于通过系统化的方法验证功能正确性。从黑盒白盒测试等基础理论,到Selenium、Postman等自动化工具应用,测试工程师需要构建完整的质量保障体系。在持续集成实践中,合理的测试分层策略和质量门禁设置能显著提升交付效率。对于电商、金融等典型应用场景,需要特别关注高并发下的性能测试和安全防护。随着AI和云原生技术的发展,智能用例生成和容器化环境测试正在成为行业新趋势。掌握缺陷管理流程、测试设计思维等核心能力,是应对测试工程师面试的关键。

weixin_30606461的博客 279

实现航迹关联的三种JPDA算法及Matlab代码

本文介绍了三种不同的JPDA算法实现航迹关联,并提供相应的Matlab代码。卡尔曼滤波是一种常用的状态估计算法,其基本思想是根据系统模型和观测数据,通过迭代计算来更新系统状态的估计值。基于卡尔曼滤波的JPDA算法是指在航迹关联问题中,同时利用卡尔曼滤波器的状态估计和概率假设,从而确定目标之间的关联关系。基于粒子滤波的JPDA算法是指在航迹关联问题中,通过抽样生成一组粒子(代表系统的不同可能状态),从而计算目标之间的关联概率。基于启发式搜索的JPDA算法是指在航迹关联问题中,通过多次迭代寻找最优关联方案。

code_welike的博客 1831

C++模板本质:编译期契约与泛型编程实践

C++模板是实现泛型编程的核心机制,其本质并非简单的类型替换,而是编译期驱动的静态契约系统——要求代码在实例化前即满足语法与语义约束。它通过编译器按需展开生成专属代码,实现零运行时开销与强类型安全。相比Java泛型或Python鸭子类型,C++模板不擦除类型,不依赖RTTI,错误前置暴露于编译阶段。这一特性使其广泛应用于高性能场景,如STL容器、嵌入式协议解析及日志系统重构。理解模板的契约边界、推导规则与SFINAE原理,是写出可维护、跨平台、高可靠C++系统的前提。本文聚焦真实工程中的模板设计逻辑与避坑指

weixin_30920597的博客 367

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

链表在现代开发中为何被动态数组取代?从缓存局部性看数据结构选型

数据结构是计算机科学的基础,它定义了数据的组织、存储和操作方式,直接影响程序的性能和资源效率。在众多数据结构中,数组和链表是最基础的线性结构,数组通过连续内存存储实现快速随机访问,而链表则通过节点和指针实现动态扩展。从原理上看,链表在插入删除操作上具有O(1)的理论优势,但这一优势在现代硬件架构下被严重削弱。CPU缓存体系结构使得连续内存访问具有极高的效率,而链表的节点分散存储导致频繁的缓存缺失,这一性能差异在数据量较大时可达数量级。因此,在工程实践中,动态数组因其卓越的缓存友好性和内存局部性,成为应用层开

weixin_33794672的博客 357

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

C++插件框架实战:8大陷阱与解决方案

在软件架构中,插件化设计是实现模块化、可扩展性的核心技术,它允许系统在运行时动态加载功能模块。其原理基于动态链接库技术,通过定义清晰的接口规范实现主程序与插件间的通信。这种技术的核心价值在于提升系统的灵活性和可维护性,支持功能热插拔和团队并行开发。在实际应用中,插件框架广泛用于大型桌面软件、IDE工具、游戏引擎和服务器中间件等场景。然而,在C++环境下实现稳健的插件系统面临诸多挑战,特别是内存泄漏和版本兼容性问题。内存泄漏常因跨模块的资源管理不当引发,而版本兼容性则涉及ABI稳定性和接口演化策略。本文聚焦C

weixin_34054931的博客 667

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

一句话让你明白java中为什么没有指针

栈中的变量指向堆内存中的变量,这就是Java中的指针。

chuyueh的博客 5844

typedef 用法

typedef到处都是,但是能够真正懂得typedef使用的不算太多。对于初学者而言,看别人的源码时对到处充斥的typedef往往不知所错,而参考书又很少,所以在此给出一个源码,供大家参考 #include &lt;stdio.h&gt; #include &lt;iostream.h&gt; /* 避免Visual C的for与标准for的不同 */ #define for...

java开发指南博客 【转载】 1322

ignite客户端启动时无法连接服务端

异常 [21:01:02,094][SEVERE][main][IgniteKernal] Failed to startmanager:GridManagerAdapter[enabled=true, name=o.a.i.i.managers.discovery.GridDiscoveryManager]class org.apache.ignite.IgniteCheckedExcepti...

明天会更好 6268

你真的了解typedef 吗?

typedef ,#define

夜风的博客 3285

java泛型的学习总结

泛型的好处:可以在编译期间检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。 规则: 1、泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。 2、同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的泛型类实例是不兼容的。 3、泛型的类型参数可以有多个。 4、泛型的参数类型可以使用extends语句,例如。习惯上称为“有界类型”。

typedef_god的专栏 738

InnoDB 内存结构总览:Change Buffer、AHI 与 Log Buffer

本文系统梳理InnoDB内存结构中的ChangeBuffer、Adaptive Hash Index(AHI)与LogBuffer。ChangeBuffer缓存二级索引页不在内存时的变更,减少随机IO,仅在页加载时合并;聚簇索引修改立即执行,因数据本身不可延后。AHI基于高频等值查询自动构建哈希索引,加速定位,仅支持等值操作。LogBuffer为redo log内存缓冲,配合磁盘日志实现崩溃恢复。三者均服务于性能优化,其中ChangeBuffer与AHI共享BufferPool空间,而LogBuffer独立

bksczm的博客 301
上一篇: SUN认证Java2程序员考试(SCJP)试题解析-Java基础-Java-编程开发
下一篇: 写Java程序最容易犯的21种错误-Java基础-Java-编程开发
java169
博客等级 码龄19年 27粉丝 2568原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值