Top 10 Mistakes Java Developers Make

Top 10 Mistakes Java Developers Make

Reoriganize From http://www.programcreek.com/2014/05/top-10-mistakes-java-developers-make/

Convert Array to ArrayList

用以下方式将数组转成ArrayList

1
List<String> list = Arrays.asList(arr);

Arrays.asList()返回的Arrays的一个内部静态类ArrayList, 而不是java.util.ArrayList. java.util.Arrays.ArrayList会有一些诸如set(), get(), contains()的方法, 但是没有任何添加元素的方法, 因为这个类是定长的. 正确的做法如下:

1
ArrayList<String> arrayList = new ArrayList<String>(Arrays.asList(arr));

ArrayList 是允许接收一个集合类为参数的, 所以要把java.util.Arrays.ArrayList再通过ArrayList给构造一下.

Check If an Array Contains a Value

有人总喜欢这么做

1
2
Set<String> set = new HashSet<String>(Arrays.asList(arr));
return set.contains(targetValue);

但是没必要, 因为直接用也能看有无包含元素. 转成Set没有必要, 还要浪费构造开销.

1
Arrays.asList(arr).contains(targetValue);

甚至

1
2
3
4
5
for(String s: arr){
if(s.equals(targetValue))
return true;
}
return false;

但第一个可读性好一点

Remove an Element from a List Inside a Loop

size会变

1
2
3
4
5
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d"));
for (int i = 0; i < list.size(); i++) {
list.remove(i);
}
System.out.println(list);

迭代器异常, 会爆ConcurrentModificationException.

1
2
3
4
5
6
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d"));

for (String s : list) {
if (s.equals("a"))
list.remove(s);
}

正确的方式

1
2
3
4
5
6
7
8
9
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d"));
Iterator<String> iter = list.iterator();
while (iter.hasNext()) {
String s = iter.next();

if (s.equals("a")) {
iter.remove();
}
}

因为在foreach循环里, 编译器会自动将删除元素后再进行迭代器的next()操作, 这就会引起ConcurrentModificationException.异常. 可以对比一下Iterator的源码.

Hashtable vs HashMap

HashtableHashMap 最大的区别是同步化.

Use Raw Type of Collection

Java里, 原生态型(raw type)和通配符(wildcard type)可以混用. 比如 Set<?>.
但如下代码

1
2
3
4
5
6
7
8
public static void add(List list, Object o){
list.add(o);
}
public static void main(String[] args){
List<String> list = new ArrayList<String>();
add(list, 10);
String s = list.get(0);
}

会爆

1
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String at ...

因为原生态型的集合类跳过了泛型检查, Set, Set<?>, 和 Set<Object> 是存在很大差别的. More details in Raw type vs. Unbounded wildcard .

Access Level

public很方便, 但是这样设计很丑陋.
如何优雅设计, 参见public, default, protected, and private.

ArrayList vs. LinkedList

LinkedList 大量删除插入, 少量随机访问
ArrayList 正好相反.

Mutable vs. Immutable

mutable通常用来避免过多的中间对象. 一个经典的例子就是大数字符串, 如果使用immutable的字符串, 那就将产生大量中间对象, 既耗空间又浪费时间, 还要垃圾立即回收.

1
2
3
4
String result="";
for(String s: arr){
result = result + s;
}

因此使用StringBuffer这种mutable的类比较合适.
more details in Why String is immutable in Java ?

Constructor of Super and Sub

!pic
父类默认构造未定义, 但是子类定义了. Java里, 一个类如果没有定义构造方法, 编译器会自动插一个无参的, 但是如果显示定义了那就不插了(这和C++不一样).
而此时子类的无参构造需要调用父类的无参构造, 但是发现不存在, 因此要报错.
要想解决这个问题, 要么给父类加一个无参的

1
2
3
public Super(){
System.out.println("Super");
}

要么把自定义的父类构造给去了, 再要么直接把super(value)塞子类构造里.

const or Constructor?

两种方式创建String

1
2
3
4
//1. use double quotes
String x = "abc";
//2. use constructor
String y = new String("abc");

但是

1
2
3
4
5
6
7
8
9
String a = "abcd";
String b = "abcd";
System.out.println(a == b); // True
System.out.println(a.equals(b)); // True

String c = new String("abcd");
String d = new String("abcd");
System.out.println(c == d); // False
System.out.println(c.equals(d)); // True

字符串直接赋值是常量, 因此都相等; 但new的时候是各自开辟空间, == 比较的是对象是否相等, 因而不等; equals比较的是值那就相等.

Contents
  1. 1. Top 10 Mistakes Java Developers Make
    1. 1.1. Convert Array to ArrayList
    2. 1.2. Check If an Array Contains a Value
    3. 1.3. Remove an Element from a List Inside a Loop
    4. 1.4. Hashtable vs HashMap
    5. 1.5. Use Raw Type of Collection
    6. 1.6. Access Level
    7. 1.7. ArrayList vs. LinkedList
    8. 1.8. Mutable vs. Immutable
    9. 1.9. Constructor of Super and Sub
    10. 1.10. const or Constructor?