Java开发人员最容易出现的几类错误
一、把数组转成ArrayList
List<String> list = Arrays.asList(arr);
//以下带伪代码来自Arrays类中
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable
{
private static final long serialVersionUID = -2764017481108945198L;
private final E[] a;
ArrayList(E[] array) {
a = Objects.requireNonNull(array);
}
}
使用Arrays.asList()方法可以得到一个ArrayList,但是得到这个ArrayList其实是定义在Arrays类中的一个私有的静态内部类。这个类虽然和java.util.ArrayList同名,但是并不是同一个类。java.util.Arrays.ArrayList类中实现了set(), get(), contains()等方法,但是并没有定义向其中增加元素的方法。也就是说通过Arrays.asList()得到的ArrayList的大小是固定的。
二、在循环中删除列表中的元素
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]
以上代码的目的是想遍历删除list中所有元素,但是结果却没有成功。原因是忽略了一个关键的问题:当一个元素被删除时,列表的大小缩小并且下标也会随之变化,所以当你想要在一个循环中用下标删除多个元素的时候,它并不会正常的生效。
也有些人知道以上代码的问题就由于数组下标变换引起的。所以,他们想到使用增强for循环的形式:
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a","b","c","d"));
for(String s:list){
if(s.equals("a")){
list.remove(s);
}
}
但是,很不幸的是,以上代码会抛出ConcurrentModificationException,有趣的是,如果在remove操作后增加一个break,代码就不会报错:
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a","b","c","d"));
for(String s:list){
if(s.equals("a")){
list.remove(s);
break;
}
}
迭代器被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以按照 fail-fast 原则 迭代器会马上抛出java.util.ConcurrentModificationException 异常。
所以,正确的在遍历过程中删除元素的方法应该是使用Iterator:
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()方法之前调用。如果在循环过程中先调用remove(),再调用next(),就会导致异常ConcurrentModificationException。原因如上。
三、迷之求和
public void test_add(){
int num = 0;
for (int i = 0; i < 100; i++) {
num = num++;
}
System.out.println(num);
}
最终 num 结果为 0,num++ 根本没起啥作用。因为后++,是先用结果,在++操作,不会给赋值。正确写法是:num = ++ num;
四、无用日志
public boolean ruleEngine(MatterReq req) {
try {
// 业务流程
} catch (Exception e) {
logger.error(e); // 只打异常,不打入参信息
}
}
五、耗时遍历
public void test_LinkedList() {
// 初始化100万数据
List<Integer> list = new LinkedList<Integer>(1000000);
// 遍历求和
int sum = 0;
for (int i = 0; i < list.size(); i++) {
sum += list.get(i);
}
}
乍一看可能觉得没什么问题,但是这个遍历求和会非常慢。主要因为链表的数据结构,每一次list.get(i)都是从链表的头开始查找,与ArrayList不同,LinkedList它时间复杂度是O(n)。那如果说你不知道对方传过来的是LinkedList还是ArrayList呢,其实可以通过list instanceof RandomAccess 进行判断。ArrayList 有随机访问的实现,LinkedList 是没有。同时也可以使用增强的for循环或者Iterator进行遍历。
Java开发人员最容易出现的几类错误的更多相关文章
- Java开发人员最常犯的10个错误
这个列表总结了10个Java开发人员最常犯的错误. Array转ArrayList 当需要把Array转成ArrayList的时候,开发人员经常这样做: List<String> list ...
- 面向 Java 开发人员的 Ajax: 构建动态的 Java 应用程序
面向 Java 开发人员的 Ajax: 构建动态的 Java 应用程序 Ajax 为更好的 Web 应用程序铺平了道路 在 Web 应用程序开发中,页面重载循环是最大的一个使用障碍,对于 Java™ ...
- Java开发人员必须掌握的Linux命令-学以致用(5)
================================================= 人工智能教程.零基础!通俗易懂!风趣幽默!大家可以看看是否对自己有帮助! 点击查看高清无码教程 == ...
- Java开发人员必须掌握的两个Linux魔法工具(四)
子曰:"工欲善其事,必先利其器." 做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 学习应该是快乐的,在这个乐园中我努力让自己能用简洁易懂(搞笑有趣) ...
- Java开发人员必须掌握的Linux命令(三)
做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 学习应该是快乐的,在这个乐园中我努力让自己能用简洁易懂(搞笑有趣)的表达来讲解知识或者技术,让学习之旅充满乐趣,这就是写博 ...
- Java开发人员必须掌握的Linux命令(二)
子曰:"工欲善其事,必先利其器." 学习应该是快乐的,在这个乐园中我努力让自己能用简洁易懂(搞笑有趣)的表达来讲解让知识或者技术,让学习之旅充满乐趣,这就是写博文的初心. 本篇的旅 ...
- Spring Boot 针对 Java 开发人员的安装指南
Spring Boot 可以使用经典的开发工具或者使用安装的命令行工具.不管使用何种方式,你都需要确定你的 Java 版本为 Java SDK v1.8 或者更高的版本.在你开始安装之前,你需要确定你 ...
- JAVA开发人员画图表总结(ECHARTS)
随着大数据的到来,越来越多的数据需求需要开发,而这些需求不可避免需要使用JS画出图表,而大多后端JAVA开发人员对JS不太熟悉,导致身心倍受折磨,今天记录以下最近我使用echarts的步骤,供参考: ...
- 【运维】Java开发人员掌握的Linux命令
作为Java开发人员,要掌握常用的Linux命令. 为什么要写此文,笔者的Linux很厉害?NoNoNo,正因为笔者不熟悉Linux才写此文,以作整理. 最主要的命令 查询命令的简要用法,help 当 ...
随机推荐
- P1426 小鱼会有危险吗(JAVA语言)
题目描述 有一次,小鱼要从A处沿直线往右边游,小鱼第一秒可以游7米,从第二秒开始每秒游的距离只有前一秒的98%.有个极其邪恶的猎人在距离A处右边s米的地方,安装了一个隐蔽的探测器,探测器左右x米之内是 ...
- vscode配置c\c++环境
目录 一.安装vscode 二.安装插件以及配置c\c++编译环境 1. 安装以下两个插件 2. 配置编译环境 一.安装mingw64(推荐) 方法一 方法二 二.如果你安装过visual studi ...
- 灵雀云Istio技术实践专题整理
Istio技术实践专题(1) Service Mesh Istio 基本概念和架构基础 Istio被称作Kubernetes的最佳云原生拍档.从今天起,我们推出"Istio技术实践" ...
- 附031.Kubernetes_v1.20.4高可用部署架构二
kubeadm介绍 kubeadm概述 参考附003.Kubeadm部署Kubernetes. kubeadm功能 参考附003.Kubeadm部署Kubernetes. 本方案描述 本方案采用kub ...
- JavaScript深入理解-正则表达式
正则表达式 正则表达式是用于匹配字符串中字符组合的模式.在JavaScript中,正则表达式也是对象.这些模式被用于RegExp的 exec和 text方法,以及String中的 match.matc ...
- Python 多线程(一)
Python多线程(一) 目录 Python多线程(一) 线程 Python线程模型 Python虚拟机按照下面所述方式来切换线程 Threading模块 未引进线程 结果 引入线程 方式一:创建Th ...
- Go-16-map
map的value可以是任何数据类型.map和切片一样,也是一种引用类型. map声明: (1)使用var关键字定义map var 变量名 map[key类型] value 类型 (2)使用make( ...
- 女娲造人引发思考之Java设计模式:工厂模式
目录 工厂模式的几种形态 简单工厂模式 示例 结构 优缺点 女娲抟土造人 工厂方法模式 结构 女娲举绳造人 抽象工厂模式 结构 女娲造万物 工厂模式的几种形态 工厂模式专门负责将大量有共同接口的类实例 ...
- 01- linux入门
LINUX是什么? -linux是计算机操作操作系统 -常见的操作系统有:Windows,Android,苹果iOS,Mac系统,Unix(和linux类似) 操作系统是干什么的? 管理硬件和程序的一 ...
- SQL 查询的执行顺序
SELECT语句的完整语法如下 SELECT DISTINCT <select_list> FROM <left_table> <join_type> JOIN & ...