今天看了下堆栈和常量池的概念发现无法确定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 a = 0 + 3,就会存到运行栈里。
      

  2.   

    谢谢啊,还想问一个 int a=3;是常量么?不是final int a=3;才是常量么?但是我看网上这也没加final啊,难道是3是常量,
      

  3.   

    String是一个很特殊的类,它不是基本类型,但是它有自己的常量池。你在A类中有一行代码:
    String a = "abc";
    这个abc字符串会先去String.class的常量池里找,如果以前没用过,常量池里是没有的,他会在常量池里创建一个,然后把a指向String.class的常量池里创建的那个字符串,如果已经有了就直接指向。
      

  4.   


    我想确认一下:int i=4;
                  private final j=5;
    这两个值都会保存在常量池中么?还是所谓的常量池只保存数值4和5?
      

  5.   

    如果是这样写:String a = new String("abc");
    String b = new String("abc");
    System.out.print(a==b);//false
    因为使用new操作,会把常量池里的字符串拷贝出来(如果没有会先在常量池创建),a和b分别指向的是拷贝的新字符串,和原常量池无关了,所以会成false.
      

  6.   


    我想确认一下:int i=4;
                  private final j=5;
    这两个值都会保存在常量池中么?还是所谓的常量池只保存数值4和5?j的类型是什么,int么?基本类型,只要编译期能确定的,都会放到常量池。
      

  7.   


    我想确认一下:int i=4;
                  private final j=5;
    这两个值都会保存在常量池中么?还是所谓的常量池只保存数值4和5?j的类型是什么,int么?基本类型,只要编译期能确定的,都会放到常量池。恩,谢谢http://bbs.csdn.net/topics/390443173中最后一个人说的貌似有点道理
      

  8.   


    我想确认一下: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会,这个原因也没找到是为什么。