百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分类 > 正文

小心陷阱!Java中常犯的10个错误(审查java代码的十一种常见错误)

ztj100 2024-11-06 13:18 13 浏览 0 评论

全文共2361字,预计学习时长9分钟



常在河边走哪有不湿鞋,有些错误真的是防不胜防。然而,以笔者面试过从菜鸟到高级技术负责人,几十位软件工程师的经历看来,在更多情况下,候选人在对基本概念的掌握上是存在差距的。


本文中笔者根据自己作为技术主管和面试官的经验,列出Java开发人员最常犯的错误,快看看自己是不是中枪了。


1.忽略访问修饰符


虽然有点莫名其妙,但候选者真的经常忘记Java中protected访问修饰符的作用域。也许是因为面试过程中过于焦虑和紧张,他们通常只能答出其一:


· 可从子类访问protected字段、方法和构造函数。

· 可从同一包中访问protected字段、方法和构造函数。


此外,包的作用域能帮助许多开发人员编写自己的测试:可以从测试路径访问受保护的方法。所以忘记这个属性等同于在面试中表明自己从来没有编写过测试!



2.字符串连接


如果使用大量字符串或大型字符串,则可能会在连接过程中浪费大量内存。


上述示例是创建一些StringBuilder和String对象:准确来说,是10.000.000个StringBuilder和10.000.001个String。


解释


先退一步,看看发生了什么。


当使用+运算符进行字符串连接时,将创建一个中间对象,该对象存储连接的结果后,将结果赋值给目标对象。


在如上示例中,一共创建了3个对象:2个用于文本,1个用于连接,即第一个字符串result的副本加上第二个字符串“world!”。因为String是不可变的,所以这种字符串连接是可以实现的。


但是编译器是足够智能的,可以将代码转化为以下内容(Java9+不适用,因为它使用StringContactFacotry,但结果非常相似):


此优化删除了中间连接对象,内存被2个字符串文本和1个StringBuilder占用。总体而言,字符串对象的数量从O(n2)下降到O(n)。


回到第一个示例,编译器对代码的优化如下:


编译器只是优化了内部连接,但这会创建很多StringBuilder和String对象!连接字符串的正确方法如下,只需一个StringBuilder和一个String。


3.没有使用equals()


如果你正在使用==(比较运算符)而不是调用equals()函数,那么你需要改变这个习惯,结果可能会令人大吃一惊。


解释


当想要比较两个String以及其他任何对象时,不要使用==。==只比较两个操作数的对象引用(内存地址比较)而非内容。


在上面的例子中,字符串不能启动字符串驻留机制:它的内存地址与x不同。

4.返回null


笔者已经发现了很多次这样的方法:


返回null的问题是强行让调用方对结果进行空检查;在这种情况下,如果没有项,调用方就会返回空列表。


开发人员总是希望返回一个异常或特殊对象(如空列表),否则使用代码的应用程序将受到NullPointerException的影响。


5.密码为字符串


将用户提供的密码存储在字符串对象中是一个安全问题,字符串容易受到内存攻击。


应该使用char[],就如同JPasswordField和Password4j正在做的那样。但如果讨论的是Web应用程序,大多数Web容器都将HttpServletRequest对象中的纯文本密码作为String传递,所以开发人员几乎对此无能为力。



解释


字符串由Java虚拟机(JVM)(驻留)缓存并存储在PermGen空间(Java8之前)或堆空间中。在这两种情况下,只有在垃圾回收发生后才删除缓存值:这意味着无法得知特定值何时会从字符串池中删除,因为垃圾收集器的行为是不确定的。


另一个问题是,String是不可变的,因此不能清除它们。然而char[]是可变的,并且可以在处理后删除(例如用0替换每个元素)。通过这个简单的技巧,攻击者只能在内存中找到全为零的数组而不是纯文本密码。


6.传递null


传递null意味着,理所当然地认为调用的代码可以管理null。如果不能,那么应用程序肯定会抛出NullPointerException。


另外,显式传递null会使代码越来越混乱。下面是一个典型实例:


调用init()时,没有可用的User对象。那么,如果一个User都没有,为什么要调用一个对User进行操作的函数呢?如果需要grantAccessToUser()中的逻辑,就应该从其他的函数中提取并使用,而非传递null。


7.Heavy methods


以下示例可能会导致系统性能损失:


Pattern.compile()是一个资源占用极高的函数,不应在每次检查字符串是否与同一模式匹配时都调用它。


解释


Pattern.compile() 将模式预编译,以便使用更快的内存表示。与单个匹配相比,此操作需要极强的计算能力。


增加性能的经典方法是在静态字段中缓存Pattern对象,如下所示:


每次使用同一个资源占用极高的无状态对象时,都应该使用这个解决方案。


8.迭代时处理集合


这段代码将抛出ConcurrentModificationException。


解释


在迭代时从列表中删除某个项目,列表迭代器会运行不良,例如跳过元素、重复元素、索引数组末尾等。这就是许多集合更容易抛出oncurrentModificationException的原因。


使用底层数组迭代器:


9.使用“返回码”而不是抛出异常


在某种意义上,开发人员认为异常是不祥的,因此他们倾向于编写返回奇怪值的函数,如-1或“C_ERR”。


这是一个值得创建自定义Exception的典型情况。该示例可以改写如下:


正如所见,代码的可读性和可维护性大大提高。调用者只需读取DeviceStartException的内容,而不必处理每个返回码。


10.使用StringBuffer


由于StringBuffer的同步特性,此示例会产生大量内存占用。在更复杂的环境中,读取器可能会错认为某些不必要的同步是必要的。


如果项目中包含StringBuffer,可能是因为某些遗留API(即Java5之前)需要它,而很少是因为代码试图在并发环境中追加String。改用StringBuilder:在Java5时引入,其所有操作是不同步的。


这只是笔者在面试和活动项目中看到的部分错误,还没有提到面向对象编程(OOP)的陷阱、设计模式、过度设计、内存泄漏等缺陷……



如果你有这些问题,那么是时候改变编码风格。这并不难,避免这些陷阱能增强开发人员的经验,并且使人主动为下一次面试做更多的准备。


多使用像SonarQube这样的静态代码分析器,它能指出实际错误,突显潜在错误。



更重要的是保持学习,不仅是语法,还包括任何编程语言背后的理论。多敲代码多练习,让小错误远离你~

留言点赞关注

我们一起分享AI学习与发展的干货

如转载,请后台留言,遵守转载规范

相关推荐

Vue 技术栈(全家桶)(vue technology)

Vue技术栈(全家桶)尚硅谷前端研究院第1章:Vue核心Vue简介官网英文官网:https://vuejs.org/中文官网:https://cn.vuejs.org/...

vue 基础- nextTick 的使用场景(vue的nexttick这个方法有什么用)

前言《vue基础》系列是再次回炉vue记的笔记,除了官网那部分知识点外,还会加入自己的一些理解。(里面会有部分和官网相同的文案,有经验的同学择感兴趣的阅读)在开发时,是不是遇到过这样的场景,响应...

vue3 组件初始化流程(vue组件初始化顺序)

学习完成响应式系统后,咋们来看看vue3组件的初始化流程既然是看vue组件的初始化流程,咋们先来创建基本的代码,跑跑流程(在app.vue中写入以下内容,来跑流程)...

vue3优雅的设置element-plus的table自动滚动到底部

场景我是需要在table最后添加一行数据,然后把滚动条滚动到最后。查网上的解决方案都是读取html结构,暴力的去获取,虽能解决问题,但是不喜欢这种打补丁的解决方案,我想着官方应该有相关的定义,于是就去...

Vue3为什么推荐使用ref而不是reactive

为什么推荐使用ref而不是reactivereactive本身具有很大局限性导致使用过程需要额外注意,如果忽视这些问题将对开发造成不小的麻烦;ref更像是vue2时代optionapi的data的替...

9、echarts 在 vue 中怎么引用?(必会)

首先我们初始化一个vue项目,执行vueinitwebpackechart,接着我们进入初始化的项目下。安装echarts,npminstallecharts-S//或...

无所不能,将 Vue 渲染到嵌入式液晶屏

该文章转载自公众号@前端时刻,https://mp.weixin.qq.com/s/WDHW36zhfNFVFVv4jO2vrA前言...

vue-element-admin 增删改查(五)(vue-element-admin怎么用)

此篇幅比较长,涉及到的小知识点也比较多,一定要耐心看完,记住学东西没有耐心可不行!!!一、添加和修改注:添加和编辑用到了同一个组件,也就是此篇文章你能学会如何封装组件及引用组件;第二能学会async和...

最全的 Vue 面试题+详解答案(vue面试题知识点大全)

前言本文整理了...

基于 vue3.0 桌面端朋友圈/登录验证+60s倒计时

今天给大家分享的是Vue3聊天实例中的朋友圈的实现及登录验证和倒计时操作。先上效果图这个是最新开发的vue3.x网页端聊天项目中的朋友圈模块。用到了ElementPlus...

不来看看这些 VUE 的生命周期钩子函数?| 原力计划

作者|huangfuyk责编|王晓曼出品|CSDN博客VUE的生命周期钩子函数:就是指在一个组件从创建到销毁的过程自动执行的函数,包含组件的变化。可以分为:创建、挂载、更新、销毁四个模块...

Vue3.5正式上线,父传子props用法更丝滑简洁

前言Vue3.5在2024-09-03正式上线,目前在Vue官网显最新版本已经是Vue3.5,其中主要包含了几个小改动,我留意到日常最常用的改动就是props了,肯定是用Vue3的人必用的,所以针对性...

Vue 3 生命周期完整指南(vue生命周期及使用)

Vue2和Vue3中的生命周期钩子的工作方式非常相似,我们仍然可以访问相同的钩子,也希望将它们能用于相同的场景。...

救命!这 10 个 Vue3 技巧藏太深了!性能翻倍 + 摸鱼神器全揭秘

前端打工人集合!是不是经常遇到这些崩溃瞬间:Vue3项目越写越卡,组件通信像走迷宫,复杂逻辑写得脑壳疼?别慌!作为在一线摸爬滚打多年的老前端,今天直接甩出10个超实用的Vue3实战技巧,手把...

怎么在 vue 中使用 form 清除校验状态?

在Vue中使用表单验证时,经常需要清除表单的校验状态。下面我将介绍一些方法来清除表单的校验状态。1.使用this.$refs...

取消回复欢迎 发表评论: