String 的一些问题

来源:互联网 发布:现在开淘宝店晚不晚 编辑:程序博客网 时间:2024/05/21 15:38

java面试中总喜欢问关于String对象的问题,比如:

String s = new String("abc"); 创建了几个String对象

还有:

       String s1 = "abc";       String s2 = "a";       String s3 = s2 + "bc";       String s4 = "a" + "bc";       String s5 = s3.intern();    
s1 == s3 是true还是false,   s1 == s4 是true还是false  s1 == s5呢

今天看了下,java API文档

  1. API中:

        字符串是常量, 它们的值在创建之后不能更改,因为String 对象是不可变的,所以可以共享 . 
  2. 那么,是如何共享的呢,String类的intern 方法有如下说明: (自己可以去看API)

        返回字符串对象的规范化表示形式。    一个初始为空的字符串池,它由类 String 私有地维护。    当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(用 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并返回此 String 对象的引用。    它遵循以下规则:对于任意两个字符串 s 和 t,当且仅当 s.equals(t) 为 true 时,s.intern() == t.intern() 才为 true。    所有字面值字符串和字符串赋值常量表达式都使用 intern 方法进行操作。字符串字面值在 Java Language Specification 的 §3.10.5 定义。    返回:     一个字符串,内容与此字符串相同,但一定取自具有唯一字符串的池。
  3. 也就是说, String类自己维护了一个池,把程序中的String对象放到那个池里面,于是我们代码中只要用到值相同的String,就是同一个String对象,节省了空间

  4. 但是,并不是任何时候String对象都在这个字符串池中, 那么,到底哪些String 对象在池中,哪些在堆中, java 语言规范第三版 String Literals 的最后一段话 解释了,

    首先解释下 什么是字符串字面常数,字面常数就是你写在源代码里面的值,比如说 :
    int i = 6;  6就是一个整数型字面常数String s = "abc"; "abc" 就是一个字符串字面常数

    java中,所有的字符串字面常数都放在上文提到的字符串池里面,是可以共享的,就是说:

     String s1 = "abc"; String s2 = "abc";  //s1 与s2 都引用的同一个字符串对象,而且这个对象在字符串池里面,因此 s1 == s2 . 另外 ,字符串字面常数是什么时候实例化并放到字符串池里面去的呢,答案是: Load Class的时候
  5. 任何类,任何包,值相同的字符串字面常数都引用同一个对象

  6. 通常,通过常量表达式计算出来的字符串,也算字符串字面常数,就是说他们也在字符串池中

  7. 在程序中运行时通过连接(+) 计算出来的字符串对象,是新创建的,他们不是字符面常数,就是他们值相同,他们也不在字符串池里面,他们在堆内存空间里,因此引用的对象各不相同。
  8. String类的intern方法,返回一个值相同的String对象,但是这个对象就是一个字符串字面常数一样,意思就是,他也到字符串池里面去了。
  9. 来看 上面 2个问题

    String s = new String("abc"); 创建了2个对象,一个是字符串字面常数,在字符串池中。 一个是new出来的字符串对象,在堆中。
      String s1 = "abc";  String s2 = "a";  String s3 = s2 + "bc";  String s4 = "a" + "bc";  String s5 = s3.intern(); // s1==s3  是false; s3 是运行时,才能计算出来的字符串,是new的,在堆中不在字符串池中, // s1 == s4 是true; s4 是通过常量表达式计算出来的,他等同于字符串字面常数,在字符串池中, // s1 == s5 是true; s5 是s3 放到字符串池里面返回的对象,所以相等

    这里需要注意: s3.intern() 方法,是返回字符串在池中的引用,并不会改变s3这个变量的引用,就是s3 还是指向堆中的那个“abc”, 并没有因调用的intern()方法而改变,实际也不可能改变

详情可看: http://www.360doc.com/content/14/0716/22/1073512_394899105.shtml

0 0