java contains_Java程序员人员容易犯的10大错误

本文列举了Java编程中常见的错误做法,包括数组转ArrayList、检查数组元素、删除列表元素、使用原始集合类型等问题,并提供了最佳实践。强调了访问权限控制、ArrayList与LinkedList的选择以及可变与不可变对象的权衡。同时,解释了构造函数的使用和字符串创建的差异。
摘要由CSDN通过智能技术生成

仅仅总结这些内容,大家可以在评论区补充

1、将数组转换为ArrayList

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

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

Arrays.asList()将返回ArrayList其中是私有静态类的Arrays,而不是java.util.ArrayList该类。该java.util.Arrays.ArrayList班有set()get()contains()方法,但没有添加元素的任何方法,所以它的大小是固定的。要创建一个realArrayList,您应该执行以下操作:

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

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

2、检查数组是否包含值

开发人员经常这样做:

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

该代码有效,但是无需先转换列表即可设置。将列表转换为集合需要额外的时间。它可以很简单:

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

要么

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

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

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

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

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]

该方法存在严重的问题。删除元素后,列表的大小会缩小,索引也会更改。因此,如果您想通过使用索引删除循环中的多个元素,那将无法正常工作。

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

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

4、哈希表与哈希图

按照算法中的约定,Hashtable是数据结构的名称。但是在Java中,数据结构的名称为HashMapHashtable和之间的主要区别HashMap之一Hashtable是同步。因此,通常您不需要Hashtable,而HashMap应该使用。

5、使用原始集合类型

在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 ...

使用原始类型集合很危险,因为原始类型集合会跳过泛型类型检查并且不安全。之间存在巨大差异SetSet<?>Set<Object>。查看

原始类型与无限制通配符以及类型擦除。

6、访问权限

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

7、ArrayList与LinkedList

当开发人员不知道之间的区别ArrayListLinkedList,他们经常使用ArrayList,因为它看起来很熟悉。但是,它们之间存在巨大的性能差异。简而言之,LinkedList如果有大量的添加/删除操作并且没有很多随机访问操作,则应首选此方法。如果您是新手,请查看ArrayListvs.LinkedList以获得有关其性能的更多信息。

8、可变与不可变

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

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

String result="";
for(String s: arr){
	result = result + s;
}

还有其他一些情况需要可变对象。例如,将可变对象传递给方法可让您收集多个结果,而无需跳过太多的语法箍。另一个示例是排序和过滤:当然,您可以创建一个采用原始集合并返回已排序集合的方法,但是这对于较大的集合将变得非常浪费。(摘自dasblinkenlight关于堆栈溢出的回答)

9、Super和Sub的构造函数

d9e00447d73f4de763e500a351b48e3f.png

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

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

要解决此问题,只需1)将Super()构造函数添加到Super类,例如

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

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

Super和Sub的构造函数

10、“”还是构造函数?

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

//1. use double quotes
String x = "abc";
//2. use constructor
String y = new String("abc");

有什么区别?

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

字符串 a =  “ abcd” ; 
字符串 b =  “ abcd” ; 
系统。出来。println ( a == b );   // True 
System。出来。println ( a。等于( b ));  //正确
 
字符串 c =  新 字符串(“ abcd” );
字符串 d =  新 字符串(“ abcd” );
系统。出来。println ( c == d );   //错误的
系统。出来。println ( c。等于( d ));  //正确
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值