群里面有小伙伴提了个问题,说在看并发源码的时候,很多时候源码中都使用for(;;)而不是使用while(true),这两个有什么区别吗?
这种问题,在java里面,最简单有效的办法就是打印字节码看一下,javap再次华丽丽的登场:
实践
1. 首先编写一个java文件,内容如下:
public class Demo {public void demo1() {for (;;) {}}public void demo2() {while (true) {}}}
2. 然后编译为class文件,并显示字节码:
zengyu@zengyu-Precision-T1700:~$ javac Demo.javazengyu@zengyu-Precision-T1700:~$ javap -verbose Demo.classClassfile /home/zengyu/Demo.classLast modified 2018-9-12; size 314 bytesMD5 checksum 5f959c0d031d1c2b2503d75222b0e94eCompiled from "Demo.java"public class Demominor version: 0major version: 52flags: ACC_PUBLIC, ACC_SUPERConstant pool:#1 = Methodref #3.#13 // java/lang/Object."<init>":()V#2 = Class #14 // Demo#3 = Class #15 // java/lang/Object#4 = Utf8 <init>#5 = Utf8 ()V#6 = Utf8 Code#7 = Utf8 LineNumberTable#8 = Utf8 demo1#9 = Utf8 StackMapTable#10 = Utf8 demo2#11 = Utf8 SourceFile#12 = Utf8 Demo.java#13 = NameAndType #4:#5 // "<init>":()V#14 = Utf8 Demo#15 = Utf8 java/lang/Object{public Demo();descriptor: ()Vflags: ACC_PUBLICCode:stack=1, locals=1, args_size=10: aload_01: invokespecial #1 // Method java/lang/Object."<init>":()V4: returnLineNumberTable:line 1: 0public void demo1();descriptor: ()Vflags: ACC_PUBLICCode:stack=0, locals=1, args_size=10: goto 0LineNumberTable:line 3: 0StackMapTable: number_of_entries = 1frame_type = 0 /* same */public void demo2();descriptor: ()Vflags: ACC_PUBLICCode:stack=0, locals=1, args_size=10: goto 0LineNumberTable:line 7: 0StackMapTable: number_of_entries = 1frame_type = 0 /* same */}SourceFile: "Demo.java"
3. 分析指令:
public void demo1();descriptor: ()Vflags: ACC_PUBLICCode:stack=0, locals=1, args_size=10: goto 0LineNumberTable:line 3: 0StackMapTable: number_of_entries = 1frame_type = 0 /* same */public void demo2();descriptor: ()Vflags: ACC_PUBLICCode:stack=0, locals=1, args_size=10: goto 0LineNumberTable:line 7: 0StackMapTable: number_of_entries = 1frame_type = 0 /* same */
可以看出二者在编译为字节码后是完全一致的。
字节码一模一样,能有啥区别?因此,在java里面,就看个人的爱好了,二者没区别!
更过关于java字节码的内容可以观看我的一个视频课程:Java生产环境下性能监控与调优详解
为啥网上有的文章说二者有区别呢?因为那是在C语言中!
在C语言中, while(1)在编译后:
mov eax,1test eax,eaxje foo+23hjmp foo+18h
for(;;)在编译后:
mp foo+23
这里的区别就非常明显了,for(;;)在c语言中指令较少,也能够节省内存,没有判断跳转,是比while(1)更好的无限循环。