Java中有两种类型,一种是基本类型,另一种是引用类型
基本类型:byte、short、char、int、long、float、double、bool
引用类型:除了以上8中类型,其他都是引用类型例1:
String str = "hello";
str是一个引用,指向了常量池中的"hello"这个对象。内存中的图:
----------        -----------
| 栈空间 |        |  常量池    |
|       |        |           |
|       |        |           |
|       |        |           |
|  str─┤────├─→"hello"│
└───┘         └──────┘
例2:
String str = new String("hello")
str是个引用类型,我们可以理解为指针。
当这句话执行完毕后,在栈、堆中都有空间被占用,栈中占用的空间存放str这个引用,而这个引用指向堆中被new出来的String对象。先看一看String类的一个构造方法:    /** The value is used for character storage. */
    private final char value[];    /** The offset is the first index of the storage that is used. */
    private final int offset;    /** The count is the number of characters in the String. */
    private final int count;    public String(String original) {
int size = original.count;
char[] originalValue = original.value;
char[] v;
   if (originalValue.length > size) {
      // The array representing the String is bigger than the new
      // String itself.  Perhaps this constructor is being called
      // in order to trim the baggage, so make a copy of the array.
            int off = original.offset;
            v = Arrays.copyOfRange(originalValue, off, off+size);
  } else {
      // The array representing the String is the same
      // size as the String, so no point in making a copy.
    v = originalValue;
  }
this.offset = 0;
this.count = size;
this.value = v;
    }
在栈里应该分配一个空间,这个空间是这个构造方法的String original(original的引用) 
这个引用就跟第一个例子string original="hello";效果一样。
在String类中offset和count都是值变量,而value可以理解成指针。
 看到了?其实new出来的这个对象自己有一个成员char []value来指向这个在常量池中字符串的。

解决方案 »

  1.   

    最后几段还是看不懂哪位大侠可以对这个String新对象系列的问题来个终极解释,带内存分析图的?
      

  2.   

    呵呵,我这图在这搞了半天,结果发上去成这样了...CSDN出个截图功能就好了..你要知道char []value;这个value在这里是指针,他指向常量池中的字符串。
    对于
    string s1 = "hello";
    string s2 = new string("hello");
    所以hbwhwang会说 如果可能访问private final char value[];的情况下,
    s1.value == s2.value
    因为他们都指向常量池中的同一个对象。
      

  3.   

    谢谢LZ了..我是个JAVA初学着..看了你的讲解对引用类型的明白多了..
    先遇到个问题..
    Integer n1=new Integer(50);
    Integer n2=new Integer(50);
    System.out.println(n1==n2);
    System.out.println(!n1==n2);
    先一开始把他们当int值去判断了..后来才知道引用类型不是这样的..
    请教LZ  这里的n1==n2是判断n1和n2是否指向同一地址吗.? 
    还有,,是不是每new一次就是给个新的地址?谢谢了.
      

  4.   

    我也是个初学,不过知道Integer是int的包装类。
    前面说了,除了那8种类型,其他都是引用类型。
    所以n1和n2都是引用类型。只要一new那么就在堆里分配空间了,n1和n2分别指向不同对象。
    System.out.println(n1==n2); 
    这里是判断他们的引用,你可以理解成判断地址。
    肯定是不同的,不同对象嘛~每次new实际是new了一个新的对象,在堆中分配对象的空间。希望和大家一起努力!共同进步!
      

  5.   

    整天在争论String的问题,都没有权威。
      

  6.   

    第一,我没有告诉别人这样一定正确,请看我的题目《内存执行小分析》
          我也再此声明过,我也是初学,只是对这个问题的一个总结而已。如果您觉得哪里不对,请明确指出,以便我们这些菜鸟学习。
          在您眼里参数表和常量池我哪里误导别人了,请您马上立即指出,您在这里说这些“废话”有什么用呢?
          而且在这里,我是通过我的努力学习,翻阅资料,查看API,询问他人得到的一个结论,我写了这么一大堆,您来一句这个,不仅对我不尊重,
          您实际上完全也是在误导他人
    第二,这不是争论,我是在和一些想弄明白这些问题的朋友讨论,学习的其中一部分-讨论 是必不可少的,想必您也知道。
          权威这个东西谁能说谁有权威?别人都是从会到不会的,精通的人就是有权威了么?出了新技术还不是跟着屁股后面走?
          这些都是基础,我希望也渴望把它弄明白。话说的非常直接,希望二位不要介意!
      

  7.   

    我倒,你说1+2 = 5,我说你在胡说还要我说哪里胡说了。你根本不了解JVM存储原理,凭自己的想象,事实上根本就浊你想象的那样,你不是在误导别人吗?String original(original的引用) 
    你认为参数那个因为是直接量所以在常量池中,而方法里面又直接指向了这个直接量,所以你说
    “其实new出来的这个对象自己有一个成员char []value来指向这个在常量池中字符串的。”这句话可以看出你根本不了解什么叫常量池,也不了解什么样的变量会指向常量池。
    任何语言编译后,在方法返回点上面是局部变量表,方法返回点下面是参数表。只有局变量表中的变量才可能指向常量池。
    参数表中的参数(严格而讲它不叫变量,只是一个即时操作数)怎么会在常量池中。这个对象自己有一个成员char []value又怎么会在常量池中。
      

  8.   

    另外,最本质的一点,直接常量在编译期已经在常量池中,简单说它已经存在class中,它的相对地址已经固定。
    而参数只有在运行期才知道传入的是什么内容,它又如何会在常量池中。
      

  9.   

    请参考我给出的地址连接,在我发表的引用里。
    那里一位大师说过
    string a = "hello";
    string b = new string("hello");
    假如说,假如说我们可以访问value的话
    那么a.value == b.value;
    这个你怎么理解呢?
    我说value这个引用指向常量池中字符串是错误的?
      

  10.   

    最后我想跟axman 说一句
    构造函数根本是没有任何返回的。
    thinking in java中提到:
    new表达式确实返回了对象新建对象的引用,但构造器本身并没有任何返回值。