千家信息网

Java中常犯的错误有哪些

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,本篇内容介绍了"Java中常犯的错误有哪些"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1. 忽略访
千家信息网最后更新 2026年11月02日Java中常犯的错误有哪些

本篇内容介绍了"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(n²)下降到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这样的静态代码分析器,它能指出实际错误,突显潜在错误。

"Java中常犯的错误有哪些"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

字符 字符串 对象 代码 内存 函数 方法 示例 错误 人员 内容 结果 开发 解释 密码 情况 文本 问题 编译 迭代 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 咖啡 互联网科技的 合肥互联网科技公司 北京互联网络科技有限公司 上海致骋互联网科技 互联网科技宣传片 中国互联网金融科技基金 栖莱科技互联网股份有限公司 重庆互联网医院沙龙医盟信息科技 南平创想时代互联网科技有限公司 岳阳华臻互联网科技有限公司 花神(南京)互联网科技有限公司 阿大互联网科技有限公司 本届互联网博览会上的黑科技 威龙国际互联网科技公司 2021互联网科技公司排名 互联网科技数字货币 上海创道互联网络科技有限公司 上海同邻互联网科技有限公司规模 杭州融税互联网科技有限公司 互联网科技公司 艾特科技互联网 福州新华互联网科技学校 知乎 随着互联网科技发展 互联网媒体平台算高科技产业 长沙互联网科技 互联网时代的科技公司 上海创道互联网络科技有限公司 科技互联网经济论坛 广州三三互联网科技有限公司
0