文档章节

Java开发者易犯错误Top10

火力全開
 火力全開
发布于 2016/10/05 18:49
字数 1799
阅读 8
收藏 0
点赞 0
评论 0

摘要:在Java中,有些事物如果不了解的话,很容易就会用错,如数组转换为数组列表、元素删除、Hashtable和HashMap、ArrayList和LinkedList、Super和Sub构造函数等,如果这些对你来说是陌生的,你可以在本文中了解它们。

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

 

Top1. 数组转换为数组列表

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

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

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

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

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

 

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

开发者经常这么做:

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

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

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

for(String s: arr){  
    if(s.equals(targetValue))  
        return true;  
}  
return false;

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

 

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

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

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]

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

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

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()的源代码

 

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作为参数: 

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之间有很大的不同。详细可查看

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)

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()构造函数,如下所示:

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

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

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

 

Top10. “”或构造函数?

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

//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字符串》

 

推荐阅读:

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

本文转载自:http://www.programcreek.com/2014/05/top-10-mistakes-java-developers-make/

火力全開
粉丝 19
博文 199
码字总数 17966
作品 0
卢湾
高级程序员

暂无相关文章

Cube、Cuboid 和 Cube Segment

1.Cube (或Data Cube),即数据立方体,是一种常用于数据分析与索引的技术;它可以对原始数据建立多维度索引。通过 Cube 对数据进行分析,可以大大加快数据的查询效率 2.Cuboid 在 Kylin 中特...

无精疯 ⋅ 25分钟前 ⋅ 0

github太慢

1:用浏览器访问 IPAddress.com or http://tool.chinaz.com 使用 IP Lookup 工具获得github.com和github.global.ssl.fastly.net域名的ip地址 2:/etc/hosts文件中添加如下格式(IP最好自己查一...

whoisliang ⋅ 26分钟前 ⋅ 0

非阻塞同步之 CAS

为解决线程安全问题,互斥同步相当于以时间换空间。多线程情况下,只有一个线程可以访问同步代码。这种同步也叫阻塞同步(Blocking Synchronization). 这种同步属于一种悲观并发策略。认为只...

长安一梦 ⋅ 37分钟前 ⋅ 0

云计算的选择悖论如何对待?

人们都希望在工作和生活中有所选择。但心理学家的调查研究表明,在多种选项中进行选择并不一定会使人们更快乐,甚至不会产生更好的决策。心理学家Barry Schwartz称之为“选择悖论”。云计算为...

linux-tao ⋅ 39分钟前 ⋅ 0

我的第一篇个人博客

虽然这是个技术博客,但是,我总是想写一些自己的东西,所有就大胆的在这里写下了第一篇非技术博客。技术博客也很久没有更新,个人原因。 以后自己打算在这里写一些非技术博客,可能个人观点...

Mrs_CoCo ⋅ 40分钟前 ⋅ 0

Redis 注册为 Windows 服务

Redis 注册为 Windows 服务 redis 注册为 windows 服务相关命令 注册服务 redis-server.exe –service-install redis.windows.conf 删除服务 redis-server –service-uninstall 启动服务 re......

Os_yxguang ⋅ 40分钟前 ⋅ 0

世界那么大,语言那么多,为什么选择Micropython,它的优势在哪?

最近国内MicroPython风靡程序界,是什么原因导致它这么火呢?是因为他功能强大,遵循Mit协议开源么? 错!因为使用它真的是太舒服了!!! Micropython的由来,这得益于Damien George这位伟大...

bodasisiter ⋅ 44分钟前 ⋅ 0

docker 清理总结

杀死所有正在运行的容器 docker kill $(docker ps -a -q) 删除所有已经停止的容器(docker rm没有加-f参数,运行中的容器不会删掉) docker rm $(docker ps -a -q) 删除所有未打 dangling 标...

vvx1024 ⋅ 54分钟前 ⋅ 0

关于学习

以前学车的时候,教练说了这样的一句话:如果一个人坐在车上一直学,一直学,反而不如大家轮流着学。因为一个人一直学,就没有给自己留空间来反思和改进。而轮流着学的时候大家下来之后思考上...

mskk ⋅ 58分钟前 ⋅ 0

压缩工具之gzip-bzip2-xz

win下常见压缩工具:rar zip 7z linux下常见压缩工具:zip gz bz2 xz tar.gz tar.bz2 tar.xz gzip 不支持目录压缩 gzip 1.txt #压缩。执行后1.txt消失,生成1.txt.gz压缩文件 gzip -d 1.txt....

ZHENG-JY ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部