今天看了下堆栈和常量池的概念发现无法确定int的值到底是放在栈中还是方法区域中1和2冲不冲突?:
(难道是根据是否编译期就可确定来区分么?)
1、
栈有一个很重要的特殊性,就是存在栈中的数据可以共享。假设我们同时定义:
int a = 3;
int b = 3;
编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找栈中是否有3这个值,如果没找到,就将3存放进来,然后将a指向3。接着处理int b = 3;在创建完b的引用变量后,因为在栈中已经有3这个值,便将b直接指向3。这样,就出现了a与b同时均指向3的情况。
2、
常量池(constant pool)指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。除了包含代码中所定义的各种基本类型(如int、long等等)和对象型(如String及数组)的常量值(final)还包含一些以文本形式出现的符号引用,比如: 类和接口的全限定名; 字段的名称和描述符; 方法和名称和描述符。 虚拟机必须为每个被装载的类型维护一个常量池。常量池就是该类型所用到常量的一个有序集和,包括直接常量(string,integer和floating point常量)和对其他类型,字段和方法的符号引用。
在程序执行的时候,常量池会储存在Method Area,而不是堆中
(难道是根据是否编译期就可确定来区分么?)
1、
栈有一个很重要的特殊性,就是存在栈中的数据可以共享。假设我们同时定义:
int a = 3;
int b = 3;
编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找栈中是否有3这个值,如果没找到,就将3存放进来,然后将a指向3。接着处理int b = 3;在创建完b的引用变量后,因为在栈中已经有3这个值,便将b直接指向3。这样,就出现了a与b同时均指向3的情况。
2、
常量池(constant pool)指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。除了包含代码中所定义的各种基本类型(如int、long等等)和对象型(如String及数组)的常量值(final)还包含一些以文本形式出现的符号引用,比如: 类和接口的全限定名; 字段的名称和描述符; 方法和名称和描述符。 虚拟机必须为每个被装载的类型维护一个常量池。常量池就是该类型所用到常量的一个有序集和,包括直接常量(string,integer和floating point常量)和对其他类型,字段和方法的符号引用。
在程序执行的时候,常量池会储存在Method Area,而不是堆中
int a = 0 + 3,就会存到运行栈里。
String a = "abc";
这个abc字符串会先去String.class的常量池里找,如果以前没用过,常量池里是没有的,他会在常量池里创建一个,然后把a指向String.class的常量池里创建的那个字符串,如果已经有了就直接指向。
我想确认一下:int i=4;
private final j=5;
这两个值都会保存在常量池中么?还是所谓的常量池只保存数值4和5?
String b = new String("abc");
System.out.print(a==b);//false
因为使用new操作,会把常量池里的字符串拷贝出来(如果没有会先在常量池创建),a和b分别指向的是拷贝的新字符串,和原常量池无关了,所以会成false.
我想确认一下:int i=4;
private final j=5;
这两个值都会保存在常量池中么?还是所谓的常量池只保存数值4和5?j的类型是什么,int么?基本类型,只要编译期能确定的,都会放到常量池。
我想确认一下:int i=4;
private final j=5;
这两个值都会保存在常量池中么?还是所谓的常量池只保存数值4和5?j的类型是什么,int么?基本类型,只要编译期能确定的,都会放到常量池。恩,谢谢http://bbs.csdn.net/topics/390443173中最后一个人说的貌似有点道理
我想确认一下:int i=4;
private final j=5;
这两个值都会保存在常量池中么?还是所谓的常量池只保存数值4和5?j的类型是什么,int么?基本类型,只要编译期能确定的,都会放到常量池。恩,谢谢http://bbs.csdn.net/topics/390443173中最后一个人说的貌似有点道理学习了。根据那个帖子的方法,我研究了下。
测试代码:public class Test{
private static int a = 32767;
private static int b = 32768;
private static double c = 1d;
private static double d = 2d;
private static final int e = 2;
public static void main(String[] args){
int f =32766;
int g =32769;
final int h = 32765;
final int i = 32770;
}
}
JAVAP运行后的显示:Constant pool:
#1 = Methodref #11.#30 // java/lang/Object."<init>":()V
#2 = Integer 32769
#3 = Fieldref #10.#31 // Test.a:I
#4 = Integer 32768
#5 = Fieldref #10.#32 // Test.b:I
#6 = Fieldref #10.#33 // Test.c:D
#7 = Double 2.0d
#9 = Fieldref #10.#34 // Test.d:D
#10 = Class #35 // Test
#11 = Class #36 // java/lang/Object
#12 = Utf8 a
#13 = Utf8 I
#14 = Utf8 b
#15 = Utf8 c
#16 = Utf8 D
#17 = Utf8 d
#18 = Utf8 e
#19 = Utf8 ConstantValue
#20 = Integer 2
#21 = Utf8 <init>
#22 = Utf8 ()V
#23 = Utf8 Code
#24 = Utf8 LineNumberTable
#25 = Utf8 main
#26 = Utf8 ([Ljava/lang/String;)V
#27 = Utf8 <clinit>
#28 = Utf8 SourceFile
#29 = Utf8 Test.java
#30 = NameAndType #21:#22 // "<init>":()V
#31 = NameAndType #12:#13 // a:I
#32 = NameAndType #14:#13 // b:I
#33 = NameAndType #15:#16 // c:D
#34 = NameAndType #17:#16 // d:D
#35 = Utf8 Test
#36 = Utf8 java/lang/Object
{
private static int a;
flags: ACC_PRIVATE, ACC_STATIC private static int b;
flags: ACC_PRIVATE, ACC_STATIC private static double c;
flags: ACC_PRIVATE, ACC_STATIC private static double d;
flags: ACC_PRIVATE, ACC_STATIC private static final int e;
flags: ACC_PRIVATE, ACC_STATIC, ACC_FINAL
ConstantValue: int 2 public Test();
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>
":()V
4: return
LineNumberTable:
line 1: 0 public static void main(java.lang.String[]);
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=5, args_size=1
0: sipush 32766
3: istore_1
4: ldc #2 // int 32769
6: istore_2
7: return
LineNumberTable:
line 11: 0
line 12: 4
line 16: 7 static {};
flags: ACC_STATIC
Code:
stack=2, locals=0, args_size=0
0: sipush 32767
3: putstatic #3 // Field a:I
6: ldc #4 // int 32768
8: putstatic #5 // Field b:I
11: dconst_1
12: putstatic #6 // Field c:D
15: ldc2_w #7 // double 2.0d
18: putstatic #9 // Field d:D
21: return
LineNumberTable:
line 2: 0
line 3: 6
line 5: 11
line 6: 15
}
可以看到,基本类型变量的存放要分2种情况:
被final修饰时:
如果是成员变量,一定会存入常量池,比如变量b;
如果是局部变量,既不会存入常量池,也不在栈中,在方法体操作中完全看不到相应的操作,这点很困惑,希望有高人指点下。没有被final修饰时:
不管是成员变量还是局部变量,都不一定会被存入常量池,int类型的变量会以2的15次方为基准,大于等于这个数就会存入常量池,小于则不会;
但是double类型1d不会,2d会,这个原因也没找到是为什么。