由一次代码调试引发的对JAVA数值包装类型的使用的思考

简介: 由一次代码调试引发的对JAVA数值包装类型的使用的思考

问题的背景是这样的,判断数据库表中的一列是否有值以及该值是否是0,该列是数值型的,JAVA类中的类型是Long,注意这里使用的包装类。实际业务中的代码实现如下:

if(list!=null&&list.size()>0){
for(PoObjectobj:list){
if(obj.getFlowId()!=null&&!obj.getFlowId().equals(0)){
obj.setUrl(url.replace("aaa",String.valueOf(obj.getFlowId())));
        }
    }
}

从数据库表中查询出数据列表,然后遍历,判断是否flowId不为空且不为0的时候,对url属性做一个replace。url属性是显示到前端做跳转使用的。数据库表里flowId对应的列值都是0,启动项目的时候,发现页面上url地址都有值,这样就都做了跳转。本意是为0了,前端的url属性就是空的,提示暂无链接。那么问题出现在哪里了呢,就是!obj.getFlowId().equals(0)这个判断,这个判断对于flowId为0的时候返回是正确的,这就奇怪了,为啥0!=0是对的呢?其实是错用了equals方法。正确的写法应该是

!obj.getFlowId().equals(0L)。JDK中对于Long的equals的实现如下:

/*** Compares this object to the specified object.  The result is* {@code true} if and only if the argument is not* {@code null} and is a {@code Long} object that* contains the same {@code long} value as this object.** @param   obj   the object to compare with.* @return  {@code true} if the objects are the same;*          {@code false} otherwise.*/publicbooleanequals(Objectobj) {
if (objinstanceofLong) {
returnvalue== ((Long)obj).longValue();
        }
returnfalse;
    }

0不是属于Long的,而0L是属于Long的,同样要注意的是Float的类型,0f和0的类型在Float的equals中也不是一样的概念。除了!obj.getFlowId().equals(0L)可以以外,还可以使用obj.getFlowId().compareTo(0L)==0去判断。这里面有个要注意的点就是Long的compareTo方法参数是Long类型的,所以如果你写compareTo(0)会报编译错误,强制你使用0L,而equeals方法的参数是Object类型的,所以不会报编译错误。由这点可以看出来编译器暴露出问题来的重要性了。可以用如下的测试用例测试一下几个包装类的比较:

publicstaticvoidmain(String [] args) {
Longid=0L;
Floata=0f;
longid2=0;
System.out.println(id2==0); //trueSystem.out.println(a.equals(0)); //falseSystem.out.println(a.equals(0f)); //trueSystem.out.println(id.equals(0)); //falseSystem.out.println(id.equals(0L)); //trueSystem.out.println(id.compareTo(0L)); //0    }

虽然是个小问题,但是刚入行的同学找了半天没找出来,还感觉很奇怪。也不是什么大问题,更不要怀疑JDK会出bugs或者会给你模棱两可的答案,从自己提供的参数去考虑,以及使用的方法执行的逻辑输出的结果是否是预期的结果这方面的入手。看看源码确实是个不错的成长途径。可能以后会遇到Integer的比较的时候会存在小于还是大于127的缓存的问题,希望能避坑。

目录
打赏
0
0
0
0
97
分享
相关文章
|
27天前
|
java变量与数据类型:整型、浮点型与字符类型
### Java数据类型全景表简介 本文详细介绍了Java的基本数据类型和引用数据类型,涵盖每种类型的存储空间、默认值、取值范围及使用场景。特别强调了`byte`、`int`、`long`、`float`、`double`等基本类型在不同应用场景中的选择与优化,如文件流处理、金融计算等。引用数据类型部分则解析了`String`、数组、类对象、接口和枚举的内存分配机制。
55 15
|
28天前
|
课时11:Java数据类型划分(浮点类型)
课时11介绍了Java中的浮点数据类型。主要内容包括:1. 定义小数,默认使用Double类型;2. 定义Float变量,需在数值后加"F"或"f"进行强制转换;3. 观察不同类型计算结果,如Int型除法会丢失精度,需至少包含一个Double或Float类型以确保准确性。总结指出,在复杂计算中推荐使用Double类型以避免精度损失。
|
28天前
|
课时10:Java数据类型划分(整型类型)
本文主要围绕Java中整型数据展开,详细讲解整型变量、常量的概念,整型数据运算规则,包括数据溢出问题及解决方法,数据类型转换(自动转换与强制转换)的原理和注意事项,同时介绍了整型数据默认值的相关知识,以及byte数据类型与int数据类型的关系和使用场景,帮助读者全面掌握Java整型数据的相关内容。
Java泛型类型擦除以及类型擦除带来的问题
本文主要讲解Java中的泛型擦除机制及其引发的问题与解决方法。泛型擦除是指编译期间,Java会将所有泛型信息替换为原始类型,并用限定类型替代类型变量。通过代码示例展示了泛型擦除后原始类型的保留、反射对泛型的破坏以及多态冲突等问题。同时分析了泛型类型不能是基本数据类型、静态方法中无法使用泛型参数等限制,并探讨了解决方案。这些内容对于理解Java泛型的工作原理和避免相关问题具有重要意义。
Java 中 Set 类型的使用方法
【10月更文挑战第30天】Java中的`Set`类型提供了丰富的操作方法来处理不重复的元素集合,开发者可以根据具体的需求选择合适的`Set`实现类,并灵活运用各种方法来实现对集合的操作和处理。
Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面
本文探讨了Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面,帮助开发者提高代码质量和程序的健壮性。
130 2
Java泛型类型擦除以及类型擦除带来的问题
泛型擦除是指Java编译器在编译期间会移除所有泛型信息,使所有泛型类型在运行时都变为原始类型。例如,`List<String>` 和 `List<Integer>` 在JVM中都视为 `List`。因此,通过 `getClass()` 比较两个不同泛型类型的 `ArrayList` 实例会返回 `true`。此外,通过反射调用 `add` 方法可以向 `ArrayList<Integer>` 中添加字符串,进一步证明了泛型信息在运行时被擦除。
107 2
Java“不能转换的类型”解决
在Java编程中,“不能转换的类型”错误通常出现在尝试将一个对象强制转换为不兼容的类型时。解决此问题的方法包括确保类型间存在继承关系、使用泛型或适当的设计模式来避免不安全的类型转换。
778 7
Java“返回类型为 void 的方法不能返回一个值”解决
在 Java 中,如果一个方法的返回类型被声明为 void,那么该方法不应该包含返回值的语句。如果尝试从这样的方法中返回一个值,编译器将报错。解决办法是移除返回值语句或更改方法的返回类型。
424 5
|
6月前
|
Java 中锁的主要类型
【10月更文挑战第10天】