当前位置: 首页 > news >正文

组里来了一个实习生,一行代码引发了一个惨案

大家好,我是静幽水,一名大厂全栈程序员,今天给大家分享一个案例,看似简单。却容易引发惨案。

事情是这样的,最近组里来了一个实习生,因为项目工作量大,人力比较紧张,所以就分配了一个简单的小需求给他,给一个接口增加一个出参,返回匹配到的规则编码列表,规则编码是数字类型,当没有匹配到规则时,就返回默认规则编码。他的代码是这样写的:

int[] ruleIds = new int[roleList.size()];
for (int i = 0; i++; i<roleList.size() ) {ruleIds[i] = roleList.get(i).getId;
}

ok,这里看着还没有问题,但是在最后返回结果之前,他好像突然想起了,如果没有匹配到规则的话,要返回一个默认规则Id,于是他写下来这段代码。

List<Integer> ruleIdList =  Arrays.asList(ruleIds);
if (ruleIdList.size() == 0){ruleIdList.add(defaultId)
}

后来,对于他的代码,我们都觉得比较简单,代码review的时候,都在review其他同时的,比较复杂的代码逻辑,也就忽视了他的代码,但往往你最轻视的地方,就是最容易出问题的地方。就是这个ruleIdList.add(),导致在匹配不到规则的场景下,程序抛出UnsupportedOperationException异常。而他自测和UT也没有覆盖到这种场景,导致这个定时炸弹一直存在到上线之前。还好在上线前的前一天晚上,我们发现了这个问题,才避免了惨案的发生。

后来我去询问他这样写的动机。为什么上面没有用List而是用的数组,他给的解释是因为要放int类型,List里面只能放对象,我当场吐血。难道不知道自动装箱拆箱吗,那后面为啥再转成list呢,他说,因为前端开发要的list类型。好吧,既然事已发生,也就没有过多去追问。但是产生这个异常的原因,我还是想和大家分享一下。

Arrays.asList()方法是Java中将数组转换为集合的常用方法。它接收一个数组作为参数,并返回一个固定大小的List。这个List实际上是Arrays类的私有静态内部类ArrayList的实例。它实现了List接口,但是并没有实现List接口中的一些修改集合结构的方法,如add()、remove()等。

其实这并不是一种设计上的缺陷,而是特意为之,目的就是为了提高数组到集合的转换效率,避免创建新的ArrayList对象。但是同时也带来了一些限制,即不能对返回的List进行修改操作。如果使用修改集合结构的方法,例如add()、remove(),将会抛出UnsupportedOperationException异常,就像上面的代码一样。

为了更好地理解Arrays.asList()方法的局限性,我们来看一下它的源码实现。Arrays.asList()方法是在Arrays类中定义的静态方法。

// Arrays类的源码
public static <T> List<T> asList(T... a) {return new ArrayList<>(a);
}

从源码可以看出,Arrays.asList()方法接收可变参数,而返回的是ArrayList类的实例。这个ArrayList类是Arrays类中的一个内部类,实现了List接口。

// Arrays类的内部类ArrayList的源码
private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable {private final E[] array;ArrayList(E[] array) {if (array == null) {throw new NullPointerException();}this.array = array;}public E get(int index) {return array[index];}public int size() {return array.length;}// 不支持修改集合结构的方法public E set(int index, E element) {throw new UnsupportedOperationException();}public void add(int index, E element) {throw new UnsupportedOperationException();}public E remove(int index) {throw new UnsupportedOperationException();}
}

从ArrayList类的源码可以看出,它继承了AbstractList类并实现了RandomAccess接口,因此支持快速随机访问。但是在ArrayList类中,修改集合结构的方法都被重写为抛出UnsupportedOperationException异常,从而保证了对返回的List进行修改的操作是不可行的。

除了Arrays.asList()方法,还存在其他类似的坑,它们在处理集合时也需要注意。

Collections.nCopies()

Collections.nCopies()方法用于创建一个指定元素重复多次的List。这个List同样是固定大小的,不能进行修改操作。

List<String> list = Collections.nCopies(3, "apple");
list.add("banana"); // 抛出UnsupportedOperationException异常

原理和Arrays.asList()类似,Collections.nCopies()方法返回的是一个AbstractList的实例,不支持修改集合结构的操作。

Arrays.asList()的嵌套问题

Arrays.asList()方法还存在一个嵌套的问题。如果使用Arrays.asList()方法将一个二维数组转换为List,会得到一个List的嵌套结构,此时对内层的List进行修改同样会抛出UnsupportedOperationException异常。

String[][] array2D = { { "apple", "banana" }, { "orange", "grape" } };
List<List<String>> nestedList = Arrays.asList(array2D);
nestedList.get(0).add("kiwi"); // 抛出UnsupportedOperationException异常

原因是这个嵌套的List中的元素仍然是固定大小的List。

这种设计是为了提高效率和节省内存开销。在转换数组到集合时,能直接使用Arrays.asList()方法的时候,它是非常方便的。但是当需要对集合进行修改操作时,应该创建一个新的ArrayList对象,并使用addAll()方法将数组元素添加进去,以避免UnsupportedOperationException异常的发生。

代码示例:

String[] array = { "apple", "banana", "orange" };
List<String> list = new ArrayList<>();
Collections.addAll(list, array);
list.add("grape"); // 正常添加元素到集合中

或者如下:

List<String> Ids = new ArrayList<>(Arrays.asList(array));
Ids.add(id);

Collections.unmodifiableList()方法的不可修改特性

Collections.unmodifiableList()方法返回的是一个不可修改的List。它采用了装饰器模式,对原始List进行了封装,重写了修改集合结构的方法并抛出UnsupportedOperationException异常。

List<String> originalList = new ArrayList<>();
originalList.add("apple");
List<String> unmodifiableList = Collections.unmodifiableList(originalList);
unmodifiableList.add("banana"); // 抛出UnsupportedOperationException异常

总结: 在使用Arrays.asList()方法将数组转换为集合时,注意其局限性。返回的List是一个固定大小的List,不支持修改集合结构的方法。类似的坑还有Collections.nCopies()方法和Arrays.asList()的嵌套问题,它们同样需要注意不能对返回的集合进行修改操作。

相关文章:

组里来了一个实习生,一行代码引发了一个惨案

大家好&#xff0c;我是静幽水&#xff0c;一名大厂全栈程序员&#xff0c;今天给大家分享一个案例&#xff0c;看似简单。却容易引发惨案。 事情是这样的&#xff0c;最近组里来了一个实习生&#xff0c;因为项目工作量大&#xff0c;人力比较紧张&#xff0c;所以就分配了一…...

随手笔记(四十五)——idea git冲突

图片为引用&#xff0c;在一次导入项目至gitee的过程中&#xff0c;不知道为什么报了403&#xff0c;很奇怪的一个错误&#xff0c;网上很多的答案大概分成两种。 第一种是最多的&#xff0c;直接找到windows凭据删掉 很抱歉的告诉各位&#xff0c;你们很多人到这里就已经解…...

chacha20 算法流程

chacha20算法请参看 RFC:7539。下面是我的理解&#xff0c;欢迎指正。 chacha20算法的基本思想&#xff1a;加密时&#xff0c;将明文数据与用户之间约定的某些数据进行异或操作&#xff0c;得到密文数据&#xff1b;由异或操作的特点可知&#xff0c;在解密时&#xff0c;只需…...

准备篇(三)Python 爬虫第三方库

第三方库无法将 "pip" 识别ModuleNotFoundError: No module named pip install 安装路径相关问题requests 库和 BeautifulSoup 库requests 库BeautifulSoup 库第三方库 Python 的 标准库 中提供了许多有用的模块和功能,如字符串处理、网络通信、多线程等,但它们并…...

从零开始的PICO开发教程(4)-- VR世界 射线传送、旋转和移动

从零开始的PICO开发教程&#xff08;4&#xff09;-- VR世界 射线传送、旋转和移动 文章目录 从零开始的PICO开发教程&#xff08;4&#xff09;-- VR世界 射线传送、旋转和移动一、前言1、大纲 二、VR射线移动功能实现与解析1、区域传送&#xff08;1&#xff09;新建 XR Orig…...

防止攥改之水印功能组件

防止攥改之水印功能组件 效果图逻辑代码 效果图 逻辑代码 <template><div class"containerBox" ref"parentRef" style"height: 300px;background-color: red;"><slot></slot></div> </template><script…...

iOS 17 适配 Xcode 15 问题

在适配 iOS 17 xcode 15时遇到的问题&#xff0c;记录一下。 1、 Could not build module ‘WebKit’ type argument nw_proxy_config_t (aka struct nw_proxy_config *) is neither an Objective-C object nor a block type解决方案&#xff1a; 选中不能编译的库的xcodep…...

Element Plus 快速开始

1.完整引入&#xff08;全局引入&#xff09; // main.ts import { createApp } from vue import ElementPlus from element-plus import element-plus/dist/index.css import App from ./App.vueconst app createApp(App)app.use(ElementPlus) app.mount(#app) npm install e…...

华为云云耀云服务器L实例评测|StackEdit中文版在线Markdown笔记工具

华为云云耀云服务器L实例评测&#xff5c;StackEdit中文版在线Markdown笔记工具 一、云耀云服务器L实例介绍1.1 云服务器介绍1.2 应用场景1.3 支持镜像 二、云耀云服务器L实例配置2.1 重置密码2.2 服务器连接2.3 安全组配置 三、部署 StackEdit 中文版3.1 StackEdit 介绍3.2 环…...

MyEclipse报错javax/persistence/EntityManagerFactory

MyEclipse报错&#xff1a; Build path is incomplete. Cannot find class file for javax/persistence/EntityManagerFactory 解决方案&#xff1a; 引入依赖 <dependency><groupId>javax.persistence</groupId> <artifactId>persistence-api</a…...

【MySQL进阶】SQL性能分析

一、SQL性能分析 1.SQL执行频率 MySQL 客户端连接成功后&#xff0c;通过 show [session|global] status 命令可以提供服务器状态信 息。通过如下指令&#xff0c;可以查看当前数据库的 INSERT 、 UPDATE 、 DELETE 、 SELECT 的访问频次&#xff1a; -- session 是查看当…...

在SpringBoot项目中整合SpringSession,基于Redis实现对Session的管理和事件监听

1、SpringSession简介 SpringSession是基于Spring框架的Session管理解决方案。它基于标准的Servlet容器API&#xff0c;提供了Session的分布式管理解决方案&#xff0c;支持把Session存储在多种场景下&#xff0c;比如内存、MongoDB、Redis等&#xff0c;并且能够快速集成到Spr…...

浅析vue中computed,method,watch,watchEffect的区别

方法methods只要调用每次都会执行watch(惰性)只有依赖项更新才会执行回调函数&#xff0c;且组件初次渲染不会执行watchEffect:自动追踪依赖变化&#xff0c;只要依赖更新即执行回调函数&#xff0c;且组件初次渲染即执行回调函数computed(惰性): 返回一个只读的ref,具有缓存功…...

activiti7的数据表和字段的解释

activiti7的数据表和字段的解释 activiti7版本有25张表&#xff0c;而activiti6有28张表&#xff0c;activiti5有27张表&#xff0c;绝大部分的表和字段的含义都是一样的&#xff0c;所以本次整理的activiti7数据表和字段的解释&#xff0c;也同样适用于activiti6和5。 1、总览…...

Java手写Trie树和Trie树应用拓展案例

Java手写Trie树和Trie树应用拓展案例 1. 算法思维导图 以下是使用mermaid代码表示的Trie树的实现原理&#xff1a; #mermaid-svg-5twy24X7Wqbhyulb {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-5twy24X7Wqbhyul…...

alova.js快速入门教程

官网地址&#xff1a;Alova.JS - Lightweight request strategy library | Alova.JS 目录 一、alova 是什么&#xff1f; 二、 快速入门 1、安装依赖 &#xff08;1&#xff09;使用npm方式安装 &#xff08;2&#xff09;使用yarn方式安装 2、在静态 html 中使用 一、al…...

获取IP地址-根据IP获取位置信息

获取外网IP地址&#xff0c;并得到该地址所在位置&#xff1b; 如&#xff1a;101.249.255.255 对应&#xff1a;西藏自治区-拉萨市-堆龙德庆区 string ipAddress GetIPAddress(); string location GetIPLocation(ipAddress); /// <summary>/// 获取IP地址/// </s…...

Android13适配-Google官方照片视频选择器

官方照片选择器 图 1. 照片选择器提供了一个直观的界面&#xff0c;便于与您的应用分享照片。 照片选择器的界面可供浏览和搜索&#xff0c;并按日期降序向用户显示其媒体库中的文件。如隐私保护最佳实践 Codelab 中所示&#xff0c;照片选择器为用户提供了一种安全的内置授权…...

云计算的发展趋势和挑战

本文将探讨云计算的发展趋势和挑战&#xff0c;旨在帮助读者了解云计算的最新动态和未来发展方向。 随着信息技术的发展&#xff0c;云计算作为一种新兴的计算模式&#xff0c;已经得到了广泛的应用和认可。它通过将计算资源、存储资源和应用程序等服务通过互联网提供给用户&a…...

PyG-GAT-Cora(在Cora数据集上应用GAT做节点分类)

文章目录 model.pymain.py参数设置运行图 model.py import torch.nn as nn from torch_geometric.nn import GATConv import torch.nn.functional as F class gat_cls(nn.Module):def __init__(self,in_dim,hid_dim,out_dim,dropout_size0.5):super(gat_cls,self).__init__()s…...

java专项练习(验证码)

package 专题练习;import java.util.Random;public class Developing_CAPTCHA {public static void main(String[] args) {/* 需求:定义方法生成一个5位的验证码 验证码长度为5,前四位为大或小写字母,最后一位是数字*///方法: 如果我们要在一堆没有规律的数据中随机抽取,可以先…...

MS1861 视频处理与显示控制器 HDMI转MIPI LVDS转MIPI带旋转功能 图像带缩放,旋转,锐化

1. 基本介绍 MS1861 单颗芯片集成了 HDMI 、 LVDS 和数字视频信号输入&#xff1b;输出端可以驱动 MIPI(DSI-2) 、 LVDS 、 Mini-LVDS 以及 TTL 类型 TFT-LCD 液晶显示。可支持对输入视频信号进行滤波&#xff0c;图 像增强&#xff0c;锐化&#xff0c;对比度调节&am…...

广州华锐互动:利用VR复原文化遗址,沉浸式体验历史文物古迹的魅力

在过去的几十年里&#xff0c;科技发展飞速&#xff0c;为我们打开了无数新的视角和可能性。其中&#xff0c;虚拟现实&#xff08;Virtual Reality&#xff0c;简称VR&#xff09;技术的崭新应用&#xff0c;为我们提供了一种全新的、近乎身临其境的体验历史的方式。本文将重点…...

微信小程序——事件监听

微信小程序是一种轻量级的应用程序&#xff0c;它在移动设备上提供了丰富的用户体验。在开发微信小程序时&#xff0c;事件监听是一项重要的技术&#xff0c;它允许开发者捕捉和处理用户的各种操作。本文将介绍微信小程序事件监听的概念、用法和一些实用示例。 1. 什么是事件监…...

View绘制流程的源码所得

一些问题 子线程可以更新 UI 吗 答案是可以的&#xff0c;在特定的情况下可以 可以先在主线程中调用requestLayout() 方法&#xff0c;然后紧接着在子线程中更新UI&#xff08;原理&#xff1a;不要在子线程触发 checkThread() 方法&#xff0c;而checkThread() 方法的调用时…...

企业级数据仓库-理论知识

D3 AM 大数据中间件 Hive&#xff1a;将SQL转化成分布式Map/Reduce进行运算&#xff0c;也支持转换成Spark,需要单独安装Hive集群才能访问Spark,支持60%的SQL&#xff0c;延迟比较大。SparkSQL:属于Spark生态圈&#xff0c;Hive on Sqark。HBase: NoSQL,高并发读&#xff0c;适…...

解决flutter不识别yaml里面配置的git项目

解决办法找到相应的 git路径&#xff0c;然后手动 git pull 暂时先用这个笨方法&#xff0c;后面有更好的解决办法了再说 studio 自己拉取的项目里面没有ios 和lib包...

rust结构体

一、定义结构体类型 语法 struct Name_of_structure {field1: data_type,field2: data_type,field3: data_type, }注意&#xff1a; 不同于C&#xff0c;Rust的struct语句仅用来定义类型&#xff0c;不能定义实例。 结尾不需要;。 每个字段定义之后用 , 分隔。最后一个逗号可…...

Python - 小玩意 - 键盘记录器

pip install keyboardimport keyboard import timedef get_time():date_time time.strftime("%Y-%m-%d %H:%S", time.localtime())return date_timedef abc(x):if x.event_type down:print(f"{get_time()}你按下了{x.name}")with open(./键盘记录器.txt,…...

msvcp71.dll丢失的解决方法分享,全面分析msvcp71.dll丢失原因

msvcp71.dll 丢失的问题可能困扰着许多使用 Windows 操作系统的用户。msvcp71.dll 是微软 C运行时库中的一个动态链接库文件&#xff0c;负责提供一些基本的函数和类&#xff0c;例如字符串处理、数学运算、文件操作等。如果这个文件丢失或损坏了&#xff0c;那么在使用依赖于它…...

莱山做网站的公司/一键优化免费下载

文/ IT创事记 祁萌人工智能变现的速度和能力超乎了传统行业的想象。即便在计算机视觉这样的“市场显学”中&#xff0c;一个独特的切入点就可以让一家创业公司在市场中崭露头角。华为北京城市峰会中&#xff0c;生态伙伴对云与AI格外关注。小视科技&#xff08;Minivision&…...

昆明网站建设公司排名/百度竞价推广有哪些优势

import random #导入随机数工具包 def rollDice(): die1 random.randrange( 1, 7 ) #取1到7之间的任意一个数 die2 random.randrange( 1, 7 ) #取1到7之间的任意一个数 workSum die1 die2 #求两个随机数的和 print "Player rolled %d %d %d" % ( die1, die2, …...

wordpress定时发布文章0点/怎么免费建个人网站

一、启动项目&#xff1a; 1 django-admin start mysite1 2 cd mysite1 3 python manage.py startapp loginapp 根据上文敲命令就可以创建好了一个项目结构&#xff0c;之后就是修改配置文件&#xff0c;这里使用的数据库是MySQL的。 二、修改配置文件&#xff1a; settings.py…...

做网站百度/如何建网站赚钱

1、 Java连接MySQL数据库之properties文件配置 2、 Java连接MySQL数据库——含步骤和代码...

做网站 接单/全网营销的公司

安装8723bs.ko模块之后&#xff0c;生成了wlan0和wlan1&#xff0c;MAC地址一样。 http://blog.csdn.net/djman007/article/details/46731335 解决方法&#xff1a; insmod rtl8723.ko ifnamewlan0 if2namep2p0 wlan0和p2p0共用一个网卡。MAC地址也比较类似。 Tony Liu 2016-12…...

wordpress使用置顶文章没用/网络平台的推广方法

PPT文件上呦限制编辑&#xff0c;不知道密码应该怎么去掉&#xff1f; 取消限制编辑在不知道密码的情况下&#xff0c;需要用到工具的帮助【PPT解密大师】快速找回密码_轻松移除使用限制-奥凯丰okfone 选择【解除限制】将PPT文件添加到软件中&#xff0c;点击一下【开始】就可…...