zoukankan      html  css  js  c++  java
  • JAVA开发规范

     

     

    1  方法行数不能超过50行,特殊情况除外;说明:如果行数过长不利于整个方法的阅读理解。如果是笔记本建议控制在40以内。

    2  方法参数不能多于7个,特殊情况除外;说明:参数过多不利于整个方法的阅读理解。

    3  变量名称需有意义且符合驼峰式写法,严禁出现a,b,c 等字符作为变量名称。

    4  严禁出现魔鬼数字(在代码中没有具体含义的数字、字符串)。

    5  新建类名,方法名意义尽量切近当前功能模块的功能,且符合驼峰式写法。

    6  If语句后必须写花括号,严禁出现 if(true)后面直接写代码,需带花括号{}。

    7  条件判断中必须有空格 如 if (1  ==  2)。 等号两边需加空格。

    8  严禁使用==判断字符串值,需使用equals方法判断。

    9  与null对象进行判断, 需写成(null  ==  xxx) 形式,null写在前;说明:有时候如果将变量写在前,恰好将==疏忽写成= 就会造成 xxx = null,等于是给变量赋值为null。

    10 对当前对象进行null判断,并且进行调用对象方法判断时,形如if(null !=  xxx  && xxx.size()  >  0)需将null !=  xxx判断写在前,这样如果为null,可以直接短路,防止空指针异常产生。

    11 静态常量名称应大写,多个单词可用下划线拼接,如 SELECT_NUMBER = 1。

    12 方法注释,若当前方法功能较为复杂,需以javadoc方式注释进行说明,注释需写成形如

    /**

         *

         * @author username

         * @param oldStage

      */

    13  无需再对boolean 值再进行判断,直接使用即可,如 if (success) { TODO…}。

        反例: if (success == true) { TODO…}

    14  POJO 类中的任何布尔类型的变量,都不要加 is,否则部分框架解析会引起序列化错误。反例:定义为基本数据类型 boolean isSuccess;的属性,它的方法也是 isSuccess(),RPC框架在反向解析的时候,“以为”对应的属性名称是 success,导致属性获取不到,进而抛出异常。

    15  if/for/while/switch/do 等保留字与左右括号之间都必须加空格。任何运算符左右必须加一个空格。说明:运算符包括赋值运算符=、逻辑运算符&&、加减乘除符号、三目运行符等。

    16  IDE 的 text file encoding 设置为 UTF-8。

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

    例如: "test".equals(object)

    18  POJO 类必须写 toString 方法。使用工具类 source> generate toString 时,如果继

    承了另一个 POJO 类,注意在前面加一下 super.toString。说明:在方法执行抛出异常时,可以直接调用 POJO 的 toString()方法打印其属性值,便于排查问题。

    19  使用索引访问用 String 的 split 方法得到的数组时,需做最后一个分隔符后有无内

    容的检查,否则会有抛 IndexOutOfBoundsException 的风险。说明:

    String str = "a,b,c,,"; String[] ary = str.split(",");

    //预期大于 3,结果是 3

    System.out.println(ary.length);

    20  【推荐】当一个类有多个构造方法,或者多个同名方法,这些方法应该按顺序放置在一起,便于阅读。

    21  【推荐】 类内方法定义顺序依次是:公有方法或保护方法 > 私有方法 > getter/setter

    方法。

    22 【推荐】setter 方法中,参数名称与类成员变量名称一致,this.成员名=参数名。在

    getter/setter 方法中,尽量不要增加业务逻辑,增加排查问题难度。

    反例:

    public Integer getData(){

    if(true) {

    return data + 100;

    } else {

    return data - 100;

    }

    }

    23  【推荐】循环体内,字符串的联接方式,使用 StringBuilder 的 append 方法进行扩展。

    反例:

    String str = "start";

    for(int i=0; i<100; i++){

    str = str + "hello";

    }

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

    24  【推荐】final 可提高程序响应效率,声明成 final 的情况:

    1) 不需要重新赋值的变量,包括类属性、局部变量。

    2) 对象参数前加 final,表示不允许修改引用的指向。

    3) 类方法确定不允许被重写。

    25  Map/Set 的 key 为自定义对象时,必须重写 hashCode 和 equals。正例:String 重写hashCode 和 equals 方法,所以我们可以非常愉快地使用 String 对象作为 key 来使用。

    26  使用集合转数组的方法,必须使用集合的 toArray(T[] array),传入的是类型完全

    一样的数组,大小就是 list.size()。

    反例:直接使用 toArray 无参方法存在问题,此方法返回值只能是 Object[]类,若强转其它类型数组将出现 ClassCastException 错误。

    正例:

    List<String> list = new ArrayList<String>(2);

    list.add("jun");

    list.add("jiang");

    String[] array = new String[list.size()];

    array = list.toArray(array);

    说明:使用 toArray 带参方法,入参分配的数组空间不够大时,toArray 方法内部将重新分配内存空间,并返回新数组地址;如果数组元素大于实际所需,下标为[ list.size() ]的数组元素将被置为 null,其它数组元素保持原值,因此最好将方法入参数组大小定义与集合元素个数一致

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

    方式,如果并发操作,需要对 Iterator 对象加锁。

    反例:

    List<String> a = new ArrayList<String>();

    a.add("1");

    a.add("2");

    for (String temp : a) {

    if("1".equals(temp)){

    a.remove(temp);

    }

    }

    说明:这个例子的执行结果会出乎大家的意料,那么试一下把“1”换成“2”,会是同样的结果吗?

    正例:

    Iterator<String> it = a.iterator();

    while(it.hasNext()){

    String temp = it.next();

    if(删除元素的条件){

    it.remove();

    }

    }

    28  【推荐】集合初始化时,尽量指定集合初始值大小。说明:ArrayList 尽量使用 ArrayList(int initialCapacity) 初始化。

    29  【推荐】使用 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 值组合集合。

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

    正例:注意线程安全,使用 DateUtils。亦推荐如下处理:

    private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>() {

    @Override

    protected DateFormat initialValue() {

    return new SimpleDateFormat("yyyy-MM-dd");

    }

    };

    说明:如果是 JDK8 的应用,可以使用 instant 代替 Date,Localdatetime 代替 Calendar,

    Datetimeformatter 代替 Simpledateformatter,官方给出的解释:simple beautiful strong

    immutable thread-safe。

    31  高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁;能

    锁区块,就不要锁整个方法体;能用对象锁,就不要用类锁。

    32  多线程并行处理定时任务时,Timer 运行多个 TimeTask 时,只要其中之一没有捕获

    抛出的异常,其它任务便会自动终止运行,使用 ScheduledExecutorService 则没有这个问题。

    33  创建线程或线程池时请指定有意义的线程名称,方便出错时回溯。

    34  在一个 switch 块内,每个 case 要么通过 break/return 来终止,要么注释说明程序

    将继续执行到哪一个 case 为止;在一个 switch 块内,都必须包含一个 default 语句并且放在最后,即使它什么代码也没有。

    35  循环体中的语句要考量性能,以下操作尽量移至循环体外处理,如定义对象、变量、获取数据库连接,进行不必要的 try-catch 操作(这个 try-catch 是否可以移至循环体外)。

    36  所有的抽象方法(包括接口中的方法)必须要用 javadoc 注释、除了返回值、参数、

    异常说明外,还必须指出该方法做什么事情,实现什么功能。

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

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

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

    39  代码修改的同时,注释也要进行相应的修改,尤其是参数、返回值、异常、核心逻辑等的修改。

        说明:代码与注释更新不同步,就像路网与导航软件更新不同步一样,如果导航软件严重滞后,就失去了导航的意义。 

    40  【参考】注释掉的代码尽量要配合说明,而不是简单的注释掉。

    说明:代码被注释掉有两种可能性:1)后续会恢复此段代码逻辑。2)永久不用。前者如果没有备注信息,难以知晓注释动机。后者建议直接删掉(代码仓库保存了历史代码)。

    41  【参考】对于注释的要求:第一、能够准确反应设计思想和代码逻辑;第二、能够描述业务含义,使别的程序员能够迅速了解到代码背后的信息。完全没有注释的大段代码对于阅读者形同天书,注释是给自己看的,即使隔很长时间,也能清晰理解当时的思路;注释也是给继任者看的,使其能够快速接替自己的工作。

    42  错误,不能工作(FIXME):(标记人,标记时间,[预计处理时间])在注释中用 FIXME 标记某代码是错误的,而且不能工作,需要及时纠正的情况。

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

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

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

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

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

    46  【推荐】任何数据结构的使用都应限制大小。说明:这点很难完全做到,但很多次的故障都是因为数据结构自增长,结果造成内存被吃光。

    47  【推荐】对于“明确停止使用的代码和配置”,如方法、变量、类、配置文件、动态配置属性等要坚决从程序中清理出去,避免造成过多垃圾。清理这类垃圾代码是技术气场,不要有这样的观念:“不做不错,多做多错”。

    48  不要捕获 Java 类库中定义的继承自 RuntimeException 的运行时异常类,如:

    IndexOutOfBoundsException / NullPointerException,这类异常由程序员预检查来规避,保证程序健壮性。

    正例: if(obj != null) {...}

    反例: try { obj.method() } catch(NullPointerException e){…}

    49  异常不要用来做流程控制,条件控制,因为异常的处理效率比条件分支低。

    50  finally 块必须对资源对象、流对象进行关闭,有异常也要做 try-catch。

    说明:如果 JDK7,可以使用 try-with-resources 方法。

    51  不能在 finally 块中使用 return,finally 块中的 return 返回后方法结束执行,不

    会再执行 try 块中的 return 语句。

    52  避免出现重复的代码(Don’t Repeat Yourself),即 DRY 原则。

    说明:随意复制和粘贴代码,必然会导致代码的重复,在以后需要修改时,需要修改所有的副本,容易遗漏。必要时抽取共性方法,或者抽象公共类,甚至是共用模块。

    正例:一个类中有多个 public 方法,都需要进行数行相同的参数校验操作,这个时候请抽取:

    private boolean checkParam(String str){...}

    53  日志打印输出的 POJO 类必须重写 toString 方法,否则只输出此对象的 hashCode 值(地址值),没啥参考意义。

    54  大量地输出无效日志,不利于系统性能提升,也不利于快速定位错误点。纪录日志时请

    思考:这些日志真的有人看吗?看到这条日志你能做什么?能不能给问题排查带来好处?

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

    反例:请勿使用 String args[]的方式来定义

    56  抽象类命名使用 Abstract 或 Base 开头;异常类命名使用 Exception 结尾;测试类命

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

    give me the ball!
  • 相关阅读:
    并发编程三要素:原子性,有序性,可见性
    【华为云技术分享】【Python成长之路】来聊聊多线程的几位“辅助”
    【华为云技术分享】根因分析
    【华为云技术分享】浅谈服务化和微服务化(下)
    【华为云技术分享】浅谈服务化和微服务化(上)
    【华为云技术分享】STM32 GPIO的原理、特性、选型和配置
    【华为云技术分享】快速理解spark-on-k8s中的external-shuffle-service
    【华为云技术分享】如何设计高质量软件-领域驱动设计DDD(Domain-Driven Design)学习心得
    【华为云技术分享】唐老师带你秒懂大数据,以及Spark和Flink在干啥咧
    【华为云技术分享】昇腾AI处理器软件栈--总览
  • 原文地址:https://www.cnblogs.com/JJJ1990/p/8038350.html
Copyright © 2011-2022 走看看