Java开发手册记录

Posted by ijays on September 10, 2017

最近又阅读了一遍阿里的Java 开发手册,发现了一些平时没有太注意的点,特此记录下来方便平时查阅。

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

    eg:定义为基本数据类型 boolean isDeleted 的属性,它的方法也是isDeleted(),RPC框架在反向解析的时候,“以为”对应的属性名称是deleted,导致属性获取不到,进而抛出异常。

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

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

    eg:”test”.equals(object);

    注:可以使用java.util.Object#equals(JDK7 引入的工具类),不过在Android 中此方法只能在API19 及以上使用。

  4. 所有的相同类型的包装类对象之间==值的比较==,全部使用 equals 方法比较。

    因为对于-128 到128 范围内的赋值,Integer 对象是在IntegerCache.cache 产生,会复用已有对象,这个区间内的 Integer 值可以直接使用 == 进行判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象。因此推荐使用 equals 方法进行判断。

  5. 关于集合 hashcode 的处理:

    a. 只要重写 equals,就必须重写hashcode。

    b. 因为Set 存储的是不重复的对象,依据 hashcode 和equals 进行推断,所以 Set 存储的对象必须重写这两个方法。

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

    注:asList 的返回对象是一个 Arrays 内部类,并没有实现集合的修改方法。Arrays.asList 体现的是适配器模式,只是转换接口,后台的数据仍是数组。

  7. 不要再foreach循环里进行元素的remove/add 操作。remove 操作使用Iterator方式,如果需要并发操作,需要对Iterator 对象加锁。

    List<String> list = new ArrayList<>();
    		list.add("1");
    		list.add("2");
    //		for (String string : list) {
    //			if ("2".equals(string)) {
    //				// 不要再foreach循环里进行元素的add、remove操作
    //              // 运行这段代码会java.util.ConcurrentModificationException
    //				list.remove(string);
    //			}
    //		}
    
    		Iterator<String> iterator = list.iterator();
    		while (iterator.hasNext()) {
    			String string = (String) iterator.next();
    			if ("2".equals(string)) {
    				iterator.remove();
    			}
    		}
    		for (String string2 : list) {
    			System.out.println("element is-->" + string2);
    		}
    

  8. 集合初始化时,制定集合初始值大小。

    HashMap 使用HashMap(int initialCapacity) 初始化,其中

    initialCapacity = (需要存储的元素个数 / loader factor) + 1,loader factor 默认值为0.75,如果暂时无法无法确定初始值大小,可以设置默认值为16。

  9. HashMap 是线程不安全的,其Key 和 Value 允许为null;ConcurrentHashMap 是线程安全的,它和 HashMap 一样均继承自 AbstractMap,但是的Key,Value 则是不允许为 null 的。

  10. 如果 substring 方法中 index 等于0,则直接返回当前对象;如果 index 不等于0,则 new 一个 sub 的对象返回。

   String str = "abc";
   System.out.println("abc" == str);//打印结果结果true
   System.out.println("abc" == substring(0));//打印结果结果true
   System.out.println("ab".substring(1));//打印结果结果false

  1. 当两个字符串常量连接(相加)时,得到的依然是字符串常量并且存储在常量池中也只有一份。

    String str = "strA";
    String str1 = "str" + "A";
    System.out.println(str == str1)//打印结果结果true
    
    

  2. 当一个字符串常量与一个 String 类型变量连接时,得到的新字符串不再存储在常量池中,而是在堆中新建一个 String 对象来存放。因为常量池中要求存放的是常量,有String 类型变量当然不能存储在常量池中了。

    String strA = "ab";
    String strB = "b";
    String strC = "a" + "strB";
    System.out.println(strA ==strC);//打印结果结果false