此列表总结了Java开发人员经常犯的十大错误。
1. 将Array转换为ArrayList
要将数组转换为 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));
构造函数ArrayList可以接受Collection类型,它也是一个超类型java.util.Arrays.ArrayList。
#2。检查数组是否包含值
开发人员经常这样做:
Set<String> set = new HashSet<String>(Arrays.asList(arr));
return set.contains(targetValue);
代码可以工作,但不需要先将列表转换为set。将列表转换为集合需要额外的时间。它可以很简单:
Arrays.asList(arr).contains(targetValue);
要么
for(String s: arr){
if(s.equals(targetValue))
return true;
}
return false;
第一个比第二个更可读。
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()…在foreach循环中,编译器将使.next()在移除元素操作后调用,这将导致ConcurrentModificationException…您可能想看看ArrayList.iterator().
4. Hashtable vs HashMap
根据算法中的约定,Hashtable 是数据结构的名称。但是在 Java 中,数据结构的名称是 HashMap .其中一个关键的区别是 Hashtable和 HashMap 那是 Hashtable 是同步的。所以很多时候你不需要 Hashtable,相反 HashMap 应该用。HashMap与Treemap vs Hashtable与LinkedHashMap
HashMap vs. TreeMap vs. Hashtable vs. LinkedHashMap
Top 10 questions about Map
5. 使用原始类型的集合
在 Java,原始类型和无界通配符类型很容易混合在一起。举个例子,Set是原始类型,而 Set<?> 是无界通配符类型。考虑使用原始类型的下列代码 List 作为参数的代码:
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 …
使用原始类型集合很危险,因为原始类型集合跳过泛型类型检查而不安全。之间存在巨大差异Set,Set<?>和Set<Object>。
查看Raw type vs. Unbounded wildcard and Type Erasure.
6. 访问权限
开发人员经常在类字段中使用 public 。通过直接引用很容易获得字段值,但这是一个非常糟糕的设计。经验法则是为成员提供尽可能低的访问级别。
public,default,protected和private
7. ArrayList 与 LinkedList
当开发人员不知道之间的区别ArrayList和LinkedList,他们经常使用ArrayList,因为它看起来很熟悉。但是,它们之间存在巨大的性能差异。简而言之,LinkedList如果存在大量的添加/删除操作并且没有大量随机访问操作,则应该首选。如果您不ArrayList熟悉LinkedList,请查看以获取有关其效果的更多信息。
8. 可变 与 不可变
不可变对象具有许多优点,例如简单性,安全性等。但是对于每个不同的值,它需要单独的对象,并且太多的对象可能导致高的垃圾收集成本。在可变和不可变之间进行选择时应该保持平衡。
通常,可变对象用于避免产生太多中间对象。一个典型的例子是连接大量字符串。如果使用不可变字符串,则会产生大量符合垃圾收集条件的对象。这会浪费CPU上的时间和精力,使用可变对象正确的解决方案(例如StringBuilder)。
String result="";
for(String s: arr){
result = result + s;
}
在需要可变对象时还有其他情况。例如,将可变对象传递给方法可以让您收集多个结果,而不会跳过太多语法箍。另一个例子是排序和过滤:当然,您可以创建一个获取原始集合的方法,并返回一个已排序的方法,但这对于较大的集合来说会变得非常浪费。(来自dasblinkenlight对Stack Overflow 的回答)
9. Constructor of Super and Sub

发生此编译错误,因为默认的超级构造函数是未定义的。在Java中,如果类没有定义构造函数,编译器将默认为该类插入默认的无参数构造函数。如果构造函数是在Super类中定义的,在本例中是Super(String s),编译器将不会插入默认的无参数构造函数。这是上面超级类的情况。
Sub类的构造函数(带参数或无参数)将调用无参数的超级构造函数。由于编译器尝试将super()插入Sub类中的2个构造函数,但未定义Super的默认构造函数,因此编译器会报告错误消息。
要解决这个问题,只需
1)将Super()构造函数添加到Super类中即可
public Super(){
System.out.println("Super");
}
或2)删除自定义的超级构造函数,或3)添加super(value)到子构造函数。
10. “” 还是构造函数?
字符串可以通过两种方式创建:
//1. use double quotes
String x = "abc";
//2. use constructor
String y = new String("abc");
有什么区别?
以下示例可以提供快速答案:
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
有关如何在内存中分配它们的更多详细信息,请查看使用“”或构造函数创建Java字符串?。

本文总结了Java开发中常见的十大误区,包括Array与ArrayList转换、数组元素检查、循环中删除元素、Hashtable与HashMap的选择、原始类型集合使用、访问权限不当、ArrayList与LinkedList性能差异、可变与不可变对象的平衡、构造函数与双引号创建字符串的区别,以及Super与Sub类构造函数的问题。
30

被折叠的 条评论
为什么被折叠?



