常言道:“细节决定成败”,编程更是如此。
近期,我参加的一个项目,让我对此体会深刻。
这个项目属于推荐系统的一部分,我负责的一块是进行MapRedcue编程,计算视频之间的相似度!另一个同事就把我计算出来的结果用Sqoop导入到数据库中,供线上调用。
在导入数据的过程中,总是爆出java.lang.NumberFormatException异常,我认为是他那里的原因,他的Sqoop没有进行空行或者空格过滤,我的相似度结果是没有错的。后来他把一部分相似度结果复制到Notepad里面,发现有的数据有空格,他是直接读入,然后进行转换,当然就出现问题了。我不知道Sqoop能不能进行空格过滤,但是,我的程序可以控制输出的结果,所以就对每一个输出结果都调用了java.lang.String类的trim()方法。最终问题解决。
空格,总是会造成一些小问题,但是不容忽视。消除空格,记得调用trim()方法。
另一个问题是基本数据类型的封装类进行比较的时候,可能不是比较的数值,而是内存的地址!
相似度计算的过程中,有一个地方需要进行java.lang.Long类型之间的相等判断。我发现最终的相似度输出结果不正确时,排查原因,最终定位到这里。原来的代码是这样的:
1 2 3 | if (lg1 == lg2){
return true;
}
|
Salin selepas log masuk
lg1和lg2都是java.lang.Long类型,我在这里是想判断lg1和lg2的数值是否相等,之前,我只是笼统地记得,Java的封装类进行比较的时候会进行转换的,所以就这样写了!但是这样写也可能比较大不是数值,而是他们各自在内存中的地址。
我用Google搜索了这个问题,网上说,java.lang.Float类型和java.lang.Double类型使用“==”进行相等判断需要转换成基本数据类型,java.lang.Integer和java.lang.Long则不需要转换,Java会自动转换的。但是,我自己做的测试跟这种说法有出入。下面是测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | package org.jindao.basic;
public class BasicTest {
public static void main(String[] args) {
Integer ig1 = 3;
Integer ig2 = 3;
System.out.println( "Integer ig1 = 3,Integer ig2 = 3 ig1==ig2的结果为:" +(ig1==ig2));
Integer ig3 = new Integer(3);
Integer ig4 = new Integer(3);
System.out.println( "Integer ig3 = new Integer(3),Long ig4 = new Integer(3) ig3==ig4的结果为:" +(ig3==ig4));
Long lg1 = 3l;
Long lg2 = 3l;
System.out.println( "Long lg1 = 3l,Long lg2 = 3l lg1==lg2的结果为:" +(lg1==lg2));
Long lg3 = new Long(3);
Long lg4 = new Long(3);
System.out.println( "Long lg3 = new Long(3),Long lg4 = new Long(3) lg3==lg4的结果为:" +(lg3==lg4));
Float flt1 = 3.2f;
Float flt2 = 3.2f;
System.out.println( "Float flt1 = 3.2f,Float flt2 = 3.2f flt1==flt2的结果为:" +(flt1==flt2));
Float flt3 = new Float(3.2);
Float flt4 = new Float(3.2);
System.out.println( "Float flt3 = new Float(3.2),Float flt4 = new Float(3.2)) flt3==flt4的结果为:" +(flt3==flt4));
Double db1 = 3.2;
Double db2 = 3.2;
System.out.println( "Double db1 = 3.2,Double db2 = 3.2 db1==db2的结果为:" +(db1==db2));
Double db3 = new Double(3.2);
Double db4 = new Double(3.2);
System.out.println( "Double db3 = new Double(3.2),Double db4 = new Double(3.2) db3==db4的结果为:" +(db3==db4));
}
}
|
Salin selepas log masuk
运行结果:
1 2 3 4 5 6 7 8 | Integer ig1 = 3,Integer ig2 = 3 ig1==ig2的结果为:true
Integer ig3 = new Integer(3),Long ig4 = new Integer(3) ig3==ig4的结果为:false
Long lg1 = 3l,Long lg2 = 3l lg1==lg2的结果为:true
Long lg3 = new Long(3),Long lg4 = new Long(3) lg3==lg4的结果为:false
Float flt1 = 3.2f,Float flt2 = 3.2f flt1==flt2的结果为:false
Float flt3 = new Float(3.2),Float flt4 = new Float(3.2)) flt3==flt4的结果为:false
Double db1 = 3.2,Double db2 = 3.2 db1==db2的结果为:false
Double db3 = new Double(3.2),Double db4 = new Double(3.2) db3==db4的结果为:false
|
Salin selepas log masuk
从结果可以看出,只有Integer和Long类型直接赋数值的时候,使用“==”判断相等才会为true,其余的时候都为false。
也就是说其余的情况比较多都是变量在内存存放的地址,并不是变量的数值。
那为什么Integer和Long类型直接赋数值,结果为true,而Float和Double类型直接赋数值,结果为false呢?我猜测,Java本身有优化措施,就是给Integer和Long类型直接赋数值的时候,内存里面并没有建立Integer和Long类型的对象,而是直接优化为基本数据类型int和long,所以是用“==”判断相等,结果才会为true。
为了保险起见,当判断封装类变量的数值相等时,最好直接取出数值来进行“==”判断,或者使用equals方法,即
像这些小细节,如果不搞清楚,说不定什么时候就造成*烦。
细节决定成败,Java编程中还有很多需要注意的细节,这里只探讨一二。
Atas ialah kandungan terperinci Java编程中那些需要注意的细节. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!