黑马程序员技术交流社区

标题: 看视频 对字符串池不是太懂??? [打印本页]

作者: 张庚    时间: 2013-2-2 20:07
标题: 看视频 对字符串池不是太懂???
本帖最后由 张庚 于 2013-2-4 11:40 编辑

package cn.itcast.p1.string.demo;

public class StringObjectDemo {


        /**
         * @param args
         */
        public static void main(String[] args) {

//                String s1 = "abc";
//                String s2 = "abc";
               
                //intern():对字符串池进行操作的
               
                String s1 = new String("abc");
                String s2 = s1.intern();
               
                System.out.println(s1==s2);
               
               
               
        }

}

不是堆和栈吗 字符串池是个什么概念????
作者: 杨浩    时间: 2013-2-2 20:56
String中intern的方法
首先查看官方API那个的解释:
———————————————————————————————————————
intern
public String intern()
返回字符串对象的规范化表示形式。
一个初始时为空的字符串池,它由类 String 私有地维护。
当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并且返回此 String 对象的引用。
它遵循对于任何两个字符串 s 和 t,当且仅当 s.equals(t) 为 true 时,s.intern() == t.intern() 才为 true。
所有字面值字符串和字符串赋值常量表达式都是内部的。
返回:
一个字符串,内容与此字符串相同,但它保证来自字符串池中。
———————————————————————————————————————
尽管在输出中调用intern方法并没有什么效果,但是实际上后台这个方法会做一系列的动作和操作。在调用”ab”.intern()方法的时候会返回”ab”,但是这个方法会首先检查字符串池中是否有”ab”这个字符串,如果存在则返回这个字符串的引用,否则就将这个字符串添加到字符串池中,然会返回这个字符串的引用。
可以看下面一个范例:
  1. String str1 = "a";
  2. String str2 = "b";
  3. String str3 = "ab";
  4. String str4 = str1 + str2;
  5. String str5 = new String("ab");
  6.   
  7. System.out.println(str5.equals(str3));
  8. System.out.println(str5 == str3);
  9. System.out.println(str5.intern() == str3);
  10. System.out.println(str5.intern() == str4);
复制代码
得到的结果:
true
false
true
false
为什么会得到这样的一个结果呢?我们一步一步的分析。
第一、str5.equals(str3)这个结果为true,不用太多的解释,因为字符串的值的内容相同。
第二、str5 == str3对比的是引用的地址是否相同,由于str5采用new String方式定义的,所以地址引用一定不相等。所以结果为false。
第三、当str5调用intern的时候,会检查字符串池中是否含有该字符串。由于之前定义的str3已经进入字符串池中,所以会得到相同的引用。
第四,当str4 = str1 + str2后,str4的值也为”ab”,但是为什么这个结果会是false呢?先看下面代码:
  1. String a = new String("ab");
  2. String b = new String("ab");
  3. String c = "ab";
  4. String d = "a" + "b";
  5. String e = "b";
  6. String f = "a" + e;

  7. System.out.println(b.intern() == a);
  8. System.out.println(b.intern() == c);
  9. System.out.println(b.intern() == d);
  10. System.out.println(b.intern() == f);
  11. System.out.println(b.intern() == a.intern());
复制代码
运行结果:
false
true
true
false
true
由运行结果可以看出来,b.intern() == a和b.intern() == c可知,采用new 创建的字符串对象不进入字符串池,并且通过b.intern() == d和b.intern() == f可知,字符串相加的时候,都是静态字符串的结果会添加到字符串池,如果其中含有变量(如f中的e)则不会进入字符串池中。但是字符串一旦进入字符串池中,就会先查找池中有无此对象。如果有此对象,则让对象引用指向此对象。如果无此对象,则先创建此对象,再让对象引用指向此对象。
    当研究到这个地方的时候,突然想起来经常遇到的一个比较经典的Java问题,就是对比equal和==的区别,当时记得老师只是说“==”判断的是“地址”,但是并没说清楚什么时候会有地址相等的情况。现在看来,在定义变量的时候赋值,如果赋值的是静态的字符串,就会执行进入字符串池的操作,如果池中含有该字符串,则返回引用。
执行下面的代码:
  1. String a = "abc";
  2. String b = "abc";
  3. String c = "a" + "b" + "c";
  4. String d = "a" + "bc";
  5. String e = "ab" + "c";
  6.          
  7. System.out.println(a == b);
  8. System.out.println(a == c);
  9. System.out.println(a == d);
  10. System.out.println(a == e);
  11. System.out.println(c == d);
  12. System.out.println(c == e);
复制代码
运行的结果:
true
true
true
true
true
true
运行的结果刚好验证了我刚才的猜想。
------------------------------------------------
还有不懂的就继续跟帖。。




作者: 梁锡伟    时间: 2013-2-2 21:58
就是你已经使用过一个东西了,这个东西会在一个地方存起来,当再次使用的时候可以直接从这个地方里面拿过来用,而不用自己new一个
作者: 王宝生    时间: 2013-2-4 09:51
举一个例子,看看如下的代码:
String str1="one";
String str2="one";
    如果没有字符串池的概念,那么上述代码就会在堆中创建两个对象,而且这两个对象的内容完全一模一样,当源代码中有大量的类似代码时,很显然会浪费内存。
  为了减少内存的浪费,引入了字符串池的概念。
  虚拟机首先在内部维护一个表,每当创建一个新对象时都会遍历这个表,如果已经有相同的对象了,那么就不需要在创建一个新对象,只需要返回现有对象的一个引用即可。。。如果表中没有这个对象,那么就在堆中新创建一个对象,然后再表中新创建一个条目,这个条目指向刚才创建的那个对象,然后返回这个这个条目。
   在上述代码中,String str1=“one”;在第一次创建这个对象时,虚拟机首先会遍历那个表,发现没有值为one的对象,此时虚拟机就会在堆中创建一个对象,将这个对象初始化为one,然后在表中添加一个队该对象的指针,最后返回这个指针给str1.
   第二次,String str2=“one”,虚拟机还会遍历那个表,这次他发现已经有一个值为one的对象了,所以就不比在创建一个新对象了,直接返回这个对象的引用即可了。
  
   事实上,这不应叫做字符串池,而是字符串留用机制。之所以可以采用这个机制,是因为字符串是个常量,一旦创建之后就不可以在更改,所以,可以使用多个指针指向这同一个对象。如果字符串不是个常量,这就会引起灾难,因为更新这个对象可能会影响多个指针。
  还有,我刚才所说的就是个原理,细节可能并不是如此,譬如,为了提高检测表的速度,这个表可能采用一个哈希实现。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2