JAVA 开发者常犯的 10 大错误【译】

本贴最后更新于 1593 天前,其中的信息可能已经时移俗易

1.将 Array 转换成 ArrayList

通常我们将 Array 转成 ArrayList 都是使用下面的语法,

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

Arrays.asList()方法将返回 ArrayList,它是 Arrays 中的一个私有静态类而不是 java.util.ArrayList 类。 java.util.Arrays.ArrayList 类具有 set ()、 get ()和 contains ()方法,但没有任何用于添加元素的方法,因此其大小是固定的。 要创建一个真正的 ArrayList,你应该这样做:

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

2.检查数组是否包含值

常见错误做法:

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

上面这个代码可以达到我们的目的,但是不需要转换 将列表转换为集合需要额外的时间。 可以简化成:

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

3.从循环列表中删除某个元素

错误做法:

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);

输出结果:
[b, d]
这种方法有一个严重的问题。删除元素时,列表的大小会缩小,索引也会发生变化。因此,如果您希望通过使用索引来删除循环中的多个元素,那将无法正常工作。
您可能知道使用迭代器是在循环中删除元素的正确方法,而且您知道 Java 中的 foreach 循环工作起来像迭代器,但实际上并非如此。代码如下。

ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d"));
 
for (String s : list) {
	if (s.equals("a"))
		list.remove(s);
}

它将抛出 ConcurrentModificationException
使用迭代器进行删除能够避免这个问题,代码如下

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();
	}
}

.next() 必须在 .remove() 之前调用。

4.Hashtable vs HashMap

map 预览
MapClassHierarchy600x354.jpg

  • HashMap:底层由哈希表实现,对键或值没有排序。
  • TreeMap:基于红黑树实现,并按键排序。
  • Hashtable:与 HashMap 相反,Hashtable 是同步的。 它有一个同步的开销。
  • LinkedHashMap:保留插入顺序,有序。

注意项:
如果 HashMap 的键是一个自定义对象,那么需要遵循 equals ()和 hashCode ()契约。
由于 TreeMaps 是按键排序的,因此 key 的对象必须能够相互比较,这就是它必须实现 Comparable 接口的原因

###5.使用原始类型(Object)的集合

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);
}

上面这段会出现如下报错信息:

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

使用原始类型集合是危险的,因为原始类型集合跳过了泛型类型检查,并且不安全。

###6. 访问级别
开发人员经常使用 public 作为类字段。 通过直接引用字段值很方便,但这是一个非常糟糕的设计。 正确的做法是尽可能低为成员提供低的访问级别。
下表总结了成员的不同修饰符的访问级别,访问级别决定字段和方法的可访问性。 它有 4 个级别: public、 protected、 package-private (没有显式修饰符)或 private。
accesslevel.png

7.ArrayList vs. LinkedList

当开发人员不知道 ArrayList 和 LinkedList 之间的区别时,他们通常使用 ArrayList,因为它看起来很熟悉。 然而,它们之间存在着巨大的性能差异。
集合预览图如下。
javacollectionhierarchy.jpeg
Arraylist 由一个可调整大小的数组实现。 随着更多的元素被添加到 ArrayList 中,它的大小会动态增加。 它的元素可以通过 get 和 set 方法直接访问,因为 ArrayList 实际上是一个数组。
Linkedlist 实现为双链表。 它在添加和删除方面的性能优于数组列表,但在 get 和 set 方法上性能较差。
时间复杂度比较如下:
arraylistvslinkedlistcomplexity.png
性能比较:
arraylistvslinkedlist1.png
他们的表现有明显的差异。 Linkedlist 在添加和删除方面更快,但在 get 方面更慢。 根据复杂度表和测试结果,我们可以确定何时使用 ArrayList 或 LinkedList。 简而言之,如果下列情况下 LinkedList 应该是首选的:
* 元素没有大量的随机存取
* 有大量的添加 / 删除操作


8.可变对象 VS 不可变对对象

不可变对象有许多优点,如简单性、安全性等。 但是,对于每个不同的值,它需要一个单独的对象,而且对象太多可能会导致垃圾收集的高成本。 在可变和不可变之间进行选择时,应该有一个平衡。
通常,使用可变对象是为了避免产生过多的中间对象。 一个典型的例子是连接大量的字符串。 如果使用不可变字符串,则会生成许多可立即进行垃圾收集的对象。 这会浪费 CPU 的时间和精力,而使用可变对象是正确的解决方案(StringBuilder


###9.父类和子类构造器
Implicitsuperconstructorisundefinedfordefaultconstructor.png
由于未定义默认父类构造函数,因此发生此编译错误。 在 Java 中,如果类没有定义构造函数,编译器将默认为类插入默认的无参数构造函数。 如果在 Super 类中定义了一个构造函数,在这种情况下,Super (String s) ,编译器不会插入默认的无参数构造函数。 这就是上面提到的父类的情况。


###10.使用""还是构造器初始化 String

//1. 使用双引号
String x = "abc";
//2. 构造器方式
String y = new String("abc");

下面我们分析一下他们之间的区别:

例子 1

String a = "abcd";
String b = "abcd";
System.out.println(a == b);  // True
System.out.println(a.equals(b)); // True

a==b 为 true,因为 a 和 b 在方法区域中引用了相同的字符串。 内存引用是相同的。
当多次创建同一字符串时,每个不同字符串值只存储一个副本。 这叫做“字符串主流”。 Java 中的所有编译时常量字符串都会自动实现。

例子 2

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

c == d 是 false,因为 c 和 d 引用堆中的两个不同对象。 不同的对象总是有不同的内存引用。

下面这个图表说明了上述两种情况:
constructorvsdoublequotesJavaStringNewPage650x324.png
772dedd20f0443648fe19bf102c78efa.jpeg

原文链接

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3169 引用 • 8207 回帖 • 1 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...