Top 10 Mistakes Java Developers Make(转)

 

 

文章列出了Java开发者最常犯的是个错误。

 

1.将数组转换为ArrayList

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

?


1

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

Arrays.asList()会返回一个ArrayList,但这个ArrayListArrays的私有静态类,不是java.util.ArrayListjava.util.Arrays.ArrayListset(), get(), contains()方法,但没有任何能增加元素的方法,所以它的大小是确定的。 为了创建一个真正的ArrayList,应该这样做:

?


1

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

ArrayList的构造函数能够接收一个Collection类型,而它也是java.util.Arrays.ArrayList的一个祖先类。

 

2.检查一个数组是否包含某个值

开发者经常这样做:

?


1

2

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

return set.contains(targetValue);

这个的代码可以工作,但没必要首先把数组转换为集合,把数组转换为集合需要额外的时间。可以这样做:

?


1

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

或者

?


1

2

3

4

5

for(String s: arr){

    if(s.equals(targetValue))

        return true;

}

return false;

第一个比第二个的可读性更好。

 

3.在循环里边删除列表的元素

思考下面的代码,该代码在循环里边删除元素

?


1

2

3

4

5

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

输出如下:

?


1

[b, d]

上面的方法有一个严重的问题。当一个元素被移除后,列表的大小减小了,索引也就变了。所以希望利用索引在一个循环里边删除多个元素是做不到的。 你可能知道利用迭代器在一个循环里边删除元素是正确的方法,并且知道Java的foreach循环很像一个迭代器,但事实上不是。思考下面的代码:

?


1

2

3

4

5

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。 下面的代码是可以的:

?


1

2

3

4

5

6

7

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循环里边,编译器会先调用.remove(),再调用.next(),从而导致异常ConcurrentModificationException。你可能想知道ArrayList.iterator()的源代码。

 

4.HashTable vs HashMap

根据算法的约定,HashTable是这个数据结构的名字,但在Java里边,HashMap是这个数据结构的名字。Hashtable和 HashMap的一个关键性的不同是,HashTable是同步的,而HashMap不是。所以通常不需要HashTable,HashMap用的更多。 HashMap vs. TreeMap vs. Hashtable vs. LinkedHashMap Top 9 questions about Java Maps

 

5.使用原始集合类型

在Java里边,原始类型和无界通配符类型很容易混合在一起。以Set为例,Set是一个原始类型,而Set< ? >是一个无界通配符类型。 考虑下面使用原始类型List作为参数的代码:

?


1

2

3

4

5

6

7

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

}

上面的代码将会抛出异常:

?


1

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

使用原始集合类型是很危险的,因为原始集合类型跳过了泛型类型检查,是不安全的。SetSet< ? >Set< Object >之间有很大差别。请参考Raw type vs. Unbounded wildcardType Erasure

 

6.访问级别

开发者经常使用Public作为类的修饰符,这样可以很简单的通过直接引用得到值,但这是一个非常糟糕的设计。根据经验,分配给成员的访问级别应尽可能的低。 public, default, protected, and private

 

7.ArrayList vs LinkedList

当开发者不知道ArrayList和LinkedList的区别的时候,通常会使用ArrayList,因为它看起来更熟悉。然而,两者之间有很大 的性能差异。简单地说,当有大量的插入/删除操作并且没有太多的随机访问操作的时候,应该使用LinkedList。如果对此不太了解,可参考ArrayList vs. LinkedList

 

8.可变与不可变

不可变对象有许多的优点,比如简单,安全等等。但是对于每一个不同的值都要有一个独立的对象,过多的对象导致垃圾回收的高消耗。当选择可变与不可变时应该有一个权衡。 通常情况下,可变对象可以用来避免产生过多的中间对象。一个经典的实例就是连接大量的字符串,如果使用不可变的字符串,将会产生大量的需要进行垃圾回收的对象。这会浪费CPU大量的时间,使用可变对象才是正确的方案(比如StringBuilder)。

?


1

2

3

4

String result="";

for(String s: arr){

    result = result + s;

}

在其它的一些情况下也是需要使用可变对象的,比如将可变对象作为参数传入方法可以使你不需要使用很多语句便可以得到多个结果。另外一个例子是排序和 过滤:当然,你可以写一个方法来接收原始的集合,并且返回一个排好序的集合,但是那样对于大的集合就太浪费了。(来自StackOverFlow的dasblinkenlight的答案)。 Why String is Immutable?

 

9.父类和子类的构造函数

因为没有定义父类的默认构造函数,在编译的时候会产生错误。在Java里边,如果一个类没有定义构造函数,编译器将会插入一个无参数的默认构造函数。如果在父类里边定义了一个构造函数,在此例中即Super(String s),编译器将不会插入默认的无参数构造函数。这就是上面示例中父类的情形。 子类的构造函数,不管是没有参数还有有参数,都会调用父类的无参构造函数。因为编译器试图把super()插入到子类的两个构造函数中。但是父类默认的构造函数未定义,编译器就会报出这个错误信息。 要修复这个问题,可以简单的通过1)在父类中添加一个Super()构造方法,就像这样:

?


1

2

3

public Super(){

    System.out.println("Super");

}

或者2)移除自定义的父类构造函数,或者3)在子类的构造函数中调用父类的super(value)。 Constructor of Super and Sub

 

10.”“还是构造函数?

有两种方式构造字符串:

?


1

2

3

4

//1. 利用双引号

String x = "abc";

//2. 利用构造函数

String y = new String("abc");

 

区别在哪? 下面的例子可以给出一个快速的答案:

?


1

2

3

4

5

6

7

8

9

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

 

关于它们内存分配的更多细节,请参考Create Java String Using ”” or Constructor?

 

将来的工作

这个列表是我根据大量的GitHub上的开源项目、Stack Overflow上的问题和一些常见的Google搜索得到的。没有明显示的评估证明它们是准确的前10,但它们绝对是很常见的问题。如果您不同意任一部 分,请留下您的评论。如果您能提出其它一些常见的错误,我将会非常感激。

翻译自:Top 10 Mistakes Java Developers Make

http://www.cnblogs.com/liushaobo/p/4375493.html

 

时间: 2024-10-27 07:58:22

Top 10 Mistakes Java Developers Make(转)的相关文章

2016 年排名 Top 100 的 Java 类库

我们分析了GitHub中47,251个依赖,从中找出了排名前一百的Java类库,让我们看看谁在前面,谁在后面. 我们在漫长的周末的消遣方式就是浏览GitHub并且搜索流行的Java类库.我们决定把其中的乐趣与结果分享给你. 我们分析了GitHub中排名前3,862个项目中的47,251个导入语句,其中有12,059个Java类库被依赖.我们从这个列表中提取出前一百并把结果分享给你. 最受欢迎的前20个Java类库 和上次分析结果一致,junit依旧是GitHub中最受欢迎的类库.Java中的日志

Cassandra杀回数据库排行Top 10,及需求Java 7的2.0版本

在MySQL被Oracle收购后,业内对这个开源数据库的议论就从未停止,对于PostgreSQL将取而代之成为最人气开源数据库的声音也从未停歇.然而从DB-Engines排行榜来看,PostgreSQL与MySQL之间的差距远不只是"几层楼"那么高(PostgreSQ得分不到MySQL的零头).着眼整个排行榜上的193个数据库,我们会发现NoSQL数据库已占大半江山,榜上有名的传统关系型数据库管理系统仅余75个. 上图为9月份最新的排行,在Oracle稳坐头把交椅的同时,MySQL与M

DEPLOYING NATIVE UWP (UNIVERSAL WINDOWS PLATFORM) APPS FOR JAVA DEVELOPERS &amp; PUBLISHING THEM TO THE MICROSOFT STORE

原文: DEPLOYING NATIVE UWP (UNIVERSAL WINDOWS PLATFORM) APPS FOR JAVA DEVELOPERS & PUBLISHING THEM TO THE MICROSOFT STORE UWP Apps may distributed in 2 different ways: In the Windows App Store. (This should be used for deployment of any production app)

Jenkins管道最佳实践Top 10

本文讲的是Jenkins管道最佳实践Top 10[编者的话]Andy Pemberton领导CloudBees的解决方案架构团队.CloudBees是一家依赖Jenkins实现云化持续集成平台的创业公司,目前已经得到C轮融资.Andy拥有超过十年的软件交付经验,同时他也是经常发表演讲和撰写博客.本文是Andy做为Jenkins专家给出的10条Jenkins管道化使用的最佳实践. Jenkins的管道化插件对于其用户来说是个变局者.依赖于域领域语言(DSL)Groovy,管道化插件实现了脚本化.这

开发者必看:最易犯的Top 10加密错误,你中枪了吗?

本文讲的是开发者必看:最易犯的Top 10加密错误,你中枪了吗?, 在对小型初创企业和大型银行和电信公司进行了数百次安全代码审查,并阅读了数百个在安全社区发布的堆栈溢出的帖子之后,我们列出了开发人员最容易犯的十大加密错误. 不幸的现实是,错误的加密方式随处可见.正确加密的次数远远低于我们发现的错误加密的次数,许多问题是由于复杂的加密API在默认的情况下是不安全的.另一个原因是,我们需要训练有素的专家进行手动代码分析才能发现问题.根据我的经验,流行的静态分析工具在寻找加密问题方面并不出色,此外,黑

数据库10大常见安全问题及Top 10 数据库安全工具盘点

本文讲的是数据库10大常见安全问题及Top 10 数据库安全工具盘点, 数据库已经成为黑客的主要攻击目标,因为它们存储着大量有价值和敏感的信息. 这些信息包括金融.知识产权以及企业数据等各方面的内容.网络罪犯开始从入侵在线业务服务器和破坏数据库中大量获利,因此,确保数据库的安全成为越来越重要的命题. 网络的高速发展为企业和个人都带来了无限机遇,随着在线业务变得越来越流行,接触全球客户也成为点指间能够实现的事情.想要建立一个在线业务,最重要的就是建立一个全面的数据库,与此同时,保护你共享在网络中的

工具推荐 | 分析大数据最需要的Top 10数据挖掘工具

本文讲的是工具推荐 | 分析大数据最需要的Top 10数据挖掘工具,首先,我们要了解什么是数据挖掘?官方提供的定义如下:数据挖掘又称为资料探勘.数据采矿.它是数据库知识发现(Knowledge-Discovery in Databases,简称:KDD)中的一个步骤,一般是指从大量的数据中通过算法搜索隐藏于其中信息的过程.数据挖掘通常与计算机科学有关,并通过统计.在线分析处理.情报检索.机器学习.专家系统(依靠过去的经验法则)和模式识别等诸多方法来实现上述目标. 随着数据量的爆炸式增长,我们需要

Transact-SQL排名大幅攀升12个名次进入Top 10

2003-2013年TIOBE编程语言排行榜2014年1月TIOBE编程语言排行榜Comments Transact-SQL在2013年最后一个月击败了其他竞争力对手,成为TIOBE 2013年度编程语言.2011年和2012年的年度编程语言是Objective-C.Transact-SQL获得年度编程语言多少有点意外,因为它的主要应用领域–微软的数据库引擎SQL Server已经不是那么流行了,所以一般说法是2013年太过平淡了.过去几年,TIOBE年度编程语言的得主在一年内都取得了很大进步.

聊聊OS X鲜为人知的细节设计 TOP 10

  编者按:说到OS X,作者的描述是:在其精致却不张扬的 UI 下所蕴藏的是无数对于细节的追求.这些细节下的设计总会在不经意间让你体会到水果对于完美的定义和对用户体验的追求.究竟有哪些细节令人惊叹而又鲜为人知,在这里作者选出了自认为「少数派」的十项细节设计. 在 OS X Yosemite 正式发布前,让我们一起来聊一聊有关 OS X Mountain Lion 的十大细节设计,不过在开篇前先说个题外话. 1997 年,德国大众启动了一项名为 D1 的项目,目的是打造一台可以与奔驰 S-Cla