Java注意点...
写这篇文章的目的,只是提醒自己一些在开发中的注意点,只是浅尝辄止,不深究。仅仅给自己提醒用。这篇文章会持续更新的......
慎用重载
重载(overload) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。
在Java1.5之前,基本类型都根本不同于所有的引用类型,但是当自动装箱出现后,就导致了一些麻烦。来看个例子:
1 public class SetList { 2 public static void main(String[] args){ 3 Set<Integer> set = new TreeSet<Integer>(); 4 List<Integer> list = new ArrayList<Integer>(); 5 6 for (int i = -3; i < 3;i++){ 7 set.add(i); 8 list.add(i); 9 } 10 System.out.println(set + " " + list); 11 for (int i = 0;i < 3;i++){ 12 set.remove(i); 13 list.remove(i); 14 } 15 System.out.print(set + " " + list); 16 } 17 }
上面的代码,首先将-3至2之间的整数都添加到了set和list中,然后都进行了三次相同的remove操作。你觉得程序的输出结果是上面呢?
是不是觉得应该打印出:
[-3, -2, -1, 0, 1, 2] [-3, -2, -1, 0, 1, 2]
[-3, -2, -1] [-3, -2, -1]
实际的输出是:
[-3, -2, -1, 0, 1, 2] [-3, -2, -1, 0, 1, 2]
[-3, -2, -1] [-2, 0, 2]
惊讶吗?原来是这样的:
❤ set.remove(i)调用选择的重载方法remove(E),这里的E是集合的元素类型,将int自动装箱到Integer中。这也是我们程序本来希望的目的。
❤ 另一方面list.remove(i)调用的是remove(int i),这个方法是从指定位置上移除元素,移除[-3, -2, -1, 0, 1, 2]中的第一个元素,即-3,然后元素前移,变为[-2, -1, 0, 1, 2],移除第一个元素,即-1,继续前移,变为[ -2, 0, 1, 2],移除第二个元素,即1,因此,最后的结果就是[-2, 0, 2]。
要修改上面例子为正确的结果,很简单:
for (int i = 0;i < 3;i++){ set.remove(i); list.remove((Integer) i); }
这样就能达到我们预期的结果。
所以以后遇到基本类型和包装类型时,需注意在集合中的自动拆箱和自动装箱。
返回零长度的数组或者集合,而不是null
在开发中,下面这样的场景是否常见?
private final List<String> strList = new ArrayList<String>(); public String[] getString (){ if (strList.size() == 0){ return null; } else{ return ...; } }
对于一个返回null而不是返回零长度的数组或者集合的方法,几乎每次用到该方法时都需要先对其进行非空判断。这样的做法是不合理的,很容易出错,因为有可能使用这个方法的程序员并不知道需要处理null,同时,这样的错误有可能会在很长的时间内不会被发现。这样就对程序造成了潜在的异常。
有人认为:null返回值比零长度的数组要好,因为避免了分配数组所需要的开销。这种观点是站不住脚的:
1.在这个级别上担心性能问题是不明智的,除非分析表明这个方法正是造成性能问题的源头。
2.对于不返回任何元素的调用,每次都返回同一个零长度数组是有可能的,因为零长度数组是不可变的,而不可变对象可以被自由的共享。
所以返回空的数组时,可以这样做:
private final List<String> strList = new ArrayList<String>(); private static final String[] emptyStr = new String[0]; public String[] getString (){ if (strList.size() == 0){ return emptyStr; } else{ return ...; } }
同样的,集合也可以做成在每当需要返回空集合时都返回一个不可变的空集合。Collections.emptySet、Collections.emptyList和emptyMap方法正是这样的。
public List<String> getStrList(List list){ if (list.isEmpty()){ return Collections.emptyList(); }else { return ...; } }
总之,返回类型为数组或者集合的方法没理由返回null,而是返回一个零长度的数组或者集合。