本文是对阿里插件中规约的详细解释二,关于插件使用,请参考这里

  1. 及时清理不再使用的代码段或配置信息。 说明:对于垃圾代码或过时配置,坚决清理干净,避免程序过度臃肿,代码冗余

    Positive example: For codes which are temporarily removed and likely to be reused, use /// to add a reasonable note.
    public static void hello() {
    /// Business is stopped temporarily by the owner.
    // Business business = new Business();
    // business.active();
    System.out.println("it's finished");
    }
  2. 后台输送给页面的变量必须加感叹号,${var}——中间加感叹号!。 说明:如果var=null或者不存在,那么${var}会直接显示在页面上
    <input type="text" name="email" value="$!email"/>
    <input type="text" name="email" value="$!{email}"/>
  3. 在if/else/for/while/do语句中必须使用大括号,即使只有一行代码,避免使用下面的形式:if (condition) statements;
  4. 在subList场景中,高度注意对原列表的修改,会导致子列表的遍历、增加、删除均产生ConcurrentModificationException异常;
    注:原因从源码可以看出,当子list添加删除元素时,也会相应添加删除本list。但反之就会出现异常。至于Java为何要这样设计,不得而知。
    Negative example:
    List<String> originList = new ArrayList<String>();
    originList.add("22");
    List<String> subList = originList.subList(0, 1);
    //warn
    originList.add("22");
  5. 在一个switch块内,每个case要么通过break/return等来终止,要么注释说明程序将继续执行到哪一个case为止;在一个switch块内,都必须包含一个default语句并且放在最后,即使它什么代码也没有。

  6. 在使用正则表达式时,利用好其预编译功能,可以有效加快正则匹配速度。 说明:不要在方法体内定义:Pattern pattern = Pattern.compile(规则);
    注:为代码效率考虑
    public class XxxClass {
    // Use precompile
    private static Pattern NUMBER_PATTERN = Pattern.compile("[0-9]+");
    public Pattern getNumberPattern() {
    // Avoid use Pattern.compile in method body.
    Pattern localPattern = Pattern.compile("[0-9]+");
    return localPattern;
    }
    }
  7. 多线程并行处理定时任务时,Timer运行多个TimeTask时,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运行,使用ScheduledExecutorService则没有这个问题。
    注:当处理多个并行任务时,如果需要线程异常不互相影响,用ScheduledExecutorService代替Timer

    //org.apache.commons.lang3.concurrent.BasicThreadFactory
    ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1,
    new BasicThreadFactory.Builder().namingPattern("example-schedule-pool-%d").daemon(true).build());
    executorService.scheduleAtFixedRate(new Runnable() {
    @Override
    public void run() {
    //do something
    }
    },initialDelay,period, TimeUnit.HOURS);
  8. 定义DO/DTO/VO等POJO类时,不要加任何属性默认值。(注:跟前面的用包装类一脉相承)
  9. 对于Service和DAO类,基于SOA的理念,暴露出来的服务一定是接口,内部的实现类用Impl的后缀与接口区别
    注:SOA:面向服务架构(Service-Oriented Architecture)
  10. 常量命名应该全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长
    public class ConstantNameDemo {
    
    /**
    * max stock count
    */
    public static final Long MAX_STOCK_COUNT = 50000L;
  11. 异常类命名使用Exception结尾
  12. 循环体内,字符串的联接方式,使用StringBuilder的append方法进行扩展。
  13. 必须回收自定义的ThreadLocal变量,尤其在线程池场景下,线程经常会被复用,如果不清理自定义的 ThreadLocal变量,可能会影响后续业务逻辑和造成内存泄露等问题。尽量在代理中使用try-finally块进行回收。

  14. 所有的包装类对象之间值的比较,全部使用equals方法比较。
    说明:对于Integer var=?在-128至127之间的赋值,Integer对象是在IntegerCache.cache产生,会复用已有对象,这个区间内的Integer值可以直接使用==进行判断,
    但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个大坑,推荐使用equals方法进行判断。 Integer a = 235;
    Integer b = 235;
    if (a.equals(b)) {
    //相等
    }
  15. 所有的抽象方法(包括接口中的方法)必须要用javadoc注释、除了返回值、参数、异常说明外,还必须指出该方法做什么事情,实现什么功能。 说明:如有实现和调用注意事项,请一并说明。
    /**
    * fetch data by rule id
    *
    * @param ruleId rule id
    * @param page page number
    * @param jsonContext json format context
    * @return Result<XxxxDO>
    */
    Result<XxxxDO> fetchDataByRuleId(Long ruleId, Integer page, String jsonContext);
  16. 所有的枚举类型字段必须要有注释,说明每个数据项的用途。
  17. 所有的类都必须添加创建者信息。
  18. 所有的覆写方法,必须加@Override注解。(注:可以让编译器提前发现错误)
  19. 所有编程相关的命名均不能以下划线或美元符号开始
  20. 抽象类命名使用Abstract或Base开头
  21. 方法内部单行注释,在被注释语句上方另起一行,使用//注释。方法内部多行注释使用/* */注释。注意与代码对齐。
  22. 方法名、参数名、成员变量、局部变量都统一使用lowerCamelCase,必须遵从驼峰形式
  23. 注意 Math.random() 这个方法返回是double类型,注意取值的范围[0,1)(能够取到零值,注意除零异常),如果想获取整数类型的随机数,不要将x放大10的若干倍然后取整,直接使用Random对象的nextInt或者nextLong方法。 
    Negative example:
    Long randomLong =(long) (Math.random() * 10); Positive example:
    Long randomLong = new Random().nextLong();
  24. 测试类命名以它要测试的类的名称开始,以Test结尾
  25. 类、类属性、类方法的注释必须使用javadoc规范,使用/**内容*/格式,不得使用//xxx方式和/*xxx*/方式。
    说明:在IDE编辑窗口中,javadoc方式会提示相关注释,生成javadoc可以正确输出相应注释;在IDE中,工程调用方法时,不进入方法即可悬浮提示方法、参数、返回值的意义,提高阅读效率。
    /**
    *
    * XXX class function description.
    *
    */
    public class XxClass implements Serializable {
    private static final long serialVersionUID = 113323427779853001L;
    /**
    * id
    */
    private Long id;
    /**
    * title
    */
    private String title; /**
    * find by id
    *
    * @param ruleId rule id
    * @param page start from 1
    * @return Result<Xxxx>
    */
    public Result<Xxxx> funcA(Long ruleId, Integer page) {
    return null;
    }
    }
  26. 类名使用UpperCamelCase风格,必须遵从驼峰形式,但以下情形例外:(领域模型的相关命名)DO / BO / DTO / VO / DAO
  27. 线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。 
    说明:Executors各个方法的弊端:
    1)newFixedThreadPool和newSingleThreadExecutor:
      主要问题是堆积的请求处理队列可能会耗费非常大的内存,甚至OOM。
    2)newCachedThreadPool和newScheduledThreadPool:
      主要问题是线程数最大数是Integer.MAX_VALUE,可能会创建数量非常多的线程,甚至OOM。 Positive example 1:
    //org.apache.commons.lang3.concurrent.BasicThreadFactory
    ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1,
    new BasicThreadFactory.Builder().namingPattern("example-schedule-pool-%d").daemon(true).build()); Positive example 2:
    ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
    .setNameFormat("demo-pool-%d").build(); //Common Thread Pool
    ExecutorService pool = new ThreadPoolExecutor(5, 200,
    0L, TimeUnit.MILLISECONDS,
    new LinkedBlockingQueue<Runnable>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy()); pool.execute(()-> System.out.println(Thread.currentThread().getName()));
    pool.shutdown();//gracefully shutdown Positive example 3:
    <bean id="userThreadPool"
    class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
    <property name="corePoolSize" value="10" />
    <property name="maxPoolSize" value="100" />
    <property name="queueCapacity" value="2000" /> <property name="threadFactory" value= threadFactory />
    <property name="rejectedExecutionHandler">
    <ref local="rejectedExecutionHandler" />
    </property>
    </bean>
    //in code
    userThreadPool.execute(thread);
  28. 获取当前毫秒数:System.currentTimeMillis(); 而不是new Date().getTime();
    注:这是从效率考虑,不用生成冗余的DAT对象
  29. 说明:如果想获取更加精确的纳秒级时间值,用System.nanoTime。在JDK8中,针对统计时间等场景,推荐使用Instant类。
    public class TimeMillisDemo {
    public static void main(String args[]) {
    // Positive example:
    long a = System.currentTimeMillis();
    // Negative example:
    long b = new Date().getTime(); System.out.println(a);
    System.out.println(b);
    }
    }

    返回类型为基本数据类型,return包装数据类型的对象时,自动拆箱有可能产生NPE

    public int method() {
    Integer a = null;
    return a;
    }
  30. 避免Random实例被多线程使用,虽然共享该实例是线程安全的,但会因竞争同一seed 导致的性能下降。说明:Random实例包括java.util.Random 的实例或者 Math.random()的方式。
    说明:使用线程池的好处是减少在创建和销毁线程上所花的时间以及系统资源的开销,解决资源不足的问题。如果不使用线程池,有可能造成系统创建大量同类线程而导致消耗完内存或者“过度切换”的问题。
    
        ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
    .setNameFormat("demo-pool-%d").build();
    ExecutorService singleThreadPool = new ThreadPoolExecutor(1, 1,
    0L, TimeUnit.MILLISECONDS,
    new LinkedBlockingQueue<Runnable>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy()); singleThreadPool.execute(()-> System.out.println(Thread.currentThread().getName()));
    singleThreadPool.shutdown();
  31. 避免用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());
  32. 避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接用类名来访问即可。(注:需要了解JVM机制)
  33. 除常用方法(如getXxx/isXxx)等外,不要在条件判断中执行复杂的语句,将复杂逻辑判断的结果赋值给一个有意义的布尔变量,以提高可读性。
    说明:很多if语句内的逻辑相当复杂,阅读者需要分析条件表达式的最终结果,才能明确什么样的条件执行什么样的语句,那么,如果阅读者分析逻辑表达式错误呢?
    
    Negative example:
    if ((file.open(fileName, "w") != null) && (...) || (...)) {
    ...
    } Positive example:
    boolean existed = (file.open(fileName, "w") != null) && (...) || (...);
    if (existed) {
    ...
    }
  34. 集合初始化时,指定集合初始值大小。
    说明:HashMap使用如下构造方法进行初始化,如果暂时无法确定集合大小,那么指定默认值(16)即可。
    
     Negative example:
    Map<String, String> map = new HashMap<String, String>(); Positive example:
    Map<String, String> map = new HashMap<String, String>(16);

阿里Java开发规约(2)的更多相关文章

  1. 阿里Java开发规约插件使用

    刚刚的云栖大会上,阿里巴巴公布了这款酝酿已久的Java开发规约插件,对于国内开发者来说是一次轻松提高自己代码规范的机会. 安装方法 IDEA安装方法: settings >> plugin ...

  2. 阿里Java开发规约笔记

    借助阿里开发规约,回顾一下Java开发编码基础方面的知识,结合自己使用中遇到的问题,记录一下规约中以前翻过的错.有共鸣的问题. 1.覆写方法时要加上@Override注解.重写一个类型T的equals ...

  3. 阿里Java开发规约(1)

    本文是对阿里插件中规约的详细解释一,关于插件使用,请参考这里 1. ArrayList的subList结果不可强转成ArrayList,否则会抛出ClassCastException异常. 说明:禁止 ...

  4. 阿里Java开发规约【摘录】

    1.命名规约 [强制]类名使用UpperCamelCase风格,必须遵从驼峰形式,但以下情形例外:(领域模型的相关命名)DO / BO / DTO / VO等. 正例:MarcoPolo / User ...

  5. 阿里和Google的JAVA开发规约

    <阿里 JAVA开发规约> 阿里巴巴Java开发手册终极版v1.3.0.pdf 出处:github地址:https://github.com/alibaba/p3c <Google ...

  6. 为什么阿里Java规约要求谨慎使用SimpleDateFormat

    前言 在阿里Java开发规约中,有强制性的提到SimpleDateFormat 是线程不安全的类 ,在使用的时候应当注意线程安全问题,如下: 其实之前已经介绍过使用JDK1.8的DateTimeFor ...

  7. 阿里巴巴 Java 开发规约插件初体验

    阿里巴巴 Java 开发手册 又一次来谈<阿里巴巴 Java 开发手册>,经过这大半年的版本迭代,这本阿里工程师们总结出来避免写出那么多 Bug 的规范,对于 Java 开发者简直就是必备 ...

  8. 阿里巴巴Java开发规约及插件安装

    [上海尚学堂编辑整理]10.14日,阿里巴巴在杭州云栖大会上,正式发布了由阿里巴巴 P3C 项目组,经过 近一年的持续研发,正式发布众所期待的 <阿里巴巴 Java 开发规约>的扫描插件. ...

  9. 阿里java代码检测工具p3c

    阿里在杭州云栖大会上,正式发布众所期待的<阿里巴巴Java开发规约>扫描插件! 该插件由阿里巴巴P3C项目组研发.这个项目组是阿里巴巴开发爱好者自发组织形成的虚拟项目组,把<阿里巴巴 ...

随机推荐

  1. SQL基础E-R图基础

    ER图分为实体.属性.关系三个核心部分.实体是长方形体现,而属性则是椭圆形,关系为菱形. ER图的实体(entity)即数据模型中的数据对象,例如人.学生.音乐都可以作为一个数据对象,用长方体来表示, ...

  2. java字符编码转换研究(转)

    1. 概述 本文主要包括以下几个方面:编码基本知识,java,系统软件,url,工具软件等. 在下面的描述中,将以"中文"两个字为例,经查表可以知道其GB2312编码是" ...

  3. day35-hibernate映射 05-Hibernate的一级缓存:快照区

    SessionImpl里面有很多的Java集合,很多java集合才构成了一级缓存.一级缓存里面有一个非常特殊的区域叫做快照区.SessionImpl实现了Session接口,有很多Java集合(包括M ...

  4. css知多少(1)——我来问你来答(转)

    css知多少(1)——我来问你来答   1. 引言 各位前端或者伪前端(比如作者本人)的同志们,css对你们来说不是很陌生.比如我,在几年之前上大学的时候,给外面做网站就用css,而且必须用css.这 ...

  5. node Util 模块

    该util模块主要设计用于支持Node.js自己的内部API的需求.但是,许多实用程序对于应用程序和模块开发人员也很有用.它可以通过以下方式访问: const util = require('util ...

  6. hdu4283 You Are the One

    传送门 题目 The TV shows such as You Are the One has been very popular. In order to meet the need of boys ...

  7. HDU 5038 Grade (水题,坑题)

    题意:给 n 个数,输出众数,但是如果所有的频率都相同但数不同输出 Bad Mushroom. 析:直接记录个数直接暴力就,就是要注意只有一种频率的时候. 代码如下: #pragma comment( ...

  8. [译]Javascript中的递归函数

    本文翻译youtube上的up主kudvenkat的javascript tutorial播放单 源地址在此: https://www.youtube.com/watch?v=PMsVM7rjupU& ...

  9. 解决低版本Eclipse安装Findbugs插件无法显示问题

    问题描述 Eclipse安装Findbugs,显示安装成功,但是重启Eclipse在[Window]-[show view]-[other]中没有显示 原因 Eclipse版本太低,新版的Findbu ...

  10. C#使用Newtonsoft.Json操作json

    1.下载 Newtonsoft.Json 右键引用,选择 管理NuGet程序包,选择浏览,输入log4net,然后点击下载 2.json数据的组装与解析 public class Class { pu ...