- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
作为一名java开发程序员,不知道大家有没有遇到过一些匪夷所思的bug。这些错误通常需要您几个小时才能解决。当你找到它们的时候,你可能会默默地骂自己是个傻瓜。是的,这些可笑的bug基本上都是你忽略了一些基础知识造成的。其实都是很低级的错误。今天,我总结一些常见的编码错误,然后给出解决方案。希望大家在日常编码中能够避免这样的问题.
欢迎关注微信公众号「JAVA旭阳」交流和学习 。
这种方法相信大家并不陌生,甚至很多人都经常使用。是JDK7提供的一种方法,可以快速实现对象的比较,有效避免烦人的空指针检查。但是这种方法很容易用错,例如:
Long longValue = 123L;
System.out.println(longValue==123); //true
System.out.println(Objects.equals(longValue,123)); //false
为什么替换 == 为 Objects.equals() 会导致不同的结果?这是因为使用 == 编译器会得到封装类型对应的基本数据类型 longValue ,然后与这个基本数据类型进行比较,相当于编译器会自动将常量转换为比较基本数据类型, 而不是包装类型.
使用该 Objects.equals() 方法后,编译器默认常量的基本数据类型为 int 。下面是源码 Objects.equals() ,其中 a.equals(b) 使用的是 Long.equals() 会判断对象类型,因为编译器已经认为常量是 int 类型,所以比较结果一定是 false .
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
public boolean equals(Object obj) {
if (obj instanceof Long) {
return value == ((Long)obj).longValue();
}
return false;
}
知道了原因,解决方法就很简单了。直接声明常量的数据类型,如 Objects.equals(longValue,123L) 。其实如果逻辑严密,就不会出现上面的问题。我们需要做的是保持良好的编码习惯.
在我们日常的开发中,经常需要对日期进行格式化,但是很多人使用的格式不对,导致出现意想不到的情况。请看下面的例子.
Instant instant = Instant.parse("2021-12-31T00:00:00.00Z");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("YYYY-MM-dd HH:mm:ss")
.withZone(ZoneId.systemDefault());
System.out.println(formatter.format(instant));//2022-12-31 08:00:00
以上用于 YYYY-MM-dd 格式化, 年从 2021 变成了 2022 。为什么?这是因为 java 的 DateTimeFormatter 模式 YYYY 和 yyyy 之间存在细微的差异。它们都代表一年,但是 yyyy 代表日历年,而 YYYY 代表星期。这是一个细微的差异,仅会导致一年左右的变更问题,因此您的代码本可以一直正常运行,而仅在新的一年中引发问题。12月31日按周计算的年份是2022年,正确的方式应该是使用 yyyy-MM-dd 格式化日期.
这个 bug 特别隐蔽。这在平时不会有问题。它只会在新的一年到来时触发。我公司就因为这个bug造成了生产事故.
如果创建一个 ThreadLocal 变量,访问该变量的线程将创建一个线程局部变量。合理使用 ThreadLocal 可以避免线程安全问题.
但是,如果在线程池中使用 ThreadLocal ,就要小心了。您的代码可能会产生意想不到的结果。举个很简单的例子,假设我们有一个电商平台,用户购买商品后需要发邮件确认.
private ThreadLocal<User> currentUser = ThreadLocal.withInitial(() -> null);
private ExecutorService executorService = Executors.newFixedThreadPool(4);
public void executor() {
executorService.submit(()->{
User user = currentUser.get();
Integer userId = user.getId();
sendEmail(userId);
});
}
如果我们使用 ThreadLocal 来保存用户信息,这里就会有一个隐藏的bug。因为使用了线程池,线程是可以复用的,所以在使用 ThreadLocal 获取用户信息的时候,很可能会误获取到别人的信息。您可以使用会话来解决这个问题.
在编码的时候,我们经常会有去重的需求。一想到去重,很多人首先想到的就是用 HashSet 去重。但是,不小心使用 HashSet 可能会导致去重失败.
User user1 = new User();
user1.setUsername("test");
User user2 = new User();
user2.setUsername("test");
List<User> users = Arrays.asList(user1, user2);
HashSet<User> sets = new HashSet<>(users);
System.out.println(sets.size());// the size is 2
细心的读者应该已经猜到失败的原因了。 HashSet 使用 hashcode 对哈希表进行寻址,使用 equals 方法判断对象是否相等。如果自定义对象没有重写 hashcode 方法和equals方法,则默认使用父对象的 hashcode 方法和 equals 方法。所以 HashSet 会认为这是两个不同的对象,所以导致去重失败.
ExecutorService executorService = Executors.newFixedThreadPool(1);
executorService.submit(()->{
//do something
double result = 10/0;
});
上面的代码模拟了一个线程池抛出异常的场景。我们真正的业务代码要处理各种可能出现的情况,所以很有可能因为某些特定的原因而触发 RuntimeException .
但是如果没有特殊处理,这个异常就会被线程池吃掉。这样就会导出出现问题你都不知道,这是很严重的后果。因此,最好在线程池中 try catch 捕获异常.
本文总结了在开发过程中很容易犯的5个错误,希望大家养成良好的编码习惯.
欢迎关注微信公众号「JAVA旭阳」交流和学习 更多学习资料请移步: 程序员成神之路 。
最后此篇关于90%的Java开发人员都会犯的5个错误的文章就讲到这里了,如果你想了解更多关于90%的Java开发人员都会犯的5个错误的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
是否有用于手动测试的代码覆盖工具?比如我新写了30行代码,编译,然后运行,有什么办法可以快速验证这30行都运行了吗? 另外,后来,在我将代码 checkin 正式版本后,有什么方法可以验证测试部门在进
老实说,这是一个家庭作业问题,但我已经浪费了好几个小时,而且无法正确解决。它返回错误数量的结果或错误的数据: 我需要选择参与指导电影和/或在电影中表演的每个人以及他们所做的次数,如果至少 5 次。 有
我正在尝试测试 MacOS 的应用内购买。输入测试用户凭据后,App Store 提示:“当前收据无效或 ds 人员 ID 不匹配。”并且购买失败。 最佳答案 我尝试了很多方法来解决这个问题。 Get
我正在为 Jenkins 使用 ActiveDirectory 插件,因此用户必须使用他们的凭据登录到 Jenkins。然后用户在 Jenkins 中被称为 joe.doe,这很完美。 当同一个人 c
如何从 Infopath 人员/组选取器检索电子邮件地址?当我将人员/组选取器添加到 infopath 表单时,我只得到 3 个字段 DisplayName、AccountId、AccountType
在 Snow Leopard 中,可以在 iCal 事件中显示空闲/忙碌时间。我搜索了 CalStore.framework 的 header ,但找不到任何描述该字段的属性。如何检索日历事件的忙/闲
是否有人成功地从专门针对 SharePoint 2013 的新建或编辑表单中获取用户(个人或组)字段的值? 我已经尝试了通过搜索互联网找到的所有解决方案以及我自己能想到的所有解决方案,所有结果都为空白
所以我需要将一个 Twitter 帐户添加到 ABRecordRef 中。然而,最快的方法似乎是获取社交资料属性的多值引用,创建它的可变版本,查找它是否有 Twitter 条目,如果已经有,则创建
我正在尝试将使用 Tomcat(最初是 5.5,但可以与 7 一起使用)在 MyEclipse 中开发的应用程序部署到我们的演示服务器 (Sun Java Web Server 7)。不幸的是,所有设
我是一名优秀的程序员,十分优秀!