问题描述
我很好奇。比如System.out.println(1+1);这里的1+1并没有赋值给任何变量,但是jdk内部是不是会默认赋值给一个我看不见的变量。比如int rs = 1+1;还是没有变量,只是在内存开辟一个空间,存储而已?
解决方案
使用jdk自带的javap查看字节码:源文件:package com.an;public class TestJavacVerbose{public static void main(String[] args){System.out.println(1+1);}}cmd下运行:E:anWorkSpacepra_testsrcmainjavacoman>javap -c TestJavacVerboseCompiled from "TestJavacVerbose.java"public class com.an.TestJavacVerbose extends java.lang.Object{public com.an.TestJavacVerbose(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: returnpublic static void main(java.lang.String[]); Code: 0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 3: iconst_2 4: invokevirtual #3; //Method java/io/PrintStream.println:(I)V 7: return}注意倒数第四行:iconst_2就是说把常量2放入栈中。也就是说2是放在class文件的常量池中的,再具体说就是类加载器加载class文件的时候,才把这个2放到方法区的常量池中,在class文件中时它只是占用了一点点字节来存储。结论:没有你说的变量,只是占用了一点空间存储了这个编译期就明确的常量而已。几乎所有编译期就能确定的内容都是这样的。
解决方案二:
应该不会的,目前的JDK会把1+1优化为2(在编译期间就会变成2)。 其中2实际上是保存在常量区的,每个Class会分配一个const pool。如果是system.out.println(a+b),也不会生成一个临时变量的,因为Java解释器实际上是栈式的方式进行解释。编译器会生成类似于如下的指令:push apush badd (实际的指令不是这样的,比如整数相加和double相加的指令是不同的,但是类似)Push即压栈指令,最后生成一个Add指令,这样JVM在解释执行的时候,在解释add时,a和b已经在栈里面了。就做了a+b操作,操作好了之后再回写到栈区。如果是c=a+b则会多一个类似于load指令,将栈区的数据读到变量c里面。