本帖最后由 blf1990 于 2014-04-29 16:29:58 编辑

解决方案 »

  1.   

    看了String类源码,还真没找到  是在什么时候 对 value进行赋值。
    所以有可能是在加载器做了这个事情。(猜的,还需要查找资料来证明一下)
    另外  String s = new String("test") ;//在constant pool 中会有一份  “test” ,在heap中会有一个“test”对象
    String a = "test"//只会在onstant pool 中会有一份  “test”
      

  2.   

    public String(String original) {...
    String str = new String("aa");  这里的"aa"应该相当于String original = "aa";
    jdk文档中说:
    String str = "abc";
     等效于: 
     char data[] = {'a', 'b', 'c'};
     String str = new String(data);
    在构造方法中String(char value[])赋值。
    个人观点,看有没有大神指出
     
      

  3.   

    字符串信息存在char[]的value中,赋值它既可实现复制字符串.
      

  4.   

    底层的东西很难解释清楚,可能实例化一个String对象时,String对象的值复制到char类型的数组中来使用的
      

  5.   

        public String(char value[]) {
            this.value = Arrays.copyOf(value, value.length);
        }
    String的value使用char[]初始化的啊。。
    LZ看的那个构造传进来的参数就是String
    类似
    String s;
    String str = new String(s);这个意思关于
    String s = new String("test") ,  
    String a = "test"  我理解这两种构造方式是一样的都用char[]构造。。
    楼上说的constantpool我不太懂JVM
      

  6.   

    String 中的value就是以char[] 的形式存在在内存中的呀
      

  7.   

    初始化一个新创建的 String 对象,使其表示一个与参数相同的字符序列;换句话说,新创建的字符串是该参数字符串的副本。由于 String 是不可变的,所以无需使用此构造方法,除非需要 original 的显式副本。
      

  8.   


    在运行Java应用程序时,使用的类得先加载到JVM,而在类的加载过程中,记得有 准备、初始化 等等;再看看字节码;
    比如:public static void main(String[] args) {
    String a = "test";
    String s = new String("test");

    a.toCharArray();
    s.toCharArray();
    }反编译后得到:
    常量池 信息(只取了一部分):
    const #14 = Asciz       main;
    const #15 = Asciz       ([Ljava/lang/String;)V;
    const #16 = String      #17;    //  test
    const #17 = Asciz       test;
    const #18 = class       #19;    //  java/lang/String
    const #19 = Asciz       java/lang/String;
    const #20 = Method      #18.#21;        //  java/lang/String."<init>":(Ljava/lang/String;)V
    const #21 = NameAndType #5:#22;//  "<init>":(Ljava/lang/String;)V
    const #22 = Asciz       (Ljava/lang/String;)V;
    const #23 = Method      #18.#24;        //  java/lang/String.toCharArray:()[C
    const #24 = NameAndType #25:#26;//  toCharArray:()[C
    const #25 = Asciz       toCharArray;
    const #26 = Asciz       ()[C;
    const #27 = Asciz       args;
    const #28 = Asciz       [Ljava/lang/String;;
    const #29 = Asciz       a;
    const #30 = Asciz       Ljava/lang/String;;
    const #31 = Asciz       s;
    const #32 = Asciz       SourceFile;main方法的字节码:
    public static void main(java.lang.String[]);
      Signature: ([Ljava/lang/String;)V
      Code:
       Stack=3, Locals=3, Args_size=1
       0:   ldc     #16; //String test
       2:   astore_1

       3:   new     #18; //class java/lang/String
       6:   dup
       7:   ldc     #16; //String test
       9:   invokespecial   #20; //Method java/lang/String."<init>":(Ljava/lang/String;)V
       12:  astore_2

       13:  aload_1
       14:  invokevirtual   #23; //Method java/lang/String.toCharArray:()[C
       17:  pop
       18:  aload_2
       19:  invokevirtual   #23; //Method java/lang/String.toCharArray:()[C
       22:  pop
       23:  return从上面的两条ldc指令可知:"test"  都是从常量池取来的;
     0:   ldc     #16; //String test  
     和 
     7:   ldc     #16; //String test对于String a = "test": 直接就是从常量池中取出"test",然后赋值给变量a;
    0:   ldc     #16; //String test
     2:   astore_1 对于 String s = new String("test"):创建个String对象,然后把"test"赋值给这个新创建的对象,然后赋值给变量s;
    3:   new     #18; //class java/lang/String
    6:   dup
    7:   ldc     #16; //String test
    9:   invokespecial   #20; //Method java/lang/String."<init>":(Ljava/lang/String;)V
    12:  astore_2从上可知:当加载这个main类后(运行main方法前),"test" 就已经存在 常量池 中了,既然 "test"  是个字符串(类型就是java.lang.String),那首先就得加载 java.lang.String 类,既然类都知道了,那么你说的 char[]  这些 String 类的字段信息都应该有了,而且 "test" 是个String实例,都说会存在 字符串常量池 中,那么那个 value[]  的值就有了;
    通过上面的说明,