Java开发者易犯错误Top10

标签: java 开发 错误 | 发表时间:2015-02-14 05:31 | 作者:u012275397
出处:http://blog.csdn.net
摘要:在Java中,有些事物如果不了解的话,很容易就会用错,如数组转换为数组列表、元素删除、Hashtable和HashMap、ArrayList和LinkedList、Super和Sub构造函数等,如果这些对你来说是陌生的,你可以在本文中了解它们。

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


Top1. 数组转换为数组列表

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

[java]  view plain copy
  1. List<String> list = Arrays.asList(arr);  

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

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

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

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

开发者经常这么做:

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

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

[java]  view plain copy
  1. Arrays.asList(arr).contains(targetValue);  

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

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

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

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

[java]  view plain copy
  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);  

输出是:

[java]  view plain copy
  1. [b, d]  

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

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

[java]  view plain copy
  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. }  

它会报出 ConcurrentModificationException异常。

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

[java]  view plain copy
  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. }  

.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 plain copy
  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. }  

该代码会抛出一个异常:

[java]  view plain copy
  1. Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String  
  2.     at ...  

使用原始类型集合是危险的,因为原始类型集合跳过了泛型类型检查,也不安全。Set、Set<?>和Set<Object>之间有很大的不同。详细可查看

Raw type vs. Unbounded wildcardType Erasure

Top6. 访问级别

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

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

Top7.ArrayList VS LinkedList

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

Top8. Mutable VS Immutable

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

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

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

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

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

Top9. Super和Sub构造函数


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

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

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

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

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

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

Top10. ""或构造函数?

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

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

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

[java]  view plain copy
  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字符串》。

推荐阅读:

Constructors of Sub and Super Classes in Java?

How Developers Sort in Java?

How to Convert Array to ArrayList in Java?

Java Type Erasure Mechanism

原文来自: programcreek

作者:u012275397 发表于2015/2/13 21:31:06 原文链接
阅读:64 评论:0 查看评论

相关 [java 开发 错误] 推荐:

Java开发者易犯错误Top10

- - CSDN博客编程语言推荐文章
摘要:在Java中,有些事物如果不了解的话,很容易就会用错,如数组转换为数组列表、元素删除、Hashtable和HashMap、ArrayList和LinkedList、Super和Sub构造函数等,如果这些对你来说是陌生的,你可以在本文中了解它们. 本文总结了Java开发者经常会犯的前十种错误列表.

Java开发者写SQL时常犯的10个错误

- - ImportNew
我十分惊讶的发现,我最近的一篇文章——《 Java开发者写SQL时常犯的10个错误》——最近在 我的博客和 我的合作伙伴DZone上非常的受欢迎. (这篇博客)的流行程度说明了几件事:. SQL在专业的Java开发中多么重要. 基本的SQL知识被忘掉(的情况)普遍存在. 通过 embracing SQL,你就能了解像.

locale错误导致Java中文乱码错误的总结

- - Java - 编程语言 - ITeye博客
线上执行MapReduce任务计算时,经过排查发现了某些服务器计算的数据出现中文乱码问题,但是服务器的配置是完全一致的. 由于我们使用的key可能包含中文,中文乱码问题体现在每次合并map记录的时候计算数据的随机性,每次执行的结果都不一样(由于Map任务执分配的随机性). (注:此文章大部分都参考了同事查找到的问题解决方法.

Java 程序员容易犯的10个SQL错误

- - ITeye博客
Java程序员编程时需要混合面向对象思维和一般命令式编程的方法,能否完美的将两者结合起来完全得依靠编程人员的水准:. 技能(任何人都能容易学会命令式编程). 模式(有些人用“模式-模式”,举个例子,模式可以应用到任何地方,而且都可以归为某一类模式). 心境(首先,要写个好的面向对象程序是比命令式程序难的多,你得花费一些功夫).

Java 8中10个不易察觉的错误

- - Java译站
我敢打赌,每人至少都会犯一次这样的错误. 就像现有的这些“流”(比如说InputStream),你也只能对它们消费一次. 你会碰到一个这样的错误:. 因此使用流的时候应当格外注意. 不小心创建了一个”无限"流. 你可能一不留神就创建了一个无限流. 流的问题就在于它有可能是无限的,如果你的确是这样设计的话.

[译] Java 中最常见的 5 个错误

- - SegmentFault 最新的文章
在编程时,开发者经常会遭遇各式各样莫名错误. 近日,Sushil Das 在 Geek On Java上列举了 Java 开发中常见的 5 个错误,与君共「免」. 原文链接: Top 5 Common Mistake in Java. 避免过度使用 null 值是一个最佳实践. 例如,更好的做法是让方法返回空的 array 或者 collection 而不是 null 值,因为这样可以防止程序抛出 NullPointerException.

Java程序员们最常犯的3个集合错误

- - JavaRanger - 专注JAVA高性能程序开发、JVM、Mysql优化、算法
将数组转化为一个列表时,程序员们经常这样做:. Arrays.asList() 会返回一个ArrayList对象,ArrayList类是Arrays的一个私有静态类,而不是java.util.ArrayList 类,java.util.Arrays.ArrayList类有set()、get()、contains()方法,但是没有增加元素的方法,所以它的大 小是固定的,想要创建一个真正的ArrayList类,你应该这样做:.

java代码开发规范

- - BlogJava_首页
格式规范:                                                                      .       1、TAB空格的数量. 编辑器上的TAB空格数量统一取值为4.       2、换行, 每行120字符.       3、if语句的嵌套层数3层以内   .

Apache Thrift - java开发详解

- - 编程语言 - ITeye博客
2、编写IDL文件 Hello.thrift. 4、编写实现类、实现Hello.Iface:. 5、编写服务端,发布(阻塞式IO + 多线程处理)服务.      * 阻塞式、多线程处理 .             //设置传输通道,普通通道  .             //使用高密度二进制协议  .

Android NDK开发Crash错误定位

- - 极客521 | 极客521
在Android开发中,程序Crash分三种情况:未捕获的异常、ANR(Application Not Responding)和闪退(NDK引发错误). 其中 未捕获的异常根据logcat打印的堆栈信息很容易定位错误. ANR错误也好查,Android规定,应用与用户进行交互时,如果5秒内没有响应用户的操作,则会引发ANR错误,并弹出一个系统提示框,让用户选择继续等待或立即关闭程序.