Java开发人员犯下的十大错误

1。将Array转换为ArrayList

要将数组转换为  ArrayList,开发人员通常会这样做:


 

Arrays.asList()将返回 ArrayList一个私有静态类 Arrays,它不是 java.util.ArrayList类。该 java.util.Arrays.ArrayListset()get()contains()方法,但没有添加元素的任何方法,所以它的大小是固定的。要创建一个真实的 <span style="color: #ff6600;">ArrayList</span>,你应该做:


构造函数 ArrayList可以接受Collection类型,它也是一个超类型 java.util.Arrays.ArrayList

2。检查数组是否包含值

开发人员经常这样做:

代码是有效的,但无需先将列表转换为Set集合。将列表转换为Set集合需要额外的时间。其实它可以更简单:


要么

第一个比第二个可读性更高。

3。从循环内的列表中删除元素

请考虑以下代码,该代码在迭代期间删除元素:

结果输出是:

这种方法存在严重问题。删除元素后,列表的大小会缩小,索引也会更改。因此,如果要使用索引删除循环内的多个元素,则无法正常工作。

您可能知道使用迭代器是删除循环内元素的正确方法,并且您知道Java中的foreach循环就像迭代器一样,但实际上并非如此。请考虑以下代码:

它会抛出ConcurrentModificationException 异常。

相反,以下代码做到完美:

.next()必须先叫 .remove()。在foreach循环中,编译器会 .next()在删除元素的操作后进行调用,从而导致 ConcurrentModificationException。您可能需要查看ArrayList.iterator()的源代码。

4。Hashtable vs HashMap

根据算法中的约定,Hashtable是数据结构的名称。但在Java中,数据结构的名称是 HashMapHashtable和之间的关键区别 HashMap之一 Hashtable是同步。所以你经常不需要 Hashtable,而 HashMap会经常使用。

5。使用原始类型的集合

在Java中,原始类型和无界通配符类型很容易混合在一起。以Set为例, Set是原始类型, Set&lt;?&gt;而是无界通配符类型。

请考虑以下使用原始类型 List作为参数的代码:

此代码将引发异常:

使用原始类型集合是危险的,因为原始类型集合跳过泛型类型检查而不安全。之间存在巨大差异 SetSet&lt;?&gt;Set&lt;Object&gt;

6。访问权限

开发人员经常将公共场所用于课堂领域。通过直接引用很容易获得字段值,但这是一个非常糟糕的设计。经验法则是为成员提供尽可能低的访问级别。

public,default,protected和private

7。ArrayList与LinkedList

当开发人员不知道之间的区别 ArrayListLinkedList,他们经常使用 ArrayList,因为它看起来很熟悉。但是,它们之间存在巨大的性能差异。ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。 对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。  对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据

8。可变与不可变

不可变对象具有许多优点,例如简单性,安全性等。但是对于每个不同的值,它需要单独的对象,并且太多的对象可能导致垃圾收集的高成本。在可变和不可变之间进行选择时应该保持平衡。

通常,可变对象用于避免产生太多中间对象。一个典型的例子是连接大量字符串。如果使用不可变字符串,则会产生大量符合垃圾收集条件的对象。这会浪费CPU上的时间和精力,使用可变对象正确的解决方案(例如 StringBuilder)。

还有其他需要可变对象的情况。例如,将可变对象传递给方法可以让您收集多个结果,而不会跳过太多语法。另一个例子是排序和过滤:当然,你可以创建一个采用原始集合的方法,并返回一个已排序的方法,但这对于较大的集合来说会变得非常浪费时间。

9。Super和Sub的构造函数

Implicit-super-constructor-is-undefined-for-default-constructor.png

发生此编译错误,因为默认的超级构造函数未定义。在Java中,如果类没有定义构造函数,则编译器将默认为该类插入默认的无参数构造函数。如果构造函数是在Super类中定义的,在本例中是Super(String s),编译器将不会插入默认的无参数构造函数。这是上面超级类的情况。

Sub类的构造函数(带参数或无参数)将调用无参数的超级构造函数。由于编译器尝试将super()插入Sub类中的2个构造函数,但未定义Super的默认构造函数,因此编译器会报告错误消息。

要解决这个问题,只需1)将Super()构造函数添加到Super类中

,或2)删除自定义的超级构造函数,或3)添加 super(value)到子构造函数。

10。两种字符串创建方式?

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

有什么不同?

以下示例可以提供快速答案: