阿里巴巴Java开发规范学习——编程规约(2)

阿里巴巴Java开发规范学习——编程规约(2)

编程规约

(三) 代码格式

1.【强制】单行字符数限制不超过 120 个,超出需要换行,换行时遵循如下原则:

1) 第二行相对第一行缩进 4 个空格,从第三行开始,不再继续缩进,参考示例。
2) 运算符与下文一起换行。
3) 方法调用的点符号与下文一起换行。
4) 方法调用中的多个参数需要换行时,在逗号后进行。
5) 在括号前不要换行,见反例。

正例:

StringBuffer sb = new StringBuffer();
// 超过 120 个字符的情况下,换行缩进 4 个空格,点号和方法名称一起换行
sb.append("zi").append("xin")...
.append("huang")...
.append("huang")...
.append("huang");

反例:

StringBuffer sb = new StringBuffer();
// 超过 120 个字符的情况下,不要在括号前换行
sb.append("zi").append("xin")...append
("huang");
// 参数很多的方法调用可能超过 120 个字符,不要在逗号前换行
method(args1, args2, args3, ...
, argsX)
2. 【推荐】单个方法的总行数不超过 80 行。

说明: 包括方法签名、结束右大括号、方法内代码、注释、空行、回车及任何不可见字符的总
行数不超过80 行。
正例: 代码逻辑分清红花和绿叶,个性和共性,绿叶逻辑单独出来成为额外方法,使主干代码
更加清晰;共性逻辑抽取成为共性方法,便于复用和维护。

(四)OOP 规约

OOP(面向对象编程)规约

1. 【强制】避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接用类名来访问即可。
2. 【强制】所有的覆写方法,必须加@Override 注解。

说明: getObject()与get0bject()的问题。一个是字母的 O,一个是数字的 0,加@Override可以准确判断是否覆盖成功。另外,如果在抽象类中对方法签名进行修改,其实现类会马上编
译报错。

3. 【强制】相同参数类型,相同业务含义,才可以使用 Java 的可变参数,避免使用 Object。

说明: 可变参数必须放置在参数列表的最后。(倡同学们尽量不用可变参数编程)
正例: public List listUsers(String type, Long… ids) {…}

4. 【强制】外部正在调用或者二方库依赖的接口,不允许修改方法签名,避免对接口调用方产生影响。接口过时必须加@Deprecated 注解,并清晰地说明采用的新接口或者新服务是什么。
5. 【强制】Object 的equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用equals。

正例: “test”.equals(object);
反例: object.equals(“test”);
说明:推荐使用java.util.Objects#equals(JDK7 引入的工具类)

6. 【强制】所有的相同类型的包装类对象之间值的比较,全部使用equals 方法比较。

说明:包装类中,equals()方法被设计为基于它们所封装的基本类型值进行比较,从而提供正确的逻辑结果。

相比之下,如果使用==运算符直接比较两个包装类对象,实际上是在比较它们的引用是否指向内存中的同一位置,而非比较它们所封装的值。

只有在以下两种特定情况下,使用==比较包装类对象会得到与equals()方法相同的值比较结果:

比较的是同一个对象实例:即两个引用指向内存中的同一块区域,此时和equals()都会返回true。
比较的是两个缓存范围内的相同小整数值的包装对象(仅对Integer、Byte、Short、Character、Long五种整数型包装类适用):例如,-128至127之间的Integer对象会被自动装箱为常量池中的单例对象。因此,对于这个范围内的值,使用
比较也会得到正确的结果。但超出此范围的整数值或非整数型包装类对象不适用此规则。
然而,由于上述第二种情况依赖于JVM的具体实现且并不适用于所有包装类,为了代码的通用性、可读性和避免潜在的错误,强烈建议在比较所有相同类型的包装类对象的值时,一律使用equals()方法。这样可以确保无论对象的创建方式如何,都能准确地按照其封装的基本类型值进行比较。

Java中的包装类共有以下八种,它们分别对应于Java的八种基本数据类型:

  1. Byte - 对应于基本类型 byte
  2. Short - 对应于基本类型 short
  3. Integer - 对应于基本类型 int
  4. Long - 对应于基本类型 long
  5. Float - 对应于基本类型 float
  6. Double - 对应于基本类型 double
  7. Boolean - 对应于基本类型 boolean
  8. Character - 对应于基本类型 char

⚠️补充:BigDecimal不是包装类。
BigDecimal类提供了equals()方法来比较两个BigDecimal对象是否相等,但是这种比较方法是严格的,它要求两个对象的值和精度都必须完全相同才会返回true。

对于需要考虑精度而不是严格相等的比较,最好使用compareTo()方法。

7. 关于基本数据类型与包装数据类型的使用标准如下:
  • 1) 【强制】所有的 POJO 类属性必须使用包装数据类型。
  • 2) 【强制】RPC 方法的返回值和参数必须使用包装数据类型。
  • 3) 【推荐】所有的局部变量使用基本数据类型。
    说明:POJO 类属性没有初值是醒使用者在需要使用时,必须自己显式地进行赋值,任何
    NPE 问题 (NullPointerException空指针异常),或者入库检查,都由使用者来保证。
    正例:数据库的查询结果可能是 null,因为自动拆箱,用基本数据类型接收有 NPE 风险。
    反例:比如显示成交总额涨跌情况,即正负 x%,x 为基本数据类型,调用的 RPC 服务,调用
    不成功时,返回的是默认值,页面显示为0%,这是不合理的,应该显示成中划线。所以包装
    数据类型的null 值,能够表示额外的信息,如:远程调用失败,异常退出。

推荐在Java编程中所有的局部变量使用基本数据类型,主要是出于以下几个原因:

  1. 内存效率

    • 基本数据类型(如 int, boolean, double 等)直接在栈内存中存储其实际值,占用的空间较小且固定。相比而言,包装类对象(如 Integer, Boolean, Double 等)不仅需要在栈内存中存储对象引用,还在堆内存中分配空间存储实际值,这导致了额外的内存开销。对于局部变量,特别是在循环、大规模计算等场景下,大量使用包装类可能会显著增加内存消耗。
  2. 性能优化

    • 直接操作基本数据类型通常比操作包装类更快。这是因为基本类型的操作通常涉及简单的CPU指令,而对包装类对象的操作往往涉及到方法调用(如访问器方法、equals()、hashCode()等),这些方法调用会产生额外的开销。尤其是在频繁进行数值计算或比较的代码段中,使用基本数据类型可以减少方法调用和对象交互的延迟,提升程序运行速度。
  3. 避免自动装箱/拆箱

    • Java提供了自动装箱(将基本类型转换为对应的包装类对象)和自动拆箱(将包装类对象转换回基本类型)功能,以方便在需要对象的地方使用基本类型。然而,这种隐式转换并非无成本,它会在运行时产生额外的字节码指令。特别是当装箱/拆箱操作频繁发生时,会引入不必要的性能损耗。直接使用基本数据类型可以避免这些无谓的性能损失。
  4. 简洁性和可读性

    • 使用基本数据类型可以使代码更简洁,减少对包装类对象创建、初始化和管理的复杂性。此外,对于熟悉基本类型的程序员来说,直接看到和操作基本类型更容易理解和维护代码。尤其是在局部变量作用域较小、生命周期较短的情况下,使用基本数据类型有助于保持代码的清晰度。
  5. 避免空指针异常

    • 当使用包装类对象时,如果不小心处理,可能会遇到NullPointerException。例如,如果一个局部变量被初始化为null,后续在未检查其是否为null的情况下直接访问其值,就会抛出异常。而基本数据类型不存在null值,因此避免了这类问题。

综上所述,推荐所有局部变量使用基本数据类型主要是为了提高内存效率、优化性能、避免自动装箱/拆箱带来的开销、保持代码简洁易读以及避免空指针异常。当然,在某些特定场景下,如需要利用包装类提供的特有方法(如Integer.toHexString())、需要放入容器类中(如List<Integer>)或者进行泛型编程时,使用包装类仍然是必要的。但在一般情况下,特别是在局部变量的使用中,优先考虑基本数据类型是一个良好的编程习惯。

8. 【强制】序列化类新增属性时,请不要修改 serialVersionUID 字段,避免反序列失败;如果完全不兼容升级,避免反序列化混乱,那么请修改 serialVersionUID 值。

说明:注意serialVersionUID不一致会抛出序列化运行时异常。

在Java中,serialVersionUID 是一个用来标识类版本的固定不变的 long 类型值,主要用于Java对象的序列化和反序列化过程。它的重要性体现在以下几个方面:

  1. 版本控制

    • 当一个类被序列化时,它的 serialVersionUID 值会被写入到序列化的字节流中。在反序列化时,Java运行环境会检查传入字节流中的 serialVersionUID 是否与当前类定义的 serialVersionUID 相匹配。如果两者不一致,反序列化将会失败,抛出 InvalidClassException
  2. 兼容性管理

    • 如果在不改变 serialVersionUID 的情况下对类进行了修改(如新增、删除或修改属性),只要这些修改不影响已序列化对象的字段布局(即不影响已有字段的顺序、类型和名称),反序列化仍能成功。这是因为Java序列化机制允许在保持字段布局不变的前提下,对类进行向后兼容的修改。

基于以上原理,关于 serialVersionUID 的使用有以下建议:

新增属性时,请不要修改 serialVersionUID 字段

  • 当你对一个已经序列化的类进行扩展,如新增属性,且这些改动不会影响已序列化对象的字段布局时,不应修改 serialVersionUID。保持原有 serialVersionUID 不变,可以让新版本类与旧版本序列化数据兼容,确保反序列化过程顺利进行。

如果完全不兼容升级,避免反序列化混乱,那么请修改 serialVersionUID

  • 当对类的改动较大,如删除或修改已有字段,或者新增字段改变了已有字段的顺序,使得新版本类无法与旧版本序列化数据兼容时,应该修改 serialVersionUID。通过改变 serialVersionUID,可以防止旧版本的序列化数据被误用在新版本类上进行反序列化,从而避免因字段不匹配导致的反序列化混乱和潜在运行时错误。

总结来说,serialVersionUID 是管理类版本和保证序列化兼容性的重要工具。在对序列化类进行修改时,应根据改动的性质和对兼容性的影响,决定是否需要更新 serialVersionUID。新增属性时通常不需要修改,除非这些改动导致了类的不兼容升级。在进行不兼容升级时,主动修改 serialVersionUID 可以防止反序列化错误和潜在的数据混乱。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/554528.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MES管理系统生产物料管理流程设计的注意事项

随着现代制造业的迅猛发展&#xff0c;MES管理系统在生产物料管理中所扮演的角色愈发重要。一个高效、精准的MES管理系统能够显著提升物料管理的效率&#xff0c;确保生产流程的顺畅进行。然而&#xff0c;在设计生产物料管理流程时&#xff0c;我们需要注意一系列关键问题&…

预选小标题

海岛,广东小岛 汕头 南澳岛(推荐) 距离东凤镇 500公里 珠海 需要坐船出海, 到达珠海码头 75公里 东澳岛, 桂山岛 海岛基本都差不多 阳江市海陵岛 可以赶海 距离东凤镇 240公里 江门 川岛, 下川岛 可下海 距离东凤镇 150公里 山林丹霞地貌 韶关 丹霞景区, 韶石景区,巴寨景…

【AI】DeepStream(01)介绍

1、简介 DeepStream 本质是 GStreamer 的插件,基于GStreamer的管道,实现高效的视频流分析。 DeepStream 将来自 USB/CSI 摄像头的流数据、来自文件的视频或通过 RTSP 的流作为输入,并使用人工智能和计算机视觉从像素中生成AI结果。 DeepStream SDK 可以成为许多视频分析解…

【MySQL 数据宝典】【内存结构】- 001 BufferPool

一、 BufferPool BufferPool 官方文档地址 1.1 什么是 Buffer Pool Buffer Pool 概述&#xff1a; Buffer Pool 是 InnoDB 存储引擎用于缓存磁盘中页的内存区域&#xff0c;它的大小直接影响数据库的性能。 默认大小和调整&#xff1a; 默认情况下&#xff0c;Buffer Pool…

[spring] rest api security

[spring] rest api security 之前的 rest api CRUD 都没有实现验证&#xff08;authentication&#xff09;和授权&#xff08;Authorization&#xff09;&#xff0c;这里使用 Spring security 进行补全 spring security 是一个非常灵活、可延伸的实现方式&#xff0c;比较简…

初识LangChain的快速入门指南

LangChain 概述 LangChain是一个基于大语言模型用于构建端到端语言模型应用的框架&#xff0c;它提供了一系列工具、套件和接口&#xff0c;让开发者使用语言模型来实现各种复杂的任务&#xff0c;如文本到图像的生成、文档问答、聊天机器人等。 LangChain简化了LLM应用程序生…

PostCSS概述和应用

文章目录 PostCSS概述**核心特性与工作原理&#xff1a;****应用场景与优势&#xff1a;****社区与生态&#xff1a;** PostCSS应用实例 PostCSS概述 PostCSS 是一款开源的、用 JavaScript 编写的 CSS 处理工具&#xff0c;其核心设计理念是利用 JavaScript 的强大编程能力和丰…

51-40 Align your Latents,基于LDM的高分辨率视频生成

由于数据工程、仿真测试工程&#xff0c;咱们不得不进入AIGC图片视频生成领域。兜兜转转&#xff0c;这一篇与智驾场景特别密切。23年4月&#xff0c;英伟达Nvidia联合几所大学发布了带文本条件融合、时空注意力的Video Latent Diffusion Models。提出一种基于LDM的高分辨率视…

synchronized的优化策略^o^

synchronized 特点&#xff1a; 开始是乐观锁&#xff0c;如果锁冲突&#xff0c;就转换为悲观锁开始是轻量级锁&#xff0c;如果锁被持有的时间较长&#xff0c;就转换为重量级锁实现轻量级锁的时候大概率用到的是自旋锁策略是一种不公平锁是一种可重入锁不是读写锁 synchro…

【考研数学】《1800》《660》《880》如何选择及搭配?看这一篇!

可以刷880&#xff01;但一定要把心态稳住&#xff01;&#xff01;&#xff01; 我考研的时候刷880前几章还可以&#xff0c;越往后越刷不动 因为很多人在备考前两轮的后期听课和刷题都不如前几章细心...越往后知识点掌握的越来越不熟练&#xff0c;所以也建议大家在前几轮复…

Kafka复习

消息中间件的作用: 异步处理: 与并行相比,虽然减少了时间,但是还是得等待其他线程执行完,但是消息中间件对于简单的业务处理,还要引入一个中间件也比较复杂如果我投递了简历之后需要发送成功邮件以及短信,就可以交给消息中间件就像数据库、redis数据一致性,需要用到延迟…

VScode使用记录

代码颜色是白色 发现没有根据对应的文本类型显示颜色 解决方法&#xff1a; 效果&#xff1a;

「sentinel」流量控制组件的应用

「sentinel」流量控制组件的应用 Sentinel版本QPS 一、初识Sentinel1、Sentinel2、Sentinel 和 Hystrix对比3、雪崩问题 二、环境搭建1、下载安装Sentinel2、微服务整合Sentinel 三、流量控制1、簇点链路2、流控设置3、流控模式直接关联链路 4、流控效果流控效果解释 四、热点限…

线性表的链式存储(循环链表)

文章目录 前言一、循环链表是什么&#xff1f;二、循环链表的操作实现总结 前言 T_T此专栏用于记录数据结构及算法的&#xff08;痛苦&#xff09;学习历程&#xff0c;便于日后复习&#xff08;这种事情不要啊&#xff09;。所用教材为《数据结构 C语言版 第2版》严蔚敏。有关…

Codeforces Round 939 (Div. 2) A~E

A.Nene’s Game&#xff08;循环&#xff09; 题意&#xff1a; 妮妮发明了一种基于递增序列 a 1 , a 2 , … , a k a_1,a_2,\ldots,a_k a1​,a2​,…,ak​的新游戏。 在这个游戏中&#xff0c;最初 n n n个玩家排成一排。在这个游戏的每一轮中&#xff0c;都会发生以下情况…

详解SPI通信协议以及FPGA实现

文章目录 一、SPI简介二、SPI通信结构三、多从机模式四、时钟极性&#xff08;CPOL&#xff09;和时钟相位&#xff08;CPHA&#xff09;五、SPI通信过程六、实现SPI主机发送程序6.1 波形图分析6.2 Verilog代码6.3 发送数据控制模块6.4 仿真代码编写以及仿真结果分析 七、Veril…

Kubernetes Pod的配置管理 ConfigMap和Secret

目录 前言 一、为什么需要配置管理 二、使用ConfigMap管理Pod的配置信息 2.1 创建ConfigMap&#xff08;4种方式&#xff09; 2.1.1 指定ConfigMap的参数创建 2.1.2 指定配置文件创建ConfigMap 2.1.3 通过一个文件内的多个键值对创建ConfigMap 2.1.4 yaml文件创建Config…

Android 性能优化(七):APK安装包体积优化

包体积优化重要性 移动 App 特别关注投放转化率指标&#xff0c;而 App 包体积是影响用户新增的重要因素&#xff0c;而 App 的包体积又是影响投放转化率的重要因素。 Google 2016 年公布的研究报告显示&#xff0c;包体积每上升 6MB 就会带来下载转化率降低 1%&#xff0c; …

114 接口中幂等性的保证

前言 同样是 面试问题 如何确保接口的 幂等性 幂等是一个 较为抽象的概念, 多次重复访问, 不会导致业务逻辑的异常 这里从增删改查, 几个方面列一下 一般来说, 我们核心需要关注的就是 新增 和 更新 对于 增加元素, 首先针对唯一约束进行校验, 然后再处理新增的相关业…

二刷大数据(三)- Flink1.17

目录 Flink概念与SparkStreaming区别分层API 工作流程部署模式**Local Mode****Standalone Mode****YARN Mode****Kubernetes Mode****Application Mode** 运行架构stand alone 核心概念算子链任务槽 窗口窗口**窗口的目的与作用****时间窗口&#xff08;Time Windows&#xff…
最新文章