本文总结了Java开发者经常会犯的前十种错误列表。
Top1. 数组转换为数组列表
将数组转换为数组列表,开发者经常会这样做:
- 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()方法,但是没有任何加元素的方法,因此它的大小是固定的。你应该这么做来创建一个真正的数组:
- ArrayList<String> arrayList = new ArrayList<String>(Arrays.asList(arr));
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<String> set = new HashSet<String>(Arrays.asList(arr)); return set.contains(targetValue);
代码可以工作,但是没有必要首先转换列表到Set,转换一个列表到一个Set需要额外的时间。因此你可以把它简化为:
- Arrays.asList(arr).contains(targetValue);
Arrays.asList(arr).contains(targetValue);
或
- for(String s: arr){
- if(s.equals(targetValue))
- return true;
- }
- return false;
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);
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]
[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);
- }
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();
- }
- }
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
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);
- }
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 ...
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和Type 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;
- }
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");
- }
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");
//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开发者和架构师容易犯的十个错误,了解并避免这些错误,将有助于提升个人和团队的开发效率,打造出更高质量的软件产品。
文章列出了Java开发者常犯的是个错误。 1.将数组转换为ArrayList 为了将数组转换为ArrayList,开发者经常会这样做: List<String> list = Arrays.asList(arr); Arrays.asList()会返回一个ArrayList,但...
这个资源是java 开发者容易犯的10个错误,是每个java初学者的必看内容
此外,作为Java开发者和架构师,应持续学习最新的技术和最佳实践,如Java新特性、设计模式、微服务架构、容器化技术(Docker)、持续集成/持续部署(CI/CD)等,以保持与时俱进。同时,良好的团队沟通和项目管理能力...
### Java编码常犯错误 #### 一、字符串拼装SQL **问题描述**:在Java开发过程中,直接使用字符串拼接的方式构造SQL语句是一种常见的做法。然而这种方式存在明显的安全隐患和性能问题。 - **安全漏洞**:直接拼接...
Java编程语言虽然强大且广泛应用,但即使是经验丰富的程序员也可能会犯一些常见的错误。本文将针对Java程序员容易犯的10个错误进行详细讲解,帮助大家避免这些陷阱。 1. **Array 转 ArrayList**: 当使用`Arrays....
在Java编程过程中,开发者经常会遇到一些常见的错误,这些错误可能会导致程序运行不正常或效率低下。以下是一些Java中常见的错误及其详细解释: 1. **类型转换错误**:Java是强类型语言,当不同类型的数据之间进行...
我十分惊讶的发现,我近的一篇文章——《Java开发者写SQL时常犯的10个错误》——近在我的博客和我的合作伙伴DZone上非常的受欢迎。(这篇博客)的流行程度说明了几件事: SQL在专业的Java开发中多么重要。 ...
以下是根据标题和描述中提到的几点,对Java程序员在SQL编程中常犯错误的详细解析: 1. 忽视NULL的特殊性 NULL在SQL中的含义是未知,与Java中的null不同。Java程序员经常混淆这两个概念,尤其是在使用NULL作为比较...
### Java程序员们最常犯的10个错误 #### 错误一:将数组错误地转化为列表 在Java中,很多程序员在尝试将数组转换为列表时,常常使用`Arrays.asList(arr)`这样的方法。虽然这种方法可以成功转换,但需要注意的是,`...
在Java编程中,程序员们常常会遇到一些常见的错误,这些错误可能在初学者和经验丰富的开发者之间都有所体现。本文将探讨Java程序员们最常犯的10个错误,并给出相应的纠正方法,这对于准备Java面试或者日常开发工作都...
本篇将详细探讨"Java习题(一些不注意就犯的错误)"中涉及的知识点,包括字符谜题、循环谜题、异常谜题、类谜题以及库谜题,旨在帮助你更好地理解和避免这些常见问题。 1. 字符谜题: Java中的字符处理有时会让人...
### Java中Long与Integer比较易犯错误总结 #### 一、引言 在Java编程过程中,经常需要对数值进行比较操作。对于基本数据类型如`int`和`long`,可以直接使用`==`进行比较。然而,当涉及到它们的包装类`Integer`和`...
### Java程序中最易犯的21种错误解析 在Java编程实践中,开发人员经常会遇到一些常见的陷阱和误区,这些问题不仅会影响代码的质量,还可能导致程序运行时出现不可预知的错误。下面将详细介绍这些常见的错误,并提供...
### Java常见异常和错误总结 #### 1. java.lang.NullPointerException (空指针异常) - **定义**: 当尝试调用未经初始化的对象或是不存在的对象时触发的异常。 - **常见场景**: - 图片处理中,若图片未初始化或...
《Java Puzzler》是Java开发者的一本独特指南,它以一种有趣且富有挑战性的方式揭示了语言中的陷阱和易犯错误。这本书的核心理念是通过一系列精心设计的谜题,帮助读者深入理解Java语言的微妙之处,从而提高编程技能...
了解Unicode与UTF-8的关系、字符集与编码的识别和转换也是Java开发者需要掌握的知识。 最后,Java虚拟机在运行期提供了各种参数来优化性能,了解这些参数以及如何根据程序的运行情况调整它们是进行性能调优的基本...
Java程序员在编写SQL程序时,由于SQL语言的特性和与Java的差异,常常会遇到一些常见错误。以下是对这些错误的详细分析和解决方案: 1. 忘记处理NULL值 NULL在SQL中的处理方式与Java中不同,容易引发混淆。Java中的...
然而,即使是经验丰富的开发者,也可能会在一些基本的Java知识点上犯错误。"JAVA基础易错总结(50%你不知道)"这份资料,由大鹏历时5个月精心原创,旨在揭示那些易被忽视或误解的Java基础知识,帮助开发者提高代码...
在Java开发过程中,开发者经常会遇到一些常见的错误,这些错误如果不及时纠正,可能会导致程序效率低下、运行不稳定甚至出现不可预见的bug。以下是对标题和描述中提到的Java开发人员最常犯的10个错误的详细分析: 1...