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

  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. C++知识点总结(6)

    1.double和float的存储方式 float遵从的是IEEE R32.24 ,而double 遵从的是R64.53.无论是单精度还是双精度在存储中都分为三个部分: 符号位(Sign) : 0代表 ...

  2. C#正则表达式匹配双引号

    html: <img class="bubble large" src="/images/hero-logos/cog.svg" width=" ...

  3. Comparatable接口和Comparator接口的使用与区别

    这篇博文可以为你解决的问题如下: 什么是自然排序 Collections.sort()与Arrays.sort()的异同点 Comparatable接口和Comparator接口各自的排序依据(理论讲 ...

  4. [patl1-046]整除光棍

    解题关键:模拟除法 #include<cstdio> #include<cstring> #include<algorithm> #include<cstdl ...

  5. win10 更换秘钥报错:拒绝访问:所请求的操作需要提升特权

    直接打开cmd执行换秘钥的命令: slmgr /ipk VK7JG-NPHTM-C97JM-9MPGT-3V66T slmgr /skms kms.xspace.in slmgr /ato 报错如图: ...

  6. 树莓派研究笔记(9)-- 树莓派SPI连接TFT屏幕

    HDMI连接和树莓派专用连接的接口的屏幕都太贵了,为了节约成本,现在国内大多数还是TFT屏幕. 树莓派可以激活SPI接口,通过代码驱动TFT屏幕的显示.这样利用树莓派zero 打造小型的游戏平台可以大 ...

  7. 带有通配符的字符串匹配算法-C/C++

    日前某君给我出了这样一道题目:两个字符串,一个是普通字符串,另一个含有*和?通配符,*代表零个到多个任意字符,?代表一个任意字符,通配符可能多次出现.写一个算法,比较两个字符串是否相等. 我花了四个小 ...

  8. 免费证书申请——Let's Encrypt的申请与应用(IIS,Tomcat)

    环境 Windows Server 2008 R2 Tomcat 8.5.31 JDK8 利用IIS+letsencrypt-win-simple.V1.9.1申请免费SSL证书 新建一个IIS空网站 ...

  9. .Net Core异步async/await探索

    走进.NetCore的异步编程 - 探索 async/await 前言: 这段时间开始用.netcore做公司项目,发现前辈搭的框架通篇运用了异步编程方式,也就是async/await方式,作为一个刚 ...

  10. UWP&WP8.1图片照片添加水印

    水印可以自己自己制作,也可以用代码写. 我这里主要写如何添加到照片上面. UWP和WP8.1添加的方法一样.代码是通用的. UWP和WP8.1没有像WPF和WINFROM中darw这样简便的API可以 ...