编码规约学习要点

news2025/3/1 13:36:35

工程结构应用分层

日志规约 

 编程规约 > 其它

【强制】日期格式化时,传入 pattern 中表示年份统一使用小写的 y。

说明:日期格式化时,yyyy 表示当天所在的年,而大写的 YYYY 代表是 week in which year(JDK7 之后引入的概念),意思是当天所在的周属于的年份,一周从周日开始,周六结束,只要本周跨年,返回的 YYYY 就是下一年。另外需要注意:
⚫ 表示月份是大写的 M
⚫ 表示分钟则是小写的 m 
⚫ 24 小时制的是大写的 H 
⚫ 12 小时制的则是小写的 h
正例:表示日期和时间的格式如下所示:
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

编程规约 > 并发处理

【强制】SimpleDateFormat 是线程不安全的类,一般不要定义为 static 变量,如果定义为static,必须加锁,或者使用 DateUtils 工具类。

正例:注意线程安全,使用 DateUtils。亦推荐如下处理:

private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>() { 
  @Override 
  protected DateFormat initialValue() { 
    return new SimpleDateFormat("yyyy-MM-dd"); 
  } 
}; 

说明:如果是 JDK8 的应用,可以使用 Instant 代替 Date,LocalDateTime 代替 Calendar,DateTimeFormatter 代替 SimpleDateFormat,官方给出的解释:simple beautiful strong immutable thread-safe。

 

【强制】在使用阻塞等待获取锁的方式中,必须在 try 代码块之外,并且在加锁方法与 try 代码块之间没有任何可能抛出异常的方法调用,避免加锁成功后,在 finally 中无法解锁。

说明一:如果在 lock 方法与 try 代码块之间的方法调用抛出异常,那么无法解锁,造成其它线程无法成功
获取锁。
说明二:如果 lock 方法在 try 代码块之内,可能由于其它方法抛出异常,导致在 finally 代码块中,
unlock 对未加锁的对象解锁,它会调用 AQS 的 tryRelease 方法(取决于具体实现类),抛出
IllegalMonitorStateException 异常。
说明三:在 Lock 对象的 lock 方法实现中可能抛出 unchecked 异常,产生的后果与说明二相同。
正例:
Lock lock = new XxxLock();
// ...
lock.lock();
try {
 doSomething();
 doOthers();
} finally {
 lock.unlock();
}
反例:
Lock lock = new XxxLock();
// ...
try {
 // 如果此处抛出异常,则直接执行 finally 代码块
 doSomething();
 // 无论加锁是否成功,finally 代码块都会执行
 lock.lock();
 doOthers();
} finally {
 lock.unlock();
}

 【强制】在使用尝试机制来获取锁的方式中,进入业务代码块之前,必须先判断当前线程是否持有锁。锁的释放规则与锁的阻塞等待方式相同。

说明:Lock 对象的 unlock 方法在执行时,它会调用 AQS 的 tryRelease 方法(取决于具体实现类),如果当前线程不持有锁,则抛出 IllegalMonitorStateException 异常。
正例:
Lock lock = new XxxLock();
// ...
boolean isLocked = lock.tryLock();
if (isLocked) {
 try {
   doSomething();
   doOthers();
 } finally {
   lock.unlock();
 } 
}

 12.【强制】多线程并行处理定时任务时,Timer 运行多个 TimeTask 时,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运行,如果在处理定时任务时使用ScheduledExecutorService 则没有这个问题。
13.【推荐】资金相关的金融敏感信息,使用悲观锁策略。

说明:乐观锁在获得锁的同时已经完成了更新操作,校验逻辑容易出现漏洞,另外,乐观锁对冲突的解决策略有较复杂的要求,处理不当容易造成系统压力或数据异常,所以资金相关的金融敏感信息不建议使用乐观锁更新。

17【参考】volatile 解决多线程内存不可见问题。对于一写多读,是可以解决变量同步问题,但是如果多写,同样无法解决线程安全问题。

说明:如果是 count++操作,使用如下类实现:AtomicInteger count = new AtomicInteger(); count.addAndGet(1); 如果是 JDK8,推荐使用 LongAdder 对象,比 AtomicLong 性能更好(减少乐观锁的重试次数)。

18.【参考】HashMap 在容量不够进行 resize 时由于高并发可能出现死链,导致 CPU 飙升,在开发过程中可以使用其它数据结构或加锁来规避此风险。
19.【参考】ThreadLocal 对象使用 static 修饰,ThreadLocal 无法解决共享对象的更新问题。、

说明:这个变量是针对一个线程内所有操作共享的,所以设置为静态变量,所有此类实例共享此静态变量,也就是说在类第一次被使用时装载,只分配一块存储空间,所有此类的对象(只要是这个线程内定义的)都可以操控这个变量。

编程规约 > 控制语句

【推荐】表达异常的分支时,少用 if-else 方式,这种方式可以改写成: 

if (condition) { 
 ... 
 return obj; 
} 
// 接着写 else 的业务逻辑代码; 
说明:如果非使用 if()...else if()...else...方式表达逻辑,避免后续代码维护困难,【强制】请勿超过 3 层。
正例:超过 3 层的 if-else 的逻辑判断代码可以使用卫语句、策略模式、状态模式等来实现,其中卫语句即代码逻辑先考虑失败、异常、中断、退出等直接返回的情况,以方法多个出口的方式,解决代码中判断分支嵌套的问题,这是逆向思维的体现。
示例如下:
public void findBoyfriend(Man man) {
 if (man.isUgly()) {
   System.out.println("本姑娘是外貌协会的资深会员");
   return;
 }
 if (man.isPoor()) {
   System.out.println("贫贱夫妻百事哀");
   return;
 }
 if (man.isBadTemper()) {
   System.out.println("银河有多远,你就给我滚多远");
   return;
 }
  System.out.println("可以先交往一段时间看看");
}

 编程规约 > 集合处理

【强制】使用 Map 的方法 keySet()/values()/entrySet()返回集合对象时,不可以对其进行添加元素操作,否则会抛出UnsupportedOperationException 异常。 

 14.【推荐】集合初始化时,指定集合初始值大小。

说明:HashMap 使用 HashMap(int initialCapacity) 初始化。
正例:initialCapacity = (需要存储的元素个数 / 负载因子) + 1。注意负载因子(即 loader factor)默认为 0.75,如果暂时无法确定初始值大小,请设置为 16(即默认值)。
反例:HashMap 需要放置 1024 个元素,由于没有设置容量初始大小,随着元素不断增加,容量 7 次被迫扩大,resize 需要重建 hash 表,严重影响性能。
15.【推荐】使用 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 值组合集合。
反例:由于 HashMap 的干扰,很多人认为 ConcurrentHashMap 是可以置入 null 值,而事实上,存储null 值时会抛出 NPE 异常。 

17.【参考】合理利用好集合的有序性(sort)和稳定性(order),避免集合的无序性(unsort)和不稳定性(unorder)带来的负面影响。

说明:有序性是指遍历的结果是按某种比较规则依次排列的。稳定性指集合每次遍历的元素次序是一定的。如:ArrayList 是 order/unsort;HashMap 是 unorder/unsort;TreeSet 是 order/sort。

11.关于基本数据类型与包装数据类型的使用标准如下:

【强制】所有的 POJO 类属性必须使用包装数据类型。
【强制】RPC 方法的返回值和参数必须使用包装数据类型。
【推荐】所有的局部变量使用基本数据类型。

说明:POJO 类属性没有初值是提醒使用者在需要使用时,必须自己显式地进行赋值,任何 NPE 问题,或者入库检查,都由使用者来保证。
正例:数据库的查询结果可能是 null,因为自动拆箱,用基本数据类型接收有 NPE 风险。
反例:比如显示成交总额涨跌情况,即正负 x%,x 为基本数据类型,调用的 RPC 服务,调用不成功时,返回的是默认值,页面显示为 0%,这是不合理的,应该显示成中划线。所以包装数据类型的 null 值,能够表示额外的信息,如:远程调用失败,异常退出。
12.【强制】定义 DO/DTO/VO 等 POJO 类时,不要设定任何属性默认值。
反例:POJO 类的 createTime 默认值为 new Date(),但是这个属性在数据提取时并没有置入具体值,在
更新其它字段时又附带更新了此字段,导致创建时间被修改成当前时间。

24.【推荐】类成员与方法访问控制从严:

如果不允许外部直接通过 new 来创建对象,那么构造方法必须是 private。
工具类不允许有 public 或 default 构造方法。
类非 static 成员变量并且与子类共享,必须是 protected。
类非 static 成员变量并且仅在本类使用,必须是 private。
类 static 成员变量如果仅在本类使用,必须是 private。
若是 static 成员变量,考虑是否为 final。
类成员方法只供类内部调用,必须是 private。
类成员方法只对继承类公开,那么限制为 protected。

说明:任何类、方法、参数、变量,严控访问范围。过于宽泛的访问范围,不利于模块解耦。思考:如果是一个 private 的方法,想删除就删除,可是一个 public 的 service 成员方法或成员变量,删除一下,不得手心冒点汗吗?变量像自己的小孩,尽量在自己的视线内,变量作用域太大,无限制的到处跑,那么你会担心的。

 

 

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第二证券|热门板块再次爆发,早盘主力抢筹超10亿元!

抗原检测、房地产概念股团体冲高&#xff0c;板块热度居高不下。 抗原检测概念股团体上涨 12月9日早盘&#xff0c;新冠抗原检测概念股团体上涨&#xff0c;概念指数涨4.74%&#xff0c;明德生物涨停&#xff0c;九安医疗、万孚生物、热景生物涨幅居前&#xff0c;分别上涨8.4…

【Window环境下使用MSYS2搭建CMake + MinGW环境】

目录标题安装CMakecmake 测试MSYS2下载MSYS2安装MSYS2修改软件下载源MSYS2下安装MinGW配置MinGW配置到环境变量hello world测试安装CMake Cmake下载地址:https://cmake.org/download/,下一个windows压缩包就好了&#xff0c;因为我比较喜欢自己来配置&#xff0c;免得不知道安…

嵌入式软件开发知识点总结-uboot文件系统

【推荐阅读】 浅析linux 系统进程冻结&#xff08;freezing of task&#xff09; 30分钟了解linux操作系统内核总结 深入linux内核架构--进程&线程 需要多久才能看完linux内核源码&#xff1f; 概述Linux内核驱动之GPIO子系统API接口 Uboot 什么是bootloader&#xff1f; …

Linux操作系统~进程崩溃的原理是什么?信号的产生方式有哪些?

目录 1.信号的概念 2.signal函数的使用 kill -l 自定义信号处理函数signal函数 3.进程异常/崩溃的原理 &#xff08;1&#xff09;.进程为什么会崩溃&#xff1f; &#xff08;2&#xff09;.如何知道进程崩溃/异常的原因 &#xff08;3&#xff09;.core dump的作用—…

C++类设计和实现的十大最佳实践

C代码提供了足够的灵活性&#xff0c;因此对于大部分工程师来说都很难把握。本文介绍了写好C代码需要遵循的10个最佳实践&#xff0c;并在最后提供了一个工具可以帮助我们分析C代码的健壮度。原文&#xff1a;10 Best practices to design and implement a C class 1. 尽可能尝…

Word处理控件Aspose.Words功能演示:使用 C# 将 Word 文档转换为 HTML

在各种情况下&#xff0c;您需要在 Web 或桌面应用程序中显示 Word 文档的内容。在这种情况下&#xff0c;合适的选项之一是将 Word 文档转换为HTML。为了在 .NET 应用程序中实现这一点&#xff0c;本文介绍了如何使用 C# 将 Word DOCX或DOC文件转换为 HTML。此外&#xff0c;您…

搅拌釜反应器全自动真空压力(正负压)控制解决方案

摘要&#xff1a;针对双层玻璃反应釜中存在的无法进行真空压力自动和准确控制等问题&#xff0c;本文提出了完整和成熟的解决方案&#xff0c;即采用卫生级电动调节阀和高精度双通道PID控制器&#xff0c;结合不同量程的真空计&#xff0c;与反应器、真空泵和正压气源构成闭环控…

ARP协议与ARP欺骗

一、ARP协议&#xff08;地址解析协议&#xff09; 所谓“地址解析”就是主机在发送帧前将目标IP地址转换成目标MAC地址的过程,ARP协议的基本功能就是通过目标设备的IP地址&#xff0c;查询目标设备的MAC地址&#xff0c;以保证通信的顺利进行。 将一个已知的IP地址解析为MAC…

169. 基于Django-RESTFramework的节流的使用

1.节流概述 节流又称限流&#xff0c;限制访问。 就是一个用户多次发送一个请求&#xff08;页面或者链接&#xff09;的时候&#xff0c;单位时间允许访问次数限制&#xff0c;超过限制就会出现访问受限&#xff0c;提示譬如&#xff1a;离下一场访问还有多久之类等的字样。 …

基于SSM的学生考勤管理系统的设计与实现

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

【学习笔记】顺序容器的表格方式总结 C++

目录顺序容器及其特点顺序容器操作向顺序容器添加元素insertemplace参考更新中… 顺序容器及其特点 名字访问元素插入&#xff0c;删除元素vector&#xff08;可变大小数组&#xff09;支持快速随机访问在尾部之外的位置插入或删除元素可能很慢deque&#xff08;双端队列&…

SpringBoot实战:整合MapStruct实现数据类型转化

MapStruct 是一个代码生成器&#xff0c;它基于约定优于配置方法极大地简化了 Java bean 类型之间映射的实现。自动生成的映射转换代码只使用简单的方法调用&#xff0c;因此速度快、类型安全而且易于理解阅读&#xff1b;本篇就是实现 SpringBoot 整合 MapStruct 实现数据类型…

[附源码]JAVA毕业设计小区物业管理系统演示录像2020(系统+LW)

[附源码]JAVA毕业设计小区物业管理系统演示录像2020&#xff08;系统LW&#xff09; 项目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09…

ffmpeg库安装及入门指南(Windows篇)- 2022年底钜献

最近项目需要&#xff0c;使用了 ffmpeg 做摄像头视频采集和串流。这几天有点时间&#xff0c;打算把相关的一些知识记录分享一下。 在撰写本文时&#xff0c;我又在另外一台电脑上把 ffmpeg 重新安装了一遍&#xff0c;所以绝对真实靠谱&#xff01;如果你觉得文章写得还不错…

代码效果测试

ROBUST TEXT DETECTION IN NATURAL IMAGES WITH EDGE ENHANCED MAXIMALLY STABLE EXTREMAL REGIONS 代码地址&#xff1a;https://github.com/akab/TextDetection 基本步骤&#xff1a; 1&#xff09;将原图转为灰度图&#xff1b; 2&#xff09;使用OpenCV的canny函数进行边…

HTML -- 常用标签及示例总结

文章目录HTML常用标签1 标签语义1.1 标签属性2 标题标签 h1 - h63 段落和换行标签3.1 段落标签3.2 换行标签4 文本格式化标签5 div和span6 图像标签7 超链接标签7.1 链接的语法格式7.2 链接分类8 表格标签8.1 表格的主要作用8.2 表格的基本语法8.3 表头单元格标签8.4 表格属性8…

C语言随机数的产生(rand、srand、time函数细节讲解)

✨C语言随机数的产生随机数生成代码&#xff1a;rand函数&#xff1a;srand函数&#xff1a;time函数&#xff1a;time函数补充:time_t类型讨论time_t指针传入的讨论&#xff1a;随机数生成代码&#xff1a; 先上代码&#xff0c;再详细解释&#xff1a; #include<stdio.h…

Python数组数据处理办法清单

import numpy as np import pandas as pd import matplotlib.pyplot as plt#matplotlib 的字体&#xff08;font&#xff09;为黑体&#xff08;SimHei&#xff09; plt.rcParams[font.sans-serif] [SimHei, ] # matplotlib正确显示正负号 plt.rcParams[axes.unicode_minus] …

dfs序(树形结构线性化)

dfs序是将树形结构转换为线性结构的一种方式。 dfs序 dfs序&#xff1a; 指每个节点在dfs深度优先遍历中的进出栈的时间序列。 定义三个数组&#xff1a; in[x]&#xff1a;表示结点x 入栈的时间戳。 out[x]&#xff1a;表示结点x出栈的时间戳&#xff0c;特殊的&#xff0c;出…

Linux网络原理及编程(5)——第十五节 TCP的连接(三次握手、四次挥手)

目录 三次握手 四次挥手 我们来重点说说两个状态&#xff1a;CLOSE_WAIT和TIME_WAIT 【CLOSE_WAIT】 【TIME_WAIT】 各位好&#xff0c;博主新建了个公众号《自学编程村》&#xff0c;拉到底部即可看到&#xff0c;有情趣可以关注看看哈哈&#xff0c;关注后还可以加博主w…