问题1:
String aa="bbb"; 有这么一说法,如果前面内存里有bbb,那么本次就是引用,就是指向bbb,如果前面没有就创建bbb。我认为好像是错误的,例如:String aa="ddd";  String bb="ddd"; 我更改aa为oooo  那岂不是bb也要更改其值?
这个问题引申出来的问题就是:
String aa=new String("ddd"); String bb="ddd";创建了几个对象。问题2:
String aa = new String("ddd");为什么是申请了2个对象呢,难道aa也算,引用和这个创建对象没关系吧

解决方案 »

  1.   

    你的理解错了的
    String 是终态类,每次赋值都重新创建一个对象,然后赋值给aa,   String aa="ddd";  String bb="ddd"; 我更改aa为oooo  那岂不是bb也要更改其值    bb的值不会改变,前提: String pool 中不存在 ddd对象 
    问题1 前面 2,后面 1;
    问题2   一个事 ddd 字符串常量对象  ,一个事 new 出来的对象存放在 堆中否则就都减一呵呵,等待高手找错
      

  2.   

    String aa = new String("ddd")  这个我明白了,
      

  3.   

    例如:String aa="ddd";  String bb="ddd"; 我更改aa为oooo  那岂不是bb也要更改其值? 
    -------------------------------------------------------------------
    将aa改为oooo,使aa指向新的的oooo,而bb还是指向ddd,bb的值怎么会变?
      

  4.   

    楼上说的对,string aa="ddd",是把aa得值指向ddd这个值的地址,而不是说aa就绑定了ddd这个值,当你把aa改变时候,你改变的是引用,而不是把ddd地址上的值改变,所以不会影响其他指向ddd地址的对象的值
      

  5.   

    问题1:我认为好像是错误的,例如:String aa="ddd";  String bb="ddd"; 我更改aa为oooo  那岂不是bb也要更改其值? String aa="ddd" 的执行过程是这样的:
    1. 在内存“栈”中建立引用 aa(其实就是一个JAVA的引用,保存内存地址)
    2. 查找 内存“栈”中是否 已经含有 "ddd",如果有则直接aa-->"ddd";如果没有“ddd”继续。
    3. 栈中没有“ddd”,则在内存栈中创建“ddd”。引申意义:栈中的数据时共享的,已经存在的"ddd",不需要重复建立。如果你使用 aa="oooo" 那么aa-->"oooo" ,bb-->"ddd" 。问题2: String aa = new String("ddd");为什么是申请了2个对象呢,难道aa也算,引用和这个创建对象没关系吧。在java中,使用 String aa = new String("ddd"); 表示,在内存“堆”中创建一个对象“ddd”,使用引用aa-->对象“ddd”,一般我们认为引用也是一个对象。所以共有两个对象。aa 这个引用你可以理解为:电视机的遥控开关,"ddd"你理解为:电视机。当你在房间走中的时候,你可以携带遥控器走动,同时可以操纵电视机。而不需要你抱着电视机到处走动。
      

  6.   

    String aa = new String("ddd");为什么是申请了2个对象呢,难道aa也算,引用和这个创建对象没关系吧这个问题是关于java字符串对象池String aa = new String("ddd");申请了对象数更具体运行环境有关。
    1.如果字符对象池中有字符串“ddd”,则只会在堆中创建一个字符串对象aa值为“ddd”
    2.如果字符对象池中没有字符串“ddd”,首先会在字符串对象池中创建一个字符串对象值为“ddd”,然后在堆中创建一个字符串对象aa值为“ddd”
      

  7.   


    有人告诉我应该这么理解:
    String是一个类,
    new String();算一个,"ddd"算一个,引用不算
      

  8.   

    第一个的理解我觉得是这样:
    两个String(aa、bb)都指向String池中的“bbb”,当楼主把aa赋值成oooo时jvm会在String池里找“oooo”,找不到就又建了一个,把引用地址给aa,此时aa指向“oooo",而bb仍然指向“bbb”。
      

  9.   

    "更改aa为oooo" 的时候 因为常量池里没有"oooo"  所以将会新创建一个"oooo" 而不是改变原来的
      

  10.   

    请看jdk的API里是怎么写的String
    public String(String original)Initializes a newly created {@code String} object so that it represents
    the same sequence of characters as the argument; in other words, the
    newly created string is a copy of the argument string. Unless an
    explicit copy of {@code original} is needed, use of this constructor is
    unnecessary since Strings are immutable.初始化一个新创建的 String 对象,使其表示一个与参数相同的字符序列;换句话说,新创建的字符串是该参数字符串的副本。由于 String 是不可变的,所以无需使用此构造方法,除非需要 original 的显式副本。 
      

  11.   

    有人告诉我应该这么理解:
    String是一个类,
    new String();算一个,"ddd"算一个,引用不算完全错误。5楼完全正解。
      

  12.   

    楼上的 5楼完全正确? 请仔细看看我刚才发的jdk的API怎么描述的
    如果无法理解 请多看几遍另外 "一般我们认为引用也是一个对象" 这个说法就是错的 引用是引用 对象是对象 要区分开来
      

  13.   

    如果还无法理解 看String源码!
      

  14.   


    的确,5楼说的不正确
    String aa="ddd"与String aa=new String("ddd");是不同的
    后者是jvm会在String pool中创建"ddd"对象,然后在堆中创建另一个"ddd"对象由aa引用,这也就是为什么为说String aa=new String("ddd");会创建2个对象的缘故。
    前者是直接在string pool中查找是否有符合equals()返回true的String,如果有,那么直接指向string pool而不再在堆中创建"ddd"对象.也就是说
    String aa=new String("ddd");//该句创建2个对象
    String bb=new String("ddd");//该句由于string pool中已经存在"ddd"那么只会在堆中创建一个"ddd"对象由bb引用
    String cc="ddd";//该句由于String pool中已经存在"ddd",则直接指向String pool中的"ddd",不会创建对象,只会创建引用
    现在应该明白了吧
      

  15.   

     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其中一个构造器
      

  16.   

    java中又个静态池
    当 String aa = "ddd";时
    如果静态池中又"ddd"就指向它,如果没有就先创建"ddd"到静态池
    所以String aa = "ddd"和String bb = "ddd"他们指向的地址是一样的
    如果这个时候aa = "ccc"那就再静态池创建"ccc"然后aa指向"ccc",此时bb还是指向"ddd"
      

  17.   

    既然大家要咬文嚼字,那我就问题讲清楚吧:参看thinking in java 第四版 里面对“数据”(包括对象)存储区域的解释:1  寄存器         速度最快的存储区域,Java不能操纵此区域2  堆栈(stack)  存储对象引用,位于通用RAM区域,对象的引用存储在此区域3  内存堆(heap) 存储JAVA对象(JAVA通过new创建对象)4  静态存储区     存储static变量,位于RAM的特定区域5  常量存储        存储在程序本身6  非RAM         流,持久化对象(保存在硬盘上)等
    再看string 的两个构造器:------------------------------------------------------------------------------
    /**
         * Initializes a newly created <code>String</code> object so that it
         * represents an empty character sequence.  Note that use of this 
         * constructor is unnecessary since Strings are immutable. 
         */
        public String() {
    this.offset = 0;
    this.count = 0;
    this.value = new char[0];
        }
     
    /**
         * Initializes a newly created <code>String</code> object so that it
         * represents the same sequence of characters as the argument; in other
         * words, the newly created string is a copy of the argument string. Unless 
         * an explicit copy of <code>original</code> is needed, use of this 
         * constructor is unnecessary since Strings are immutable. 
         *
         * @param   original   a <code>String</code>.
         */
        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.
        v = new char[size];
          System.arraycopy(originalValue, original.offset, v, 0, 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;
        }
    ------------------------------------------------------------------------------
    由存储区域分析:
    可见在JAVA里面使用的是char[] 数组存储的String 。(在JAVA中数组也是一种隐式的对象,它存在于"java.unil.Arrays"中),现在问题来了。
    1)请问char[]数组存储在什么地方?
    2)别告诉我说是存储在String pool 里,请问String pool 位于RAM的哪个区域?
    3)String pool是个什么破玩意儿,别"google it,百度之"一些垃圾帖就来误人子弟可以吗?不知道没关系,我告诉你,其实就是:静态存储区。即char[] 中的每一个char都是以二进制的形式存储在 RAM上特定的区域(这个区域不是内存堆也不是内存栈)在这个区域里面,数据是共享的,即:你创建过了"ddd"就没有必要再创建了,直接从这个区域取就可以了,提高程序运行效率。
    回到刚才的问题:
    String aa=new String("ddd"); String bb="ddd"; 创建几个对象?aa是引用-->存储在"内存栈",它指向一个char['d','d','d'](数组是隐式对象)"ddd"-->存储在"静态存储区",理解为:一个char['d','d','d'](数组是隐式对象)new String("ddd")-->既然有new关键字,就在内存堆中开辟一个String "ddd"对象。请问:一共有几个对象,答:两个(1个String对象 ,1个char[]数组(隐式)对象)。
    new String("ddd")     内存堆上存储了1个String对象  
    "ddd"                 内存"静态存储区"存了1个char[]数组:1个 (隐式)对象
    aa是一个引用  指向"ddd" 它实际上指向一个char['d','d','d']数组隐式对象
    PS:引用当然不是对象,但是它指向1个char[]数组:1个 (隐式)对象,你就理解为:引用已经指向了一个对象,加上 new String("ddd"),难道不是两个对象?