Java开发者经常会犯的前十种错误列表_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > Java开发者经常会犯的前十种错误列表

Java开发者经常会犯的前十种错误列表

 2015/2/26 19:33:28  AILIKES  程序员俱乐部  我要评论(0)
  • 摘要:本文总结了Java开发者经常会犯的前十种错误列表。Top1.数组转换为数组列表将数组转换为数组列表,开发者经常会这样做:[java]viewplaincopyprint?List<String>list=Arrays.asList(arr);List<String>list=Arrays.asList(arr);Arrays.asList()将返回一个数组内部是私有静态类的ArrayList,这不是java.util.ArrayList类,java.util
  • 标签:Java 开发 开发者 错误

本文总结了Java开发者经常会犯的前十种错误列表。

Top1. 数组转换为数组列表

将数组转换为数组列表,开发者经常会这样做:

?

[java] view plaincopyprint?
    class="dp-j">
  1. List<String>?list?=?Arrays.asList(arr);??
List<String> list = Arrays.asList(arr);

?

Arrays.asList()将返回一个数组内部是私有静态类的ArrayList,这不是java.util.ArrayList类,java.util.Arrays.ArrayList类有set()、 get()、 contains()方法,但是没有任何加元素的方法,因此它的大小是固定的。你应该这么做来创建一个真正的数组:

?

[java] view plaincopyprint?
  1. ArrayList<String>?arrayList?=?new?ArrayList<String>(Arrays.asList(arr));??
ArrayList<String> arrayList = new ArrayList<String>(Arrays.asList(arr));

?

ArrayList的构造函数能够接受一个集合类型,这也是java.util.Arrays.ArrayList的超级类型。

Top2. 检查一个数组包含一个值

开发者经常这么做:

?

[java] view plaincopyprint?
  1. Set<String>?set?=?new?HashSet<String>(Arrays.asList(arr));??
  2. return?set.contains(targetValue);??
Set<String> set = new HashSet<String>(Arrays.asList(arr));
return set.contains(targetValue);

?

代码可以工作,但是没有必要首先转换列表到Set,转换一个列表到一个Set需要额外的时间。因此你可以把它简化为:

?

[java] view plaincopyprint?
  1. Arrays.asList(arr).contains(targetValue);??
Arrays.asList(arr).contains(targetValue);

?

?

[java] view plaincopyprint?
  1. for(String?s:?arr){??
  2. ????if(s.equals(targetValue))??
  3. ????????return?true;??
  4. }??
  5. return?false;??
for(String s: arr){
	if(s.equals(targetValue))
		return true;
}
return false;

?

第一个比第二个更具可读性

Top3. 在一个循环中从一个列表里删除一个元素

考虑下面删除元素的代码在迭代中的结果:

?

[java] view plaincopyprint?
  1. ArrayList<String>?list?=?new?ArrayList<String>(Arrays.asList("a",?"b",?"c",?"d"));??
  2. for?(int?i?=?0;?i?<?list.size();?i++)?{??
  3. ????list.remove(i);??
  4. }??
  5. System.out.println(list);??
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);

?

输出是:

?

[java] view plaincopyprint?
  1. [b,?d]??
[b, d]

?

该方法有一个严重的问题,当一个元素被删除时,列表收缩的大小以及指针改变了。所以想要在循环内利用指针删除多个元素是无法正常进行的。

这种情况下使用迭代器才是正确的方法,foreach循环在Java中的工作像是一个迭代器,但实际上并不是,考虑下面的代码:

[java] view plaincopyprint?
  1. ArrayList<String>?list?=?new?ArrayList<String>(Arrays.asList("a",?"b",?"c",?"d"));??
  2. ???
  3. for?(String?s?:?list)?{??
  4. ????if?(s.equals("a"))??
  5. ????????list.remove(s);??
  6. }??
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d"));
 
for (String s : list) {
	if (s.equals("a"))
		list.remove(s);
}

?

它会报出ConcurrentModificationException异常

相反下面这个就可以正常工作。

?

[java] view plaincopyprint?
  1. ArrayList<String>?list?=?new?ArrayList<String>(Arrays.asList("a",?"b",?"c",?"d"));??
  2. Iterator<String>?iter?=?list.iterator();??
  3. while?(iter.hasNext())?{??
  4. ????String?s?=?iter.next();??
  5. ???
  6. ????if?(s.equals("a"))?{??
  7. ????????iter.remove();??
  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();
	}
}

?

?

.next()必须在.remove()之前被调用。在foreach循环中,编译器将在删除元素操作之后调用.next(),这也是导致ConcurrentModificationException异常的原因,你可以点击此处查看ArrayList.iterator()的源代码。

Top4. Hashtable vs HashMap

根据算法的常规,Hashtable是对数据结构的称呼。但是在Java中,数据结构的名称是HashMap。Hashtable和HashMap关键不同之一是Hashtable是同步的。

关于这一点可查看以下两个链接:

HashMap vs. TreeMap vs. Hashtable vs. LinkedHashMap

Map问题Top10

Top5. 使用集合的原始类型

在Java中,原始类型和无限制通配符类型很容易被混淆。以Set为例,Set是原始类型,而Set(?)则是无限制的通配符类型。

考虑下面的代码,以一个原始类型List作为参数:

?

[java] view plaincopyprint?
  1. public?static?void?add(List?list,?Object?o){??
  2. ????list.add(o);??
  3. }??
  4. public?static?void?main(String[]?args){??
  5. ????List<String>?list?=?new?ArrayList<String>();??
  6. ????add(list,?10);??
  7. ????String?s?=?list.get(0);??
  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);
}

?

该代码会抛出一个异常:

?

[java] view plaincopyprint?
  1. Exception?in?thread?"main"?java.lang.ClassCastException:?java.lang.Integer?cannot?be?cast?to?java.lang.String??
  2. ????at?...??
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 wildcardType Erasure

Top6. 访问级别

开发者经常对类域使用public,这很容易通过直接引用获得域值,但这是一个非常糟糕的设计。根据经验来说是给予成员的访问级别越低越好。

详细情况可点击查看Java中成员访问级别:public、protected、private

Top7.ArrayList VS LinkedList

如果你不知道ArrayList和LinkedList之间的区别时,你可能会经常的选用ArrayList,因为它看起来看熟悉。然而它们之间有巨大的性能不同。简单的来说,如果有大量的添加/caozuo.html" target="_blank">删除操作,并且没有很多的随机存取操作时,LinkedList应该是你的首选。如果您对此不是很了解的话,点此此处查看更多关于它们性能的信息。

Top8. Mutable VS Immutable

Immutable对象有很多优势,比如简单、安全等等。但它要求每一个不同的值都需要有一个不同的对象,而太多的对象可能会导致垃圾收集的高成本。所以对Mutable和Immutable的选择应该有一个平衡点。

一般来说,Mutable对象用于避免产生过多的中间对象,经典的例子是连接大量的字符串数。如果你使用Immutable字符串,那么会产生很多符合垃圾收集条件的对象。这对CPU是浪费时间和精力的,当其可以使用Mutable对象作为正确的解决方案。(如StringBuilder)

?

[java] view plaincopyprint?
  1. String?result="";??
  2. for(String?s:?arr){??
  3. ????result?=?result?+?s;??
  4. }??
String result="";
for(String s: arr){
	result = result + s;
}

?

这里还有一些其他Mutable对象可取的情况。例如mutable对象传递到方法中允许你在不跳过太多语法的情况下收集多个结果。另一个例子是排序和过滤,你可以构建一个带有原有集合的方法,并返回一个已排序的,不过这对大的集合来说会造成更大的浪费。

推荐阅读:为什么字符串是Immutable?

Top9. Super和Sub构造函数


这个编译错误是因为默认的Super构造函数是未定义的。在Java中,如果一个类没有定义一个构造函数,编译器会默认的为类插入一个无参数构造函数。如果一个构造函数是在Super类中定义的,这种情况下Super(String s),编译器不会插入默认的无参数构造函数。

另一方面,Sub类的构造函数,无论带不带有参数,都会调用无参数的Super构造函数。

编译器在Sub类中试图将Super()插入到两个构造函数中,但是Super默认的构造函数是没有定义的,编译器才会报错。如何解决这一问题?你只需在Super类中添加一个Super()构造函数,如下所示:

?

[java] view plaincopyprint?
  1. public?Super(){??
  2. ????System.out.println("Super");??
  3. }??
public Super(){
    System.out.println("Super");
}

?

或移除自定义的Super构造函数,又或者在Sub函数中添加super(value)。

这方面想了解更多的可以点击此处查看。

Top10. ""或构造函数?

字符串可以通过两种方式创建:

?

[java] view plaincopyprint?
  1. //1.?use?double?quotes??
  2. String?x?=?"abc";??
  3. //2.?use?constructor??
  4. String?y?=?new?String("abc");??
//1. use double quotes
String x = "abc";
//2. use constructor
String y = new String("abc");

?

它们之间有何不同?下面的例子可以给出答案:

?

[java] view plaincopyprint?
  1. String?a?=?"abcd";??
  2. String?b?=?"abcd";??
  3. System.out.println(a?==?b);??//?True??
  4. System.out.println(a.equals(b));?//?True??
  5. ???
  6. String?c?=?new?String("abcd");??
  7. String?d?=?new?String("abcd");??
  8. System.out.println(c?==?d);??//?False??
  9. System.out.println(c.equals(d));?//?True??
上一篇: java jvm 记录(一) 下一篇: 没有下一篇了!
发表评论
用户名: 匿名