阿里巴巴Java开发规范——编程规约(3)

# 阿里巴巴Java开发规范——编程规约(3)

编程规约

(四) OOP规约

1.【强制】构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在 init 方法中

这条编程规范的目的是为了保持代码的清晰性、可读性和维护性。具体解释如下:

  1. 清晰性:构造函数的主要职责是初始化对象的基本属性,使其达到可用状态。如果在构造函数中混入复杂的业务逻辑,会使构造过程变得模糊不清,阅读者需要花费更多精力去理解这个构造函数究竟做了什么。将业务逻辑移至单独的 init 方法中,可以使构造过程专注于对象的初始化,业务逻辑则集中在一个明确命名的方法中,提高了代码的清晰度。

  2. 可读性:构造函数通常在创建对象时被调用,其内部逻辑应当一目了然。如果包含业务逻辑,尤其是较为复杂的逻辑,会增加代码阅读难度,影响开发人员对类功能和行为的理解。将业务逻辑封装在 init 方法中,并通过方法名清晰地表明其作用,有助于提高代码的可读性。

  3. 维护性:当业务需求发生变化时,如果业务逻辑嵌套在构造函数中,修改或扩展这些逻辑可能会牵涉到构造函数本身,增加修改风险。将业务逻辑分离到独立的 init 方法,使得改动更加局部化,降低了对构造过程的影响,提升了代码的维护性。同时,这样的设计也便于进行单元测试,可以针对 init 方法单独编写测试用例,确保业务逻辑的正确性。

  4. 灵活性:有时候,对象可能需要在不同的场景下进行不同程度的初始化。如果业务逻辑在构造函数中,那么每次创建对象时都会执行这些逻辑,无法根据实际需求进行灵活调整。而将业务逻辑放在 init 方法中,可以根据需要选择是否调用、何时调用以及如何调用该方法,增加了代码的灵活性。

综上所述,遵循“构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在 init 方法中”这一规范,有利于提升代码的清晰性、可读性、维护性和灵活性。在实际编程中,应尽量保持构造函数简洁明了,仅用于设置对象的基本属性,将复杂的业务逻辑封装在专门的方法(如 init)中处理。

2. 【强制】POJO 类必须写 toString 方法。使用 IDE 中的工具:source> generate toString时,如果继承了另一个 POJO 类,注意在前面加一下 super.toString。

说明:在方法执行抛出异常时,可以直接调用 POJO 的toString()方法打印其属性值,便于排查问题。

3. 【推荐】循环体内,字符串的连接方式,使用 StringBuilder 的 append 方法进行扩展。

说明: 下例中,反编译出的字节码文件显示每次循环都会 new 出一个 StringBuilder 对象,
然后进行append 操作,最后通过 toString 方法返回String 对象,造成内存资源浪费。

反例:

String str = "start";
for (int i = 0; i < 100; i++) {
str = str + "hello";
}

(五) 集合处理

1. 【强制】关于hashCode 和equals 的处理,遵循如下规则:

1) 只要重写 equals,就必须重写hashCode。
2) 因为 Set 存储的是不重复的对象,依据 hashCode 和equals 进行判断,所以 Set 存储的
对象必须重写这两个方法。

3) 如果自定义对象作为Map 的键,那么必须重写 hashCode 和equals。
说明:String 重写了hashCode 和equals 方法,所以我们可以非常愉快地使用 String 对象
作为key 来使用。

在 Java 中,如果一个类重写了 equals() 方法,那么通常也应该同时重写 hashCode() 方法。原因在于,这两个方法在 Java 的集合框架(如 HashMapHashSet 等)以及对象相等性的语义中扮演着重要且相互关联的角色。具体解释如下:

  1. 一致性要求:根据 Object 类中 equals()hashCode() 方法的约定,对于任何非空对象 x,多次调用 x.hashCode() 应该返回相同的哈希码。同时,如果 x.equals(y)true,那么 x.hashCode()y.hashCode() 必须相等。这就是所谓的“相等的对象必须具有相等的哈希码”。如果不重写 hashCode(),默认实现可能无法满足这一要求,导致集合类的行为不符合预期。

  2. 集合类性能HashMapHashSet 等基于散列的集合类依赖于 hashCode() 方法来快速定位元素。它们首先计算对象的哈希码,然后将其映射到一个桶(bucket)中。如果两个相等的对象具有不同的哈希码,它们会被分配到不同的桶中,导致在查找、添加、删除等操作时效率降低,甚至可能导致无法找到已存在的对象。因此,当重写 equals() 改变了对象相等性的判断规则时,也需要相应地重写 hashCode(),确保相等对象的哈希码一致,以维持集合类的高效运作。

  3. API 合约:Java 官方文档明确指出,如果一个类覆盖了 equals() 方法,那么它必须也要覆盖 hashCode() 方法。这是为了保持 Java 集合框架的一致性和正确性。违反这一约定可能会导致程序在使用集合类时出现难以预料的问题。

示例:

假设有一个 Person 类,包含 nameage 属性,并且我们希望两个 Person 对象在 name 相同且 age 相同时被视为相等。此时,我们需要同时重写 equals()hashCode() 方法:

public class Person {
    private String name;
    private int age;

    // 构造函数、getter/setter...

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (!(obj instanceof Person)) return false;
        Person other = (Person) obj;
        return Objects.equals(name, other.name) && age == other.age;
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

在这个例子中,我们不仅重写了 equals() 方法,使其基于 nameage 判断对象相等性,还同时重写了 hashCode() 方法,使用 Objects.hash() 工具方法生成一个基于 nameage 的哈希码。这样,当两个 Person 对象相等时,它们的哈希码也必然相等,符合集合类的要求。

总之,只要重写 equals() 方法,就必须同时重写 hashCode() 方法,以确保对象相等性的一致性、维持基于散列的集合类的性能,并遵守 Java API 的约定。

2. 【【强制】不要在foreach 循环里进行元素的remove/add 操作。remove 元素请使用Iterator方式,如果并发操作,需要对 Iterator 对象加锁。

正例:

List<String> list = new ArrayList<>();
list.add("1");
list.add("2");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
if (删除元素的条件) {
iterator.remove();
}
}

反例::

for (String item : list) {
if ("1".equals(item)) {
list.remove(item);
}
}
3. 【推荐】集合初始化时,指定集合初始值大小。

说明: HashMap 使用 HashMap(int initialCapacity) 初始化。
正例: initialCapacity = (需要存储的元素个数 / 负载因子) + 1。 注意负载因子 (即loader
factor)默认为0.75,如果暂时无法确定初始值大小,请设置为 16(即默认值)。
反例:HashMap 需要放置1024 个元素,由于没有设置容量初始大小,随着元素不断增加,容
量7 次被迫扩大,resize 需要重建hash 表,严重影响性能。

4. 【推荐】使用entrySet 遍历Map 类集合KV,而不是keySet 方式进行遍历。

说明: keySet 其实是遍历了 2 次,一次是转为 Iterator 对象,另一次是从 hashMap 中取出
key 所对应的value。而entrySet 只是遍历了一次就把 key 和value 都放到了entry 中,效
率更高。如果是JDK8,使用Map.foreach 方法。
正例: values()返回的是 V 值集合,是一个list 集合对象;keySet()返回的是K 值集合,是
一个Set 集合对象;entrySet()返回的是K-V 值组合集合。

5. 【推荐】集合泛型定义时,在JDK7 及以上,使用diamond 语法或全省略。

说明:菱形泛型,即 diamond,直接使用<>来指代前边已经指定的类型。
正例:

// <> diamond 方式
HashMap<String, String> userCache = new HashMap<>(16);
// 全省略方式
ArrayList<User> users = new ArrayList(10);
6. 【推荐】高度注意 Map 类集合K/V 能不能存储 null 值的情况,如下表格:

在这里插入图片描述

反例: 由于HashMap 的干扰,很多人认为ConcurrentHashMap 是可以置入 null 值,而事实上,
存储null 值时会抛出NPE 异常。

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

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

相关文章

怎么理解算力?1000P算力是什么概念?

算力&#xff0c;指计算机系统在单位时间内能够完成的计算任务量&#xff0c;它涵盖了CPU、GPU、TPU等硬件&#xff0c;每秒能处理的数据量&#xff0c;通常以“P”&#xff08;PetaFLOPS&#xff0c;即千万亿次浮点运算每秒&#xff09;为单位来衡量&#xff0c;是评估计算机性…

【笔试强训】day8

没啥好说&#xff0c;都是一遍过 1.求最小公倍数 思路&#xff1a; 求lcm。其实就是两数之乘积除以两个数的gcd。gcd就是是求两个数的最大公约数。 代码&#xff1a; #define _CRT_SECURE_NO_WARNINGS 1 #include <iostream> using namespace std;int gcd(int a, int …

虚拟线程的定义及使用

0.前言 长期以来&#xff0c;虚拟线程是 Java 中最重要的创新之一。 它们是在 Project Loom 中开发的&#xff0c;自 Java 19 作为预览功能以来一直包含在 JDK 中&#xff0c;自 Java 21 作为最终版本 (JEP 444) 以来&#xff0c;它们已包含在 JDK 中。 1.虚拟线程的作用 任…

【C++】双指针算法:复写零

1.题目 别看这是一道简单题&#xff0c;它的通过率低于一些中等甚至困难的题目&#xff01; 大大增加这道题目难度的是最后一句话&#xff1a;1.不可越界写入。2.就地修改。 如果可以再创建一个数组的话&#xff0c;那么这道题目就会非常简单&#xff0c;但这道题目必须要求在…

网络工程师---第十天

ARP表&#xff1a; 提起ARP表必然先想起ARP&#xff08;address resolution protocol&#xff09;协议&#xff0c;地址解析协议。 在实际应用中&#xff0c;我们经常遇到这样的问题&#xff1a;已知一个机器的IP地址&#xff0c;但在实际网络的链路上传送数据帧时&#xff0c;…

Redis安装部署教程

文章目录 Redis安装部署 Redis安装部署 &#xff08;1&#xff09; 下载xx.msi安装包&#xff0c;可以通过该下载地址进行下载。 &#xff08;2&#xff09; 双击下载的安装包进行安装。 &#xff08;3&#xff09; 选择安装目录&#xff08;默认C盘&#xff09;&#xff…

Kali Linux扩容(使用图形化界面)

因为今天在拉取vulhub中的镜像的时候报错空间不够&#xff0c;因为最开始只给了20GB的空间&#xff0c;所以现在需要扩容了&#xff0c;结合了一下网上的找到了简便的解决方法 1.首先虚拟机设置->磁盘->扩展 小插曲&#xff1a;在对虚拟机磁盘进行扩容以后&#xff0c;…

Flask-SQLAlchemy 中使用显式主主数据库设置

1、问题背景 在一个 Flask-SQLAlchemy 项目中&#xff0c;用户想要使用显式主主数据库设置。具体而言&#xff0c;他想要能够从默认数据库中读取数据&#xff0c;并将数据持久化到两个主数据库中。他希望知道是否可以使用 Flask-SQLAlchemy 和 binds 来实现这一目标。 2、解决…

解决宝塔面板无法访问(无法访问或拒绝链接)

&#x1f40c;博主主页&#xff1a;&#x1f40c;​倔强的大蜗牛&#x1f40c;​ &#x1f4da;专栏分类&#xff1a;Linux ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 问题如下&#xff1a; 本人设置了授权IP&#xff0c;但是有些问题&#xff0c;所以是打算取消授权IP 重…

使用QQ邮箱进行登录验证

使用场景不多说&#xff0c;接下来直接看实现~ 登录到QQ邮箱&#xff0c;进入设置 打开IMAP/SMTP服务&#xff0c;记得把授权码记录下来&#xff0c;后面配置文件中需要用到 新建application的配置文件 spring:mail:# 指定邮件服务器地址host: smtp.qq.comusername: 你自己的q…

分布式与一致性协议之拜占庭将军问题(一)

拜占庭将军问题 概述 拜占庭将军问题其实是借拜占庭将军故事展现了分布式共识问题&#xff0c;探讨和论证了解决的办法。实际上&#xff0c;拜占庭将军问题是分布式领域最复杂的一个容错模型&#xff0c;一旦搞懂了它&#xff0c;久能掌握分布式共识问题的解决思路&#xff0…

NTLM认证

文章目录 1.概念(1) 本地认证(2) SAM(3) NTLM Hash(4) NTLM 和 NTLM Hash(5) NTLM v2 1.概念 (1) 本地认证 Windows不存储用户的明文密码&#xff0c;它会将用户的明文密码经过加密后存储在 SAM (Security Account Manager Database&#xff0c;安全账号管理数据库)中。 (2)…

Marching Cubes算法

Marching Cubes算法 1. 简介2. 算法原理的理解2.1 如何找到面经过的这些小块(六面体)&#xff1f;2.2 找到后&#xff0c;如何又进一步的找到面与这些小块(六面体)的交点&#xff1b;2.3 这些交点按照怎么的拓扑连接关系连接&#xff0c;是怎么操作的&#xff1f; 3. 总结4. 参…

【链表】Leetcode 两数相加

题目讲解 2. 两数相加 算法讲解 我们这里设置一个头结点&#xff0c;然后遍历两个链表&#xff0c;使用一个flag记录相加的结果和进位&#xff0c;如果两个链表没有走到最后或者进位不等于0&#xff0c;我们就继续遍历处理进位&#xff1b;如果当前的链表都遍历完成了&#x…

基于springboot实现的摄影跟拍预定管理系统

开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven…

【系统分析师】多媒体技术与知识产权标准化

文章目录 一、多媒体技术1、音频2、图像3、媒体的分类4、有损压缩和无损压缩5、多媒体标准 二、知识产权标准化1、保护范围和对象2、保护期限3、知识产权人确定4、侵权判定5、标准化 一、多媒体技术 1、音频 # 声音文件格式 .wav .mp3 .ra .mid .snd .au .aif .voc2、图像 # 彩…

一招下载transformers真不用网上那些教程(我试了1*mol多次才知道)

pip很多是2 然而&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;…

ASP.NET大文件分片上传

ASP.NET大文件分片上传&#xff0c;C#上传大型视频文件到服务器,解决方案&#xff0c;用C# 实现断点续传 (HTTP)&#xff0c;ASP.NET实现文件夹的上传和下载&#xff0c;.NET使用WEBUPLOADER做大文件的分块和断点续传&#xff0c;ASP.NET实现文件上传和下载&#xff0c;完美解决…

fastgpt、dify功能分析比较

目录 前言 一、dify、fastgpt是什么&#xff1f; 二、同场pk 1.大模型接入 2.chat&#xff08;最简应用&#xff09; 3.发布应用 4.知识库 5.workflow 6.其他 三、一些point记录 总结 前言 现在都开始AI应用开发&#xff0c;何谓AI应用&#xff0c;起码要和AI大模型…

13-LINUX--消息队列

一.消息队列 1.消息队列&#xff1a;消息队列为一个进程向另一个进程发送一个数据块提供了条件&#xff0c;每个数据块会包含一个类型。 2.相关函数 1>.msgget(key_t key,int msgflg) : 创建消息队列 2>. msgsnd&#xff1a;把消息添加到消息队列 3>.msgrcv &#xf…