干货!java代码规范汇总,看了绝对不会让你失望

作为一名开发人员,当你接手他人的项目时,且当你阅读他人的代码时,是否急火攻心,暴跳如雷过,甚至有着大爆粗口的想法,此时的你看着那些密密麻麻的代码就如同天书一般,羞涩难懂。反正我是有过,你们呢?

Robert Martin曾说过"在代码阅读中说脏话的频率是衡量代码质量额唯一标准"。当你发现别人看你的代码时频频点头,甚至投出欣赏的目光,那么我想此时你的心情也会随着他人一起愉悦,那种成就感对于程序员来说,是一种说不上的幸福!话不多说,直接干货!

本文完全采用阿里巴巴的java开发规范

如果您习惯用IDEA进行代码开发,推荐一款实用的插件:Alibaba Java Coding Guidelines,可实时帮助我们检测代码规范!(本文重点在规范层面,具体用法且见下回分解)

头一回检测共发现 32+518+378=928处不规范的地方,甚是可怕!

1.避免用Apache Beanutils进行属性的copy。

说明

Apache BeanUtils性能较差,可以使用其他方案比如Spring BeanUtils, Cglib BeanCopier。    TestObject a = new TestObject();    TestObject b = new TestObject();    a.setX(b.getX());    a.setY(b.getY());复制代码

注意点

从Apache 的拷贝方案切换到Spring 的方案时,需要参数位置进行互换一下

Spring 的拷贝,需要保证拷贝与被拷贝的对象都拥有对应属性的 get 和 set 方法

拷贝的两个类必须拥有相同的成员变量

如果两个对象拥有2个属性完全一致但是类名不同的内部类,会被认为不是同一个类,不会执行拷贝

举例:

model类转entity类private String saveProjectMessage(ProjectModel projectModel) throws Exception{        ProjectEntity projectEntity = new ProjectEntity();        // org.apache.commons.beanutils.BeanUtils;        BeanUtils.copyProperties(projectEntity,projectModel); // 摒弃        org.springframework.beans.BeanUtils.copyProperties(projectModel,projectEntity); //推荐        return commonProjectBiz.saveProject(projectEntity);    }

2.所有的包装类对象之间值的比较,全部使用equals方法比较

对于Integer var=?在-128至127之间的赋值,Integer对象是在IntegerCache.cache产生,会复用已有对象,这个区间内的Integer值可以直接使用==进行判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个大坑,推荐使用equals方法进行判断。

Integer a = 235;Integer b = 235;if (a.equals(b)) {    // code}

3.Object的equals方法容易抛空指针异常,应使用常量或确定有值的对象来调用equals。

反例

public void f(String str){        if (str.equals("hi")) {            System.out.println("hello world");        }    }

public void f(String str){        String inner = "hi";        if (inner.equals(str)) {            System.out.println("hello world");        }    }

4.集合初始化时,指定集合初始值大小。

说明

HashMap使用如下构造方法进行初始化,如果暂时无法确定集合大小,那么指定默认值(16)即可。

反例:      Map<String, String> map = new HashMap<String, String>();正例:    Map<String, String> map = new HashMap<String, String>(16);

5.除常用方法(如getXxx/isXxx)等外,不要在条件判断中执行复杂的语句,将复杂逻辑判断的结果赋值给一个有意义的布尔变量,以提高可读性。

说明

很多if语句内的逻辑相当复杂,阅读者需要分析条件表达式的最终结果,才能明确什么样的条件执行什么样的语句,那么,如果阅读者分析逻辑表达式错误呢?

反例

if ((file.open(fileName, "w") != null) && (...) || (...)) {        // ...    }

正例

boolean existed = (file.open(fileName, "w") != null) && (...) || (...);    if (existed) {        //...    }

6.不允许任何魔法值(即未经定义的常量)直接出现在代码中

反例

if (key.equals("Id#taobao_1")) {            //...    }

正例

String KEY_PRE = "Id#taobao_1";    if (KEY_PRE.equals(key)) {            //...    }

7.Map/Set的key为自定义对象时,必须重写hashCode和equals

说明

关于hashCode和equals的处理,遵循如下规则:1.只要重写equals,就必须重写hashCode 2.因为Set存储的是不重复的对象,依据hashCode和equals进行判断,所以Set存储的对象必须重写这两个方法 3.如果自定义对象做为Map的键,那么必须重写hashCode和equals。 

举例

// 定义一个车牌类public class CarNumber {    private String cityCode; // 城市代号    private String number; // 车牌号    public String getCityCode() {        return cityCode;    }    public void setCityCode(String cityCode) {        this.cityCode = cityCode;    }    public String getNumber() {        return number;    }    public void setNumber(String number) {        this.number = number;    }

反例

public class Test {    public static void main(String [] args) {        //  key为自定义类        Map<CarNumber, String> map =new HashMap<>(16);        CarNumber car1 = new CarNumber();        car1.setCityCode("苏A");        car1.setNumber("11111");        CarNumber car2 = new CarNumber();        car2.setCityCode("苏A");        car2.setNumber("22222");        map.put(car1, "车牌号1");        map.put(car2, "车牌号2");        // 参数内容和car2对象一样        CarNumber car3 = new CarNumber();        car3.setCityCode("苏A");        car3.setNumber("22222");                //控制台输出        System.out.println(map.get(car1));        System.out.println(map.get(car2));        System.out.println(map.get(car3));    }}

输出结果为:

正常理解car2&car3对象从hashMap中取值应该是相同的,但如果不重写hashcode()方法,比较是其地址,car3和car2地址不同,所以不相等!

正例

public class CarNumber {    private String cityCode; // 城市代号    private String number; // 车牌号    //在CarNumber 类中重写equals()和hashCode()方法;    @Override    public boolean equals(Object o) {        if (this == o) return true;        if (o == null || getClass() != o.getClass()) return false;        CarNumber carNumber = (CarNumber) o;        return Objects.equals(cityCode, carNumber.cityCode) &&                Objects.equals(number, carNumber.number);    }        @Override    public int hashCode() {        return Objects.hash(cityCode, number);    }}

输出结果为

原理

HashMap中的比较key是这样的,先求出key的hashcode(),比较其值是否相等,若相等再比较equals(),若相等则认为他们是相等 的。若equals()不相等则认为他们不相等。

如果只重写hashcode()不重写equals()方法,当比较equals()时只是看他们是否为同一对象(即进行内存地址的比较),所以必定要两个方法一起重写。

HashMap用来判断key是否相等的方法,其实是调用了HashSet判断加入元素 是否相等。

8.对于Service和DAO类,基于SOA的理念,暴露出来的服务一定是接口,内部的实现类用Impl的后缀与接口区别

反例

public interface DemoService{        void f();    }

正例

public class DemoServiceImpl implements DemoService {    @Override    public void f(){        System.out.println("hello world");    }}

9.单个方法的总行数不超过80行

说明

除注释之外的方法签名、结束右大括号、方法内代码、空行、回车及任何不可见字符的总行数不超过80行。

10.方法内部单行注释,在被注释语句上方另起一行,使用//注释。方法内部多行注释使用/* */注释。注意与代码对齐。

public void method() {        // Put single line comment above code. (Note: align '//' comment with code)        int a = 3;            /**        * Some description about follow code. (Note: align '/**' comment with code)        */        int b = 4;    }

11.所有编程相关的命名均不能以下划线或美元符号开始

反例

private void $test(){    System.out.println("命名不能以美元符号开始")}private void _test(){    System.out.println("命名不能以下划线开始")}

12.所有的抽象方法(包括接口中的方法)必须要用javadoc注释、除了返回值、参数、异常说明外,还必须指出该方法做什么事情,实现什么功能。

说明:如有实现和调用注意事项,请一并说明。

正例

/*** fetch data by rule id* * @param ruleId 规则Id* @param page 页数* @param jsonContext json字符串* @return Result<XxxxDO> 出参*/Result<XxxxDO> fetchDataByRuleId(Long ruleId, Integer page, String jsonContext);

13.方法名、参数名、成员变量、局部变量都统一使用lowerCamelCase,必须遵从驼峰形式

反例

void selectTODOList(Map<String,Object> todoMap);

正例

void selectTodoList(Map<String,Object> todoMap);

14.包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。包名统一使用单数形式,但是类名如果有复数含义,类名可以使用复数形式

正例

com.alibaba.mpp.util / com.taobao.tddl.domain.dto

15.不能使用过时的类或方法

说明

java.net.URLDecoder 中的方法decode(String encodeStr)这个方法已经过时

应该使用双参数decode(String source, String encode)

接口提供方既然明确是过时接口,那么有义务同时提供新的接口;作为调用方来说,有义务去考证过时方法的新实现是什么。

16.常量命名应该全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长

17.所有的覆写方法,必须加@Override注解、

反例

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

18.在if/else/for/while/do语句中必须使用大括号,即使只有一行代码,避免使用下面的形式:

if (condition) statements;

反例

if(flag) System.out.println("hello world");

正例

if (flag) {  System.out.println("hello world");}

19.常量命名应该全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长

public class ConstantNameDemo {    /**    * max stock count    */    public static final Long MAX_STOCK_COUNT = 50000L;

20.所有的枚举类型字段必须要有注释,说明每个数据项的用途。

正例

public enum TestEnum {        /**        * agree        */        agree("agree"),        /**        * reject        */        reject("reject");                private String action;            TestEnum(String action) {            this.action = action;        }            public String getAction() {            return action;        }    }

21.所有的类都必须添加创建者信息。

说明

在设置模板时,注意IDEA的@author为${USER},而eclipse的@author为${user},大小写有区别,而日期的设置统一为yyyy/MM/dd的格式。

正例

/**    * Demo class    *      * @author java酱    * @date 2020/01/10    */    public class CodeNoteDemo {    }

有问题的可以加群私聊交流讨论哦985824512


作者:java酱

链接:https://juejin.im/post/5e184a755188254e35124c89

来源:掘金

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,125评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,293评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,054评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,077评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,096评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,062评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,988评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,817评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,266评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,486评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,646评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,375评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,974评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,621评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,642评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,538评论 2 352

推荐阅读更多精彩内容