阿里巴巴Java代码规范

阿里巴巴Java代码规范

  • 1.及时清理不再使用的代码段或配置信息。
  • 2.不要在foreach循环里进行元素的remove/add操作,remove元素请使用Iterator方式。
  • 3. POJO类中的任何布尔类型的变量,都不要加is,否则部分框架解析会引起序列化错误
  • 4.在一个switch块内,每个case要么通过break/return等来终止,要么注释说明程序将继续执行到哪一个case为止;在一个switch块内,都必须包含一个default语句并且放在最后,即使它什么代码也没有。
  • 5.在if/else/for/while/do语句中必须使用大括号,即使只有一行代码,避免使用下面的形式:if (condition) statements;
  • 6.在subList场景中,高度注意对原列表的修改,会导致子列表的遍历、增加、删除均产生ConcurrentModificationException异常。
  • 7.POJO类必须写toString方法。使用工具类source> generate toString时,如果继承了另一个POJO类,注意在前面加一下super.toString。
  • 8.线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
  • 9.单个方法的总行数不超过80行。
  • 10.集合初始化时,指定集合初始值大小。
  • 11.测试类命名以它要测试的类的名称开始,以Test结尾
  • 12.不允许任何魔法值(即未经定义的常量)直接出现在代码中。
  • 13. 线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。
  • 14.后台输送给页面的变量必须加感叹号,${var}——中间加感叹号!。
  • 15. 创建线程或线程池时请指定有意义的线程名称,方便出错时回溯。创建线程池的时候请使用带ThreadFactory的构造函数,并且提供自定义ThreadFactory实现或者使用第三方实现。
  • 1.避免采用取反逻辑运算符。
  • 17.类、类属性、类方法的注释必须使用javadoc规范,使用/**内容*/格式,不得使用//xxx方式和/*xxx*/方式。
  • 18.循环体内,字符串的联接方式,使用StringBuilder的append方法进行扩展。
  • 19.关于基本数据类型与包装数据类型的使用标准
  • 20.iBATIS自带的queryForList(String statementName,int start,int size)不推荐使用
  • 21.常量命名应该全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长
  • 22.所有编程相关的命名均不能以下划线或美元符号开始
  • 23.包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。包名统一使用单数形式,但是类名如果有复数含义,类名可以使用复数形式
  • 24.ArrayList的subList结果不可强转成ArrayList,否则会抛出ClassCastException异常。
  • 25. 类名使用UpperCamelCase风格,必须遵从驼峰形式,但以下情形例外:(领域模型的相关命名)DO / BO / DTO / VO / DAO
  • 26.使用工具类Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方法,它的add/remove/clear方法会抛出UnsupportedOperationException异常。
  • 27.多线程并行处理定时任务时,Timer运行多个TimeTask时,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运行,使用ScheduledExecutorService则没有这个问题。
  • 28.避免用Apache Beanutils进行属性的copy。
  • 29.日期格式化字符串[%s]使用错误,应注意使用小写‘y’表示当天所在的年,大写‘Y’代表week in which year。
  • 30.返回类型为基本数据类型,return包装数据类型的对象时,自动拆箱有可能产生NPE
  • 31.Map/Set的key为自定义对象时,必须重写hashCode和equals。
  • 32.在使用正则表达式时,利用好其预编译功能,可以有效加快正则匹配速度。
  • 33.获取当前毫秒数:System.currentTimeMillis(); 而不是new Date().getTime();
  • 34.SimpleDateFormat 是线程不安全的类,一般不要定义为static变量,如果定义为static,必须加锁,或者使用DateUtils工具类。
  • 35.所有的抽象方法(包括接口中的方法)必须要用javadoc注释、除了返回值、参数、异常说明外,还必须指出该方法做什么事情,实现什么功能。
  • 36.方法内部单行注释,在被注释语句上方另起一行,使用//注释。方法内部多行注释使用/* */注释。注意与代码对齐。
  • 37.对于Service和DAO类,基于SOA的理念,暴露出来的服务一定是接口,内部的实现类用Impl的后缀与接口区别
  • 38.不能使用过时的类或方法。
  • 39.避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接用类名来访问即可。
  • 40.注意 Math.random() 这个方法返回是double类型,注意取值的范围[0,1)(能够取到零值,注意除零异常),如果想获取整数类型的随机数,不要将x放大10的若干倍然后取整,直接使用Random对象的nextInt或者nextLong方法。
  • 41.避免Random实例被多线程使用,虽然共享该实例是线程安全的,但会因竞争同一seed 导致的性能下降。说明:Random实例包括java.util.Random 的实例或者 Math.random()的方式。
  • 42. 必须回收自定义的ThreadLocal变量,尤其在线程池场景下,线程经常会被复用,如果不清理自定义的 ThreadLocal变量,可能会影响后续业务逻辑和造成内存泄露等问题。尽量在代理中使用try-finally块进行回收。
  • 43.所有的类都必须添加创建者信息。
  • 44.定义DO/DTO/VO等POJO类时,不要加任何属性默认值。
  • 45.long或者Long初始赋值时,必须使用大写的L,不能是小写的l,小写容易跟数字1混淆,造成误解。
  • 46.事务场景中,抛出异常被catch后,如果需要回滚,一定要手动回滚事务。
  • 47.异常类命名使用Exception结尾
  • 48.使用集合转数组的方法,必须使用集合的toArray(T[] array),传入的是类型完全一样的数组,大小就是list.size()
  • 49.除常用方法(如getXxx/isXxx)等外,不要在条件判断中执行复杂的语句,将复杂逻辑判断的结果赋值给一个有意义的布尔变量,以提高可读性。
  • 50.Object的equals方法容易抛空指针异常,应使用常量或确定有值的对象来调用equals。
  • 51.所有的覆写方法,必须加@Override注解。
  • 52.抽象类命名使用Abstract或Base开头
  • 53.中括号是数组类型的一部分,数组定义如下:String[] args
  • 54.使用CountDownLatch进行异步转同步操作,每个线程退出前必须调用countDown方法,线程执行代码注意catch异常,确保countDown方法可以执行,避免主线程无法执行至await方法,直到超时才返回结果。
  • 55. 方法名、参数名、成员变量、局部变量都统一使用lowerCamelCase,必须遵从驼峰形式
  • 56. 不能在finally块中使用return,finally块中的return返回后方法结束执行,不会再执行try块中的return语句。
  • 57.所有的包装类对象之间值的比较,全部使用equals方法比较。
  • 58. 所有的枚举类型字段必须要有注释,说明每个数据项的用途。

阿里巴巴Java开发手册(华山版):https://github.com/JackWei1996/p3c/blob/master/%E9%98%BF%E9%87%8C%E5%B7%B4%E5%B7%B4Java%E5%BC%80%E5%8F%91%E6%89%8B%E5%86%8C%EF%BC%88%E5%8D%8E%E5%B1%B1%E7%89%88%EF%BC%89.pdf

1.及时清理不再使用的代码段或配置信息。

Name
   RemoveCommentedCodeRule

Severity
   Major

Message
   及时清理不再使用的代码段或配置信息。

Description
   说明:对于垃圾代码或过时配置,坚决清理干净,避免程序过度臃肿,代码冗余。

Examples
   
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.不要在foreach循环里进行元素的remove/add操作,remove元素请使用Iterator方式。

Name
   DontModifyInForeachCircleRule

Severity
   Blocker

Message
   不要在foreach循环里进行元素的remove/add操作,remove元素请使用Iterator方式。

Examples
   
Negative example:   
   List<String> originList = new ArrayList<String>();
   originList.add("22");
   for (String item : originList) { 
      //warn
      list.add("bb");
   }   
Positive example: 
   Iterator<Integer> it=b.iterator();		 
   while(it.hasNext()){                      
      Integer temp =  it.next();             
      if (delCondition) {
          it.remove();
      }
   }   

3. POJO类中的任何布尔类型的变量,都不要加is,否则部分框架解析会引起序列化错误

Name
   BooleanPropertyShouldNotStartWithIsRule

Severity
   Critical

Message
   POJO类中的任何布尔类型的变量,都不要加is,否则部分框架解析会引起序列化错误

Examples
   
public class DemoDO{
        Boolean success;
        Boolean delete;
}   

4.在一个switch块内,每个case要么通过break/return等来终止,要么注释说明程序将继续执行到哪一个case为止;在一个switch块内,都必须包含一个default语句并且放在最后,即使它什么代码也没有。

Name
   SwitchStatementRule

Severity
   Critical

Message
   在一个switch块内,每个case要么通过break/return等来终止,
   要么注释说明程序将继续执行到哪一个case为止;在一个switch块内,
   都必须包含一个default语句并且放在最后,即使它什么代码也没有。

Examples
   
switch (x) {
        case 1:
            break;
        case 2:
            break;
        default:
}   

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

Name
   NeedBraceRule

Severity
   Blocker

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

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

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

Name
   ConcurrentExceptionWithModifyOriginSubListRule

Severity
   Critical

Message
   在subList场景中,高度注意对原列表的修改,
   会导致子列表的遍历、增加、删除均产生ConcurrentModificationException异常。

Examples
   
Negative example:                
   List<String> originList = new ArrayList<String>();
   originList.add("22");
   List<String> subList = originList.subList(0, 1);
   //warn
   originList.add("22");   

7.POJO类必须写toString方法。使用工具类source> generate toString时,如果继承了另一个POJO类,注意在前面加一下super.toString。

Name
   PojoMustOverrideToStringRule

Severity
   Major

Message
   POJO类必须写toString方法。使用工具类source> generate toString时,如果继承了另一个POJO类,注意在前面加一下super.toString。

Description
   说明:在方法执行抛出异常时,可以直接调用POJO的toString()方法打印其属性值,便于排查问题。

Examples
   
public class ToStringDemo extends Super{
        private String secondName;

        @Override
        public String toString() {
            return super.toString() + "ToStringDemo{" + "secondName='" + secondName + '\'' + '}';
        }
    }

    class Super {
        private String firstName;

        @Override
        public String toString() {
            return "Super{" + "firstName=" + firstName + '\'' + '}';
        }
    }   

8.线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。

Name
   ThreadPoolCreationRule

Severity
   Blocker

Message
   线程池不允许使用Executors去创建,
   而是通过ThreadPoolExecutor的方式,
   这样的处理方式让写的同学更加明确线程池的运行规则,
   规避资源耗尽的风险。

Description
   说明:Executors各个方法的弊端:
   1)newFixedThreadPool和newSingleThreadExecutor:
     主要问题是堆积的请求处理队列可能会耗费非常大的内存,甚至OOM。
   2)newCachedThreadPool和newScheduledThreadPool:
     主要问题是线程数最大数是Integer.MAX_VALUE,可能会创建数量非常多的线程,甚至OOM。

Examples
   
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);   

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

Name
   MethodTooLongRule

Severity
   Major

Message
   单个方法的总行数不超过80行。

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

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

Name
   CollectionInitShouldAssignCapacityRule

Severity
   Major

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

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

Examples
   
Negative example:   
   Map<String, String> map = new HashMap<String, String>();   
Positive example: 
   Map<String, String> map = new HashMap<String, String>(16);   

11.测试类命名以它要测试的类的名称开始,以Test结尾

Name
   TestClassShouldEndWithTestNamingRule

Severity
   Major

Message
   测试类命名以它要测试的类的名称开始,以Test结尾

Examples
   
public class DemoTest {
}   

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

Name
   UndefineMagicConstantRule

Severity
   Major

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

Examples
   
Negative example:
    //Magic values, except for predefined, are forbidden in coding.
    if (key.equals("Id#taobao_1")) {
            //...
    }   
Positive example:
    String KEY_PRE = "Id#taobao_1";  
    if (KEY_PRE.equals(key)) {
            //...
	}   

13. 线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。

Name
   AvoidManuallyCreateThreadRule

Severity
   Critical

Message
   线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。

Description
   说明:使用线程池的好处是减少在创建和销毁线程上所花的时间以及系统资源的开销,解决资源不足的问题。如果不使用线程池,有可能造成系统创建大量同类线程而导致消耗完内存或者“过度切换”的问题。

Examples
   
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();   

14.后台输送给页面的变量必须加感叹号,${var}——中间加感叹号!。

Name
   UseQuietReferenceNotationRule

Severity
   Major

Message
   后台输送给页面的变量必须加感叹号,${var}——中间加感叹号!。

Description
   说明:如果var=null或者不存在,那么${var}会直接显示在页面上。

Examples
   
<input type="text" name="email" value="$!email"/>
    <input type="text" name="email" value="$!{email}"/>   

15. 创建线程或线程池时请指定有意义的线程名称,方便出错时回溯。创建线程池的时候请使用带ThreadFactory的构造函数,并且提供自定义ThreadFactory实现或者使用第三方实现。

Name
   ThreadShouldSetNameRule

Severity
   Critical

Message
   创建线程或线程池时请指定有意义的线程名称,
   方便出错时回溯。
   创建线程池的时候请使用带ThreadFactory的构造函数,
   并且提供自定义ThreadFactory实现或者使用第三方实现。

Examples
   
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();   
public class TimerTaskThread extends Thread {
        public TimerTaskThread(){
        super.setName("TimerTaskThread");}   

1.避免采用取反逻辑运算符。

Name
   AvoidNegationOperatorRule

Severity
   Major

Message
   避免采用取反逻辑运算符。

Description
   说明: 取反逻辑不利于快速理解,并且取反逻辑写法必然存在对应的正向逻辑写法。

Examples
   
Negative example:
    // Use `if (!(x >= 628))` to represent that x is less than 628.
    if (!(x >= 628)) {
        // ...
    }   
Positive example:
    // Use `if (x < 628)` to represent that x is less than 628.
    if (x < 628)) {
        // ...
    }   

17.类、类属性、类方法的注释必须使用javadoc规范,使用/*内容/格式,不得使用//xxx方式和/xxx/方式。

Name
   CommentsMustBeJavadocFormatRule

Severity
   Major

Message
   类、类属性、类方法的注释必须使用javadoc规范,使用/**内容*/格式,不得使用//xxx方式和/*xxx*/方式。

Description
   说明:在IDE编辑窗口中,javadoc方式会提示相关注释,生成javadoc可以正确输出相应注释;在IDE中,工程调用方法时,不进入方法即可悬浮提示方法、参数、返回值的意义,提高阅读效率。

Examples
   
/**
     * 
     * 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
         */
        public Result<Xxxx> funcA(Long ruleId, Integer page) {
            return null;
        }
    }   

18.循环体内,字符串的联接方式,使用StringBuilder的append方法进行扩展。

Name
   StringConcatRule

Severity
   Major

Message
   循环体内,字符串的联接方式,使用StringBuilder的append方法进行扩展。

Description
   说明:反编译出的字节码文件显示每次循环都会new出一个StringBuilder对象,然后进行append操作,最后通过toString方法返回String对象,造成内存资源浪费。

Examples
   
Negative example:
    String result;
    for (String string : tagNameList) {
        result = result + string;
    }   
Positive example:
    StringBuilder stringBuilder = new StringBuilder();
    for (String string : tagNameList) {
        stringBuilder.append(string);
    }
    String result = stringBuilder.toString();   

19.关于基本数据类型与包装数据类型的使用标准

Name
   PojoMustUsePrimitiveFieldRule

Severity
   Major

Message
   关于基本数据类型与包装数据类型的使用标准如下:
 1) 所有的POJO类属性必须使用包装数据类型。
 2) RPC方法的返回值和参数必须使用包装数据类型。
 3) 所有的局部变量推荐使用基本数据类型。

Description
   说明:POJO类属性没有初值是提醒使用者在需要使用时,必须自己显式地进行赋值,任何NPE问题,或者入库检查,都由使用者来保证。

Examples
   
public class DemoDO {
        String str;
        Integer a;
}   

20.iBATIS自带的queryForList(String statementName,int start,int size)不推荐使用

Name
   IbatisMethodQueryForListRule

Severity
   Major

Message
   iBATIS自带的queryForList(String statementName,int start,int size)不推荐使用

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

Name
   ConstantFieldShouldBeUpperCaseRule

Severity
   Critical

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

Examples
   
public class ConstantNameDemo {

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

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

Name
   AvoidStartWithDollarAndUnderLineNamingRule

Severity
   Critical

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

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

Name
   PackageNamingRule

Severity
   Major

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

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

24.ArrayList的subList结果不可强转成ArrayList,否则会抛出ClassCastException异常。

Name
   ClassCastExceptionWithSubListToArrayListRule

Severity
   Critical

Message
   ArrayList的subList结果不可强转成ArrayList,否则会抛出ClassCastException异常。

Description
   说明:禁止强转,如果需要用到集合特性方法,请新建一个集合,然后置入sublist,new 集合(sublist结果)。

Examples
   
Negative example:
   List<String> list = new ArrayList<String>();
   list.add("22");
   //warn
   List<String> test = (ArrayList<String>) list.subList(0, 1);   
Positive example:
   List<String> list2 = new ArrayList<String>(list.subList(0, 1));   

25. 类名使用UpperCamelCase风格,必须遵从驼峰形式,但以下情形例外:(领域模型的相关命名)DO / BO / DTO / VO / DAO

Name
   ClassNamingShouldBeCamelRule

Severity
   Major

Message
   类名使用UpperCamelCase风格,必须遵从驼峰形式,但以下情形例外:(领域模型的相关命名)DO / BO / DTO / VO / DAO

26.使用工具类Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方法,它的add/remove/clear方法会抛出UnsupportedOperationException异常。

Name
   UnsupportedExceptionWithModifyAsListRule

Severity
   Critical

Message
   使用工具类Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方法,它的add/remove/clear方法会抛出UnsupportedOperationException异常。

Examples
   
Positive example:
   List<String> t   = Arrays.asList("a","b","c"); 
   //warn
   t.add("22");
   //warn
   t.remove("22");
   //warn
   t.clear();   

27.多线程并行处理定时任务时,Timer运行多个TimeTask时,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运行,使用ScheduledExecutorService则没有这个问题。

Name
   AvoidUseTimerRule

Severity
   Blocker

Message
   多线程并行处理定时任务时,Timer运行多个TimeTask时,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运行,使用ScheduledExecutorService则没有这个问题。

Examples
   
//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);   

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

Name
   AvoidApacheBeanUtilsCopyRule

Severity
   Blocker

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

Description
   说明:Apache BeanUtils性能较差,可以使用其他方案比如Spring BeanUtils, Cglib BeanCopier。

Examples
   
TestObject a = new TestObject();
    TestObject b = new TestObject();
    a.setX(b.getX());
    a.setY(b.getY());   

29.日期格式化字符串[%s]使用错误,应注意使用小写‘y’表示当天所在的年,大写‘Y’代表week in which year。

Name
   UseRightCaseForDateFormatRule

Severity
   Critical

Message
   日期格式化字符串[%s]使用错误,应注意使用小写‘y’表示当天所在的年,大写‘Y’代表week in which year。

Description
   日期格式化时,yyyy表示当天所在的年,而大写的YYYY代表是week in which year(JDK7之后引入的概念),意思是当天所在的周属于的年份,一周从周日开始,周六结束,只要本周跨年,返回的YYYY就是下一年。

Examples
   
Negative example:
    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");   
Positive example:
        SimpleDateFormat format = new SimpleDateFormat("YYYY-mm-dd HH:mm:ss");   

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

Name
   MethodReturnWrapperTypeRule

Severity
   Major

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

Examples
   
public int method() {
        Integer a = null;
        return a;
    }   

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

Name
   MapOrSetKeyShouldOverrideHashCodeEqualsRule

Severity
   Critical

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

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

32.在使用正则表达式时,利用好其预编译功能,可以有效加快正则匹配速度。

Name
   AvoidPatternCompileInMethodRule

Severity
   Blocker

Message
   在使用正则表达式时,利用好其预编译功能,可以有效加快正则匹配速度。

Description
   说明:不要在方法体内定义:Pattern pattern = Pattern.compile(规则);

Examples
   
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;
        }
    }   

33.获取当前毫秒数:System.currentTimeMillis(); 而不是new Date().getTime();

Name
   AvoidNewDateGetTimeRule

Severity
   Blocker

Message
   获取当前毫秒数:System.currentTimeMillis(); 而不是new Date().getTime();

Description
   说明:如果想获取更加精确的纳秒级时间值,用System.nanoTime。在JDK8中,针对统计时间等场景,推荐使用Instant类。

Examples
   
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);
        }
    }   

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

Name
   AvoidCallStaticSimpleDateFormatRule

Severity
   Critical

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

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

Examples
   
Positive example 1private static final String FORMAT = "yyyy-MM-dd HH:mm:ss";
    public String getFormat(Date date){
        SimpleDateFormat dateFormat = new SimpleDateFormat(FORMAT);
        return sdf.format(date);
    }   
Positive example 2private static final SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    public void getFormat(){
        synchronized (sdf){
        sdf.format(new Date());.;
    }   
Positive example 3private static final ThreadLocal<DateFormat> DATE_FORMATTER = new ThreadLocal<DateFormat>() {
        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd");
        }
    };   

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

Name
   AbstractMethodOrInterfaceMethodMustUseJavadocRule

Severity
   Major

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

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

Examples
   
/**
     * fetch data by rule id
     * 
     * @param ruleId rule id
     * @param page page number
     * @param jsonContext json format context
     * @return Result
     */
    Result<XxxxDO> fetchDataByRuleId(Long ruleId, Integer page, String jsonContext);   

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

Name
   AvoidCommentBehindStatementRule

Severity
   Major

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

Examples
   
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;
    }   

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

Name
   ServiceOrDaoClassShouldEndWithImplRule

Severity
   Critical

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

Examples
   
public interface DemoService{
        void f();
    }

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

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

Name
   AvoidUseDeprecationRule

Severity
   Critical

Message
   不能使用过时的类或方法。

Description
   说明:java.net.URLDecoder 中的方法decode(String encodeStr) 这个方法已经过时,应该使用双参数decode(String source, String encode)。接口提供方既然明确是过时接口,那么有义务同时提供新的接口;作为调用方来说,有义务去考证过时方法的新实现是什么。

39.避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接用类名来访问即可。

Name
   AvoidAccessStaticViaInstanceRule

Severity
   Blocker

Message
   避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接用类名来访问即可。

40.注意 Math.random() 这个方法返回是double类型,注意取值的范围[0,1)(能够取到零值,注意除零异常),如果想获取整数类型的随机数,不要将x放大10的若干倍然后取整,直接使用Random对象的nextInt或者nextLong方法。

Name
   AvoidMissUseOfMathRandomRule

Severity
   Major

Message
   注意 Math.random() 这个方法返回是double类型,注意取值的范围[0,1)(能够取到零值,注意除零异常),如果想获取整数类型的随机数,不要将x放大10的若干倍然后取整,直接使用Random对象的nextInt或者nextLong方法。

Examples
   
Negative example:
    Long randomLong =(long) (Math.random() * 10);   
Positive example:
    Long randomLong = new Random().nextLong();   

41.避免Random实例被多线程使用,虽然共享该实例是线程安全的,但会因竞争同一seed 导致的性能下降。说明:Random实例包括java.util.Random 的实例或者 Math.random()的方式。

Name
   AvoidConcurrentCompetitionRandomRule

Severity
   Major

Message
   避免Random实例被多线程使用,虽然共享该实例是线程安全的,但会因竞争同一seed 导致的性能下降。说明:Random实例包括java.util.Random 的实例或者 Math.random()的方式。

Examples
   
Positive example 1/**
     * @author caikang
     * @date 2017/04/07
     */
    public class RandomInThread extends Thread {
        private Random random = new Random();

        @Override
        public void run() {
            long t = random.nextLong();
        }
    }   
Positive example 2/**
     * @author caikang
     * @date 2017/04/07
     */
    public class RandomInThread extends Thread {
        private Random random = ThreadLocalRandom.current();

        @Override
        public void run() {
            long t = random.nextLong();
        }
    }   

42. 必须回收自定义的ThreadLocal变量,尤其在线程池场景下,线程经常会被复用,如果不清理自定义的 ThreadLocal变量,可能会影响后续业务逻辑和造成内存泄露等问题。尽量在代理中使用try-finally块进行回收。

Name
   ThreadLocalShouldRemoveRule

Severity
   Critical

Message
   必须回收自定义的ThreadLocal变量,尤其在线程池场景下,线程经常会被复用,如果不清理自定义的 ThreadLocal变量,可能会影响后续业务逻辑和造成内存泄露等问题。尽量在代理中使用try-finally块进行回收。

Examples
   
/**
     * @author caikang
     * @date 2017/04/07
     */
    public class UserHolder {
        private static final ThreadLocal<User> userThreadLocal = new ThreadLocal<User>();

        public static void set(User user){
            userThreadLocal.set(user);
        }

        public static User get(){
            return userThreadLocal.get();
        }

        public static void remove(){
            userThreadLocal.remove();
        }
    }

    /**
     * @author caikang
     * @date 2017/04/07
     */
    public class UserInterceptor extends HandlerInterceptorAdapter {
        @Override
        public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception {
            UserHolder.set(new User());
            return true;
        }

        @Override
        public void afterCompletion(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception ex) throws Exception {
            UserHolder.remove();
        }
    }   

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

Name
   ClassMustHaveAuthorRule

Severity
   Major

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

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

Examples
   
/**
     * Demo class
     * 
     * @author keriezhang
     * @date 2016/10/31
     */
    public class CodeNoteDemo {
    }   

44.定义DO/DTO/VO等POJO类时,不要加任何属性默认值。

Name
   PojoNoDefaultValueRule

Severity
   Major

Message
   定义DO/DTO/VO等POJO类时,不要加任何属性默认值。

Examples
   
public class DemoDO {
        String str;
        Integer a;
    }   

45.long或者Long初始赋值时,必须使用大写的L,不能是小写的l,小写容易跟数字1混淆,造成误解。

Name
   UpperEllRule

Severity
   Blocker

Message
   long或者Long初始赋值时,必须使用大写的L,不能是小写的l,小写容易跟数字1混淆,造成误解。

Examples
   
Negative example:
    //It is hard to tell whether it is number 11 or Long 1.
    Long warn = 1l;   
Positive example:
    Long notwarn = 1L;   

46.事务场景中,抛出异常被catch后,如果需要回滚,一定要手动回滚事务。

Name
   TransactionMustHaveRollbackRule

Severity
   Major

Message
   事务场景中,抛出异常被catch后,如果需要回滚,一定要手动回滚事务。

Examples
   
Positive example 1/**
     * @author caikang
     * @date 2017/04/07
     */
    @Service
    @Transactional(rollbackFor = Exception.class)
    public class UserServiceImpl implements UserService {
        @Override
        public void save(User user) {
            //some code
            //db operation
        }
    }   
Positive example 2/**
     * @author caikang
     * @date 2017/04/07
     */
    @Service
    public class UserServiceImpl implements UserService {
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void save(User user) {
            //some code
            //db operation
        }
    }   
Positive example 3/**
     * @author caikang
     * @date 2017/04/07
     */
    @Service
    public class UserServiceImpl implements UserService {
        @Autowired
        private DataSourceTransactionManager transactionManager;

        @Override
        @Transactional
        public void save(User user) {
            DefaultTransactionDefinition def = new DefaultTransactionDefinition();
            // explicitly setting the transaction name is something that can only be done programmatically
            def.setName("SomeTxName");
            def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

            TransactionStatus status = transactionManager.getTransaction(def);
            try {
                // execute your business logic here
                //db operation
            } catch (Exception ex) {
                transactionManager.rollback(status);
                throw ex;
            }
        }
    }   

47.异常类命名使用Exception结尾

Name
   ExceptionClassShouldEndWithExceptionRule

Severity
   Critical

Message
   异常类命名使用Exception结尾

Examples
   
public class CacheDemoException extends Exception{
    }   

48.使用集合转数组的方法,必须使用集合的toArray(T[] array),传入的是类型完全一样的数组,大小就是list.size()

Name
   ClassCastExceptionWithToArrayRule

Severity
   Critical

Message
   使用集合转数组的方法,必须使用集合的toArray(T[] array),传入的是类型完全一样的数组,大小就是list.size()

Examples
   
Negative example:  
   Integer[] a = (Integer [])c.toArray();   
Positive example: 
   Integer[] b = (Integer [])c.toArray(new Integer[c.size()]);   

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

Name
   AvoidComplexConditionRule

Severity
   Major

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

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

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

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

Name
   EqualsAvoidNullRule

Severity
   Critical

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

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

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

Name
   MissingOverrideAnnotationRule

Severity
   Blocker

Message
   所有的覆写方法,必须加@Override注解。

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

Examples
   
/**
     * @author caikang
     * @date 2016/12/24
     */
    public class MissingOverrideAnnotationRule extends AbstractEclipseRule {
        @Override
        public Object visit(ASTCompilationUnit node, Object data) {
            return super.visit(node, data);
        }
    }   

52.抽象类命名使用Abstract或Base开头

Name
   AbstractClassShouldStartWithAbstractNamingRule

Severity
   Critical

Message
   抽象类命名使用Abstract或Base开头

Examples
   
abstract class BaseControllerDemo{
    }

    abstract class AbstractActionDemo{
    }   

53.中括号是数组类型的一部分,数组定义如下:String[] args

Name
   ArrayNamingShouldHaveBracketRule

Severity
   Major

Message
   中括号是数组类型的一部分,数组定义如下:String[] args

Examples
   
String[] a = new String[3];   

54.使用CountDownLatch进行异步转同步操作,每个线程退出前必须调用countDown方法,线程执行代码注意catch异常,确保countDown方法可以执行,避免主线程无法执行至await方法,直到超时才返回结果。

Name
   CountDownShouldInFinallyRule

Severity
   Major

Message
   使用CountDownLatch进行异步转同步操作,每个线程退出前必须调用countDown方法,线程执行代码注意catch异常,确保countDown方法可以执行,避免主线程无法执行至await方法,直到超时才返回结果。

Description
   说明:注意,子线程抛出异常堆栈,不能在主线程try-catch到。

Examples
   
/**
     * @author caikang
     * @date 2017/04/07
     */
    public class CountDownExample {
        public void operate(CountDownLatch countDownLatch){
            try{
                System.out.println("business logic");
            }catch (RuntimeException e){
                // do something
            }finally {
                countDownLatch.countDown();
            }
        }
    }   

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

Name
   LowerCamelCaseVariableNamingRule

Severity
   Critical

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

56. 不能在finally块中使用return,finally块中的return返回后方法结束执行,不会再执行try块中的return语句。

Name
   AvoidReturnInFinallyRule

Severity
   Critical

Message
   不能在finally块中使用returnfinally块中的return返回后方法结束执行,不会再执行try块中的return语句。

Examples
   
Negative example:
    public static Long readFileLength(String fileName) {
        try {
            File file = new File(fileName);
            RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r");
            return randomAccessFile.length();
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            countDownLatch.countDown();
            return 0L;
        }
    }   

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

Name
   WrapperTypeEqualityRule

Severity
   Blocker

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

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

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

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

Name
   EnumConstantsMustHaveCommentRule

Severity
   Critical

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

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

你可能感兴趣的:(浩哥的JAVA之路)