1. 11.关于基本数据类型与包装数据类型的使用标准如下:
    2. 1)【强制】所有的POJO类属性必须使用包装数据类型。
    3. 2)【强制】RPC方法的返回值和参数必须使用包装数据类型。
    4. 3)【推荐】所有的局部变量使用基本数据类型。
    5. 说明:POJO类属性没有初值是提醒使用者在需要使用时,必须自己显式地进行赋值,任何NPE问题,或者入库检查,都由使用者来保证。正例:数据库的查询结果可能是null,因为自动拆箱,用基本数据类型接收有NPE风险。反例:比如显示成交总额涨跌情况,即正负x%,x为基本数据类型,调用的RPC服务,调用不成功时,返回的是默认值,页面显示为0%,这是不合理的,应该显示成中划线。所以包装数据类型的null值,能够表示额外的信息,如:远程调用失败,异常退出。
    1. 13.【强制】序列化类新增属性时,请不要修改serialVersionUID字段,避免反序列失败;如果完全不兼容升级,避免反序列化混乱,那么请修改serialVersionUID值。
    2. 说明:注意serialVersionUID不一致会抛出序列化运行时异常
    1. 14.【强制】构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在init方法中。
    1. 17.【推荐】使用索引访问用Stringsplit方法得到的数组时,需做最后一个分隔符后有无内容的检查,否则会有抛IndexOutOfBoundsException的风险。
    2. 说明:String str = "a,b,c,,";
    3. String[] ary = str.split(","); // 预期大于3,结果是3
    4. System.out.println(ary.length);
    1. 21.【推荐】循环体内,字符串的连接方式,使用StringBuilderappend方法进行扩展。
    2. 说明:下例中,反编译出的字节码文件显示每次循环都会new出一个StringBuilder对象,然后进行append操作,最后通过toString方法返回String对象,造成内存资源浪费。
    3. 反例:
    4. String str = "start";
    5. for(int i=0; i<100; i++){
    6. str = str + "hello";
    7. }
    1. 23.【推荐】慎用Objectclone方法来拷贝对象。
    2. 说明:对象clone方法默认是浅拷贝,若想实现深拷贝需覆写clone方法实现域对象的深度遍历式拷贝。
    1. 24.【推荐】类成员与方法访问控制从严:
    2. 1)如果不允许外部直接通过new来创建对象,那么构造方法必须是private
    3. 2)工具类不允许有publicdefault构造方法。
    4. 3)类非static成员变量并且与子类共享,必须是protected
    5. 4)类非static成员变量并且仅在本类使用,必须是private
    6. 5)类static成员变量如果仅在本类使用,必须是private
    7. 6)若是static成员变量,考虑是否为final
    8. 7)类成员方法只供类内部调用,必须是private
    9. 8)类成员方法只对继承类公开,那么限制为protected
    10. 说明:任何类、方法、参数、变量,严控访问范围。过于宽泛的访问范围,不利于模块解耦。思考:如果
    11. 是一个private的方法,想删除就删除,可是一个publicservice成员方法或成员变量,删除一下,不得手心冒点汗吗?变量像自己的小孩,尽量在自己的视线内,变量作用域太大,无限制的到处跑,那么你会担心的。

    集合处理

    1. 1.【强制】关于hashCodeequals的处理,遵循如下规则:
    2. 1)只要覆写equals,就必须覆写hashCode
    3. 2)因为Set存储的是不重复的对象,依据hashCodeequals进行判断,所以Set存储的对象必须覆写这两个方法。
    4. 3)如果自定义对象作为Map的键,那么必须覆写hashCodeequals
    5. 说明:String已覆写hashCodeequals方法,所以我们可以愉快地使用String对象作为key来使用。
    6. 2.【强制】ArrayListsubList结果不可强转成ArrayList,否则会抛出ClassCastException异常,即java.util.RandomAccessSubList cannot be cast to java.util.ArrayList
    7. 说明:subList 返回的是ArrayList的内部类SubList,并不是ArrayList而是ArrayList 的一个视图,对于SubList子列表的所有操作最终会反映到原列表上。
    8. 3.【强制】使用Map的方法keySet()/values()/entrySet()返回集合对象时,不可以对其进行添加元素操作,否则会抛出UnsupportedOperationException异常。
    9. 5.【强制】在subList场景中,高度注意对原集合元素的增加或删除,均会导致子列表的遍历、增加、删除产生ConcurrentModificationException异常
    1. 6.【强制】使用集合转数组的方法,必须使用集合的toArray(T[] array),传入的是类型完全一致、长度为0的空数组。
    2. 反例:直接使用toArray无参方法存在问题,此方法返回值只能是Object[]类,若强转其它类型数组将出现ClassCastException错误。
    3. 正例:
    4. List<String> list = new ArrayList<>(2);
    5. list.add("guan");list.add("bao");
    6. String[] array = list.toArray(new String[0]);
    7. 说明:使用toArray带参方法,数组空间大小的length
    8. 1)等于0,动态创建与size相同的数组,性能最好。
    9. 2)大于0但小于size,重新创建大小等于size的数组,增加GC负担。
    10. 3)等于size,在高并发情况下,数组创建完成之后,size正在变大的情况下,负面影响与上相同。
    11. 4)大于size,空间浪费,且在size处插入null值,存在NPE隐患。
    1. 7.【强制】在使用Collection接口任何实现类的addAll()方法时,都要对输入的集合参数进行NPE判断。
    2. 8.【强制】使用工具类Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方法,它的add/remove/clear方法会抛出UnsupportedOperationException异常。
    3. 说明:asList的返回对象是一个Arrays内部类,并没有实现集合的修改方法。
    4. Arrays.asList体现的是适配器模式,只是转换接口,后台的数据仍是数组。
    5. String[] str = new String[] { "yang", "hao" };Listlist = Arrays.asList(str);
    6. 第一种情况:list.add("yangguanbao");运行时异常。
    7. 第二种情况:str[0]= "changed"; 也会随之修改,反之亦然。
    1. 9.【强制】泛型通配符<? extends T>来接收返回的数据,此写法的泛型集合不能使用add方法,而<? superT>不能使用get方法,作为接口调用赋值时易出错。
    2. 说明:扩展说一下PECS(Producer Extends Consumer Super)原则:第一、频繁往外读取内容的,适合用<? extends T>。第二、经常往里插入的,适合用<? superT>
    1. 11.【强制】不要在foreach循环里进行元素的remove/add操作。remove元素请使用Iterator方式,如果并发操作,需要对Iterator对象加锁。
    2. 正例:
    3. List<String> list = new ArrayList<>();
    4. list.add("1");
    5. list.add("2");
    6. Iterator<String> iterator = list.iterator();
    7. while (iterator.hasNext()) {
    8. String item=iterator.next(); if (删除元素的条件) {
    9. iterator.remove();
    10. }
    11. }
    1. 12.【强制】在JDK7版本及以上,Comparator实现类要满足如下三个条件,不然Arrays.sortCollections.sort会抛IllegalArgumentException异常。
    2. 说明:三个条件如下
    3. 1xy的比较结果和yx的比较结果相反。
    4. 2x>yy>z,则x>z
    5. 3x=y,则xz比较结果和yz比较结果相同
    1. 15.【推荐】使用entrySet遍历Map类集合KV,而不是keySet方式进行遍历。说明:keySet其实是遍历了2次,一次是转为Iterator对象,另一次是从hashMap中取出key所对应的value。而entrySet只是遍历了一次就把keyvalue都放到了entry中,效率更高。如果是JDK8,使用Map.forEach方法。
    2. 正例:
    3. values()返回的是V值集合,是一个list集合对象;
    4. keySet()返回的是K值集合,是一个Set集合对象;
    5. entrySet()返回的是K-V值组合集合。

    建议

    1. 时间戳类型: Instant时间戳类
    1. HashMapHashtableConcurrentHashMap的原理与区别
    1. 线程池不允许使用Executors,而是通过ThreadPoolExecutor的方式