今天在Debug一个Java程序时,遇到一个问题就是源代码和Java字节码反编译之后的代码不一样。
源代码如下:
public CharSequence apply(final Object context, final Options options) throws IOException {
String policy = (String)options.hash("policy", "advanced");
if (context == null || StringUtil.isEmpty(context.toString())) {
return options.hash("default", "");
}
String value = context.toString();
if (value.startsWith(CDATA_START) && value.endsWith(CDATA_END)) {
return value;
}
return sanitize(value);
}
在字节码反编译之后,显示的代码如下:
public CharSequence apply(Object context, Options options) throws IOException {
String policy = (String)options.hash("policy", "advanced");
if (context != null && !StringUtil.isEmpty(context.toString())) {
String value = context.toString();
return value.startsWith("<![CDATA[") && value.endsWith("]]>") ? value : sanitize(value);
} else {
return (CharSequence)options.hash("default", "");
}
}
源代码中使用 || 操作符的判断,在字节码反编译之后,居然变成了&&的判断。
难道是&&的操作更快一些吗? 于是,写了如下测试代码进行测试:
public static boolean testIfStatement1(String value) {
if (value == null || value.length() == 0){
return true;
} else {
return false;
}
}
public static boolean testIfStatement2(String value) {
if (value != null && value.length() != 0){
return false;
} else {
return true;
}
}
测试所花时间的代码如下:
public static void main(String[] args) {
String value1 = null;
long startTime1 =System.nanoTime();
for (long i=0; i< 100000000;i++) {
TestUtil.testIfStatement1(value1);
}
long endTime1 =System.nanoTime();
System.out.println("Time cost for testIfStatement1 is "+endTime1);
String value2 = null;
long startTime2 =System.nanoTime();
for (long j=0; j< 100000000;j++) {
TestUtil.testIfStatement2(value2);
}
long endTime2 =System.nanoTime();
System.out.println("Time cost for testIfStatement2 is "+endTime2);
TestUtil.testQueryParam();
SpringApplication.run(LargestApplication.class, args);
}
分别取值为:test, "" 和null 测试的结果如下:
操作符 | 取值 | ||
test | “” | null | |
|| | 773894902573100 | 773984677463400 | 774730049828900 |
&& | 773895147096200 | 773984924305100 | 774730324403600 |
通过三组值的比较发现||的操作总是比&&的操作快。
于是又进一步查看两个函数的字节码:
发现唯一的不同的地方就是判断是否为null的时候的跳转目标不同,一个11(+10),一个是13(+12),难道是因为多跳了两个的缘故?
即使是如此,当判断的值不是null的时候,按理说,剩下的逻辑应该一样的了,时间也应该差不多,没想到的是也总是||的方法比较快。