我很好奇。比如
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:\anWorkSpace\pra_test\src\main\java\com\an>javap -c TestJavacVerbose
Compiled 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."":()V
4: return
public 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 a
push b
add
(实际的指令不是这样的,比如整数相加和double相加的指令是不同的,但是类似)
Push即压栈指令,最后生成一个Add指令,这样JVM在解释执行的时候,在解释add时,a和b已经在栈里面了。就做了a+b操作,操作好了之后再回写到栈区。
如果是c=a+b则会多一个类似于load指令,将栈区的数据读到变量c里面。