java开发规范

一、命名风格

  1. 【强制】类名使用 UpperCamelCase 风格,必须遵从驼峰形式,但以下情形例外:DO / BO / DTO / VO / AO

  2. 【强制】方法名、参数名、成员变量、局部变量都统一使用 lowerCamelCase 风格,必须遵从 驼峰形式。

  3. 【强制】常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。

    正例:MAX_STOCK_COUNT 反例:MAX_COUNT

  4. 【强制】抽象类命名使用 Abstract 或 Base 开头;异常类命名使用 Exception 结尾;测试类命名以它要测试的类的名称开始,以 Test 结尾。

  5. 【强制】Model 类中布尔类型的变量,都不要加 is,否则部分框架解析会引起序列化错误。

    反例:定义为基本数据类型 Boolean isDeleted;的属性,它的方法也是 isDeleted(),RPC框架在反向解析的时候,“以为”对应的属性名称是 deleted,导致属性获取不到,进而抛出异常。

  6. 【参考】枚举类名建议带上 Enum 后缀,枚举成员名称需要全大写,单词间用下划线隔开。
    说明:枚举其实就是特殊的常量类,且构造方法被默认强制是私有。
    正例:枚举名字为 ProcessStatusEnum 的成员名称:SUCCESS / UNKOWN_REASON。

  7. 【参考】各层命名规约:
    A) Service/DAO 层方法命名规约
    1) 获取单个对象的方法用 get 做前缀。
    2) 获取多个对象的方法用 list 做前缀。
    3) 获取统计值的方法用 count 做前缀。
    4) 插入的方法用 save/insert 做前缀。
    5) 删除的方法用 remove/delete 做前缀。
    6) 修改的方法用 update 做前缀。

二、变量定义

  1. 【推荐】不要使用一个常量类维护所有常量,按常量功能进行归类,分开维护。 说明:大而全的常量类,非得使用查找功能才能定位到修改的常量,不利于理解和维护。

正例:缓存相关常量放在类 CacheConsts 下;系统配置相关常量放在类 ConfigConsts 下。

三、代码格式

  1. 【强制】大括号的使用约定。如果是大括号内为空,则简洁地写成{}即可,不需要换行;如果 是非空代码块则:
    1) 左大括号前不换行。
    2) 左大括号后换行。
    3) 右大括号前换行。
    4) 右大括号后还有 else 等代码则不换行 表示终止的右大括号后必须换行。

  2. 【强制】 左小括号和字符之间不出现空格;同样,右小括号和字符之间也不出现空格。
    反例:if (空格a == b空格)

  3. 【强制】if/for/while/switch/do 等保留字与括号之间都必须加空格。

  4. 【强制】任何二目、三目运算符的左右两边都需要加一个空格。
    说明:运算符包括赋值运算符=、逻辑运算符&&、加减乘除符号等。

  5. 【强制】采用 4 个空格缩进,禁止使用 tab 字符。

  6. 【强制】注释的双斜线与注释内容之间有且仅有一个空格。
    正例:// 注释内容,注意在//和注释内容之间有一个空格。

  7. 【强制】方法参数在定义和传入时,多个参数逗号后边必须加空格。
    正例:下例中实参的"a",后边必须要有一个空格。method("a", "b", "c");

  8. 【推荐】方法体内的执行语句组、变量的定义语句组、不同的业务逻辑之间或者不同的语义之间插入一个空行。相同业务逻辑和语义之间不需要插入空行。
    说明:没有必要插入多个空行进行隔开。

  9. 代码提交之前请格式化上传。idea有相应的对以上格式化的设置。快捷键window系统 Ctril+Alt+L,Mac:Command+Alt+L

 

四、异常处理

  1.  永远不要catch中吞掉异常,否则在系统发生错误时,你永远不知道到底发生了什
     
    
    catch (SomeException e) {
      return  null;
    }
    wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==
  2. 尽量使用特定的异常而不是一律使用Exception
    这样太泛泛的异常一味的使用Exception,这样就违背了可检查异常的设计初衷,
    因为调用都不知道Exception到底是什么,也不知道该如何处理。捕获异常时,
    也不要捕获范围太大,例如捕获Exception,相反,只捕获你能处理的异常,
    应该处理的异常。即然方法的声明者在方法上声明了不同类型的可检查异常,
    他是希望调用者区别对待不同异常的。

     

  3. Never catch Throwable class。
    永远不要捕获Throwable,因为Error也是继承自它,Error是Jvm都处理不了的错误,你能处理?
    所以基于有些Jvm在Error时就不会让你catch住。
  4. 正确的封装和传递异常。不要丢失异常栈,
    
    catch (SomeException e) {
    throw  new MyServiceException("Some information: " + e.getMessage());  //错误的做法
    }
    一定要保留原始的异常:
    
    catch (SomeException e) {
       throw new MyServiceException("Some information: " , e);  //正确的打开方式
    }

     

  5. 要打印异常,就不要抛出,不要两者都做
    
    catch (SomeException e) {
       LOGGER.error("Some information", e);
    throw e;
    }
    这样的log没有任何意义,只会打印出一连串的error log,对于定位问题无济于事。
  6. 不要在finally块中抛出异常
    如果在finally中抛出异常,将会覆盖原始的异常,如果finally中真的可能会发生异常,那一定要处理并记录它,不要向上抛。

     

  7. 不要使用printStackTrace
    要给异常添加上有用的上下文信息,单纯的异常栈,没有太大意义
  8. Throw early catch late
    异常界著名的原则,错误发生时及早抛出,然后在获得所以全部信息时再捕获处理.
    也可以理解为在低层次抛出的异常,在足够高的抽象层面才能更好的理解异常,然后捕获处理。
  9. 对于使用一些重量级资源的操作,发生异常时,一定记得清理
    如网络连接,数据库操作等,可以用try finally来做clean up的工作。
  10. 不要使用异常来控制程序逻辑流程
    我们总是不经意间这么做了,这样使得代码变更丑陋,使得正常业务逻辑和错误处理混淆不清;
    而且也可能会带来性能问题,因为异常是个比较重的操作
  11. 及早校验用户的输入
    在最边缘的入口校验用户的输入,这样使得我们不用再更底层逻辑中处处校验参数的合法性,
    能大大简化业务逻辑中不必要的异常处理逻辑;相反,在业务中不如果担心参数的合法性,
    则应该使用卫语句抛出运行时异常,一步步把对参数错误的处理推到系统的边缘,保持系统内部的清洁。
  12. 在打印错误的log中尽量在一行中包含尽可能多的上下文

五、集合使用

1.关于hsahCode和equals的处理,遵循如下规则:

只要重写 equals,就必须重写 hashCode。
因为 Set 存储的是不重复的对象,依据 hashCode 和 equals 进行判断,所以 Set 存储的对象必须重写这两个方法。
如果自定义对象作为 Map 的键,那么必须重写 hashCode 和 equals。
说明:String 重写了 hashCode 和 equals 方法,所以我们可以非常愉快地使用 String 对象作为 key 来使用。

2.ArrayList 的 subList 结果不可强转成 ArrayList,否则会抛出 ClassCastException 异常,即 java.util.RandomAccessSubList cannot be cast to java.util.ArrayList. 
说明:subList 返回的是 ArrayList 的内部类 SubList,并不是 ArrayList ,而是ArrayList 的一个视图,对于 SubList 子列表的所有操作最终会反映到原列表上。

3.在 subList 场景中,高度注意对原集合元素个数的修改,会导致子列表的遍历、增加、删除均会产生 ConcurrentModificationException 异常。

4.不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator方式,如果并发操作,需要对 Iterator 对象加锁。 
正例:

        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            String item = iterator.next();
            if (删除元素的条件) {
                iterator.remove();
            }
        }
反例:

        List<String> list = new ArrayList<String>();
        list.add("1");
        list.add("2");
        for (String item : list) {
            if ("1".equals(item)) {
                list.remove(item);
            }
        }
5.集合初始化时,指定集合初始值大小。 
说明:HashMap 使用 HashMap(int initialCapacity) 初始化,减少hashMap多次进行扩容机制。其他集合类同理。

正例:initialCapacity = (需要存储的元素个数 / 负载因子) + 1。注意负载因子(即 loader factor)默认为 0.75,如果暂时无法确定初始值大小,请设置为 16(即默认值)。

反例:HashMap 需要放置 1024 个元素,由于没有设置容量初始大小,随着元素不断增加,容量7 次被迫扩大,resize 需要重建 hash 表,严重影响性能。

6.使用 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 值组合集合。

7.对集合进行操作时,用java 8的特性Stream操作,这样对于编码来说效率增加。代码量减少

//使用Java8
List<RuleDTO> ruleDTOS = accountRules.stream().map(
                rule -> new RuleDTO(rule.getId(), rule.getRuleType(), rule.getRuleTitle(),
                    rule.getGmtCreate(), rule.getGmtModified(), rule.getIsDeleted(), rule.getStatus())).collect(
                Collectors.toCollection(() -> new ArrayList<>(accountRules.size())));

推荐使用Stream操作集合类

stream 相对于 Collection 的优点

  1. 无存储
  2. 惰性求值
  3. 无需上界
  4. 代码简练

 

ps:以上参考阿里Java开发规

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值