`

字符串详解

 
阅读更多
一、字符串的六道经典题

看明白了,基本上就掌握了字符串的原理了。

public class test1 {

/**
* @param args
*/
public static void main(String[] args){
String a = "a1";
String b = "a"+ 1;
System.out.println(a==b);
}//true

}



test2:

package StringTest;

public class test2 {

/**
* @param args
*/
public static void main(String[] args){
String a = "ab";
String bb = "b";
String b = "a"+ bb; //编译器不能确定为常量
System.out.println(a==b);
}//false

}

test3:


package StringTest;

public class test3 {

/**
* @param args
*/
public static void main(String[] args){
String a = "ab";
final String bb = "b";
String b = "a"+ bb; //bb加final后是常量,可以在编译器确定b
System.out.println(a==b);
}//true

}

test4:

package StringTest;

public class test4 {

/**
* @param args
*/
public static void main(String[] args){
String a = "ab";
final String bb = getBB();
String b = "a"+ bb;//bb是通过函数返回的,虽然知道它是final的,但不知道具体是啥,要到运行期才知道bb的值
System.out.println(a==b);
}//false
private static String getBB(){ return "b"; }

}

test5:

package StringTest;

public class test5 {

/**
* @param args
*/
private static String a = "ab";
public static void main(String[] args){
String s1 = "a";
String s2 = "b";
String s = s1 + s2;//+的用法
System.out.println(s == a);
System.out.println(s.intern() == a);//intern的含义
}//flase true

}

test6:

package StringTest;

public class test6 {

/**
* @param args
*/
private static String a = new String("ab");
public static void main(String[] args){
String s1 = "a";
String s2 = "b";
String s = s1 + s2;
System.out.println(s == a);
System.out.println(s.intern() == a);
System.out.println(s.intern() == a.intern());
}//flase false true
}

原因解析:

    String str1 = "java";
    String str2 = "blog";
    String s = str1+str2;
    System.out.print(s=="javablog");
原因很简单,JVM确实会对型如String str1 = "java"; 的String对象放在字符串常量池里,但是它是在编译时刻那么做的,而String s = str1+str2; 是在运行时刻才能知道,也就是说str1+str2是在堆里创建的,s引用当然不可能指向字符串常量池里的对象。没崩溃的人继续看例子D。

    另外,对字符串进行赋值时,假如右操纵数含有一个或一个以上的字符串引用时,则在堆中再建立一个字符串对象,返回引用;如String s=str1+ "blog"; 会在堆中创建对象。


二、创建了几个对象

    现在分析String str = new String("abc");创建了几个String对象。很明显,传入的"abc"字符串字面常量在驻留池中创建了一个对象,new操作符在堆中创建了一个对象,所以,一共创建了两个String对象,一个是编译期,一个是运行期。


三、字符串的不可变性

    String s1 = "s1";
  String s2 = s1;
  s2 = "s2";
  s1指向的对象中的字符串是什么?
  答案: "s1"。(永远不要忘了String不可变的,s2 = "s2";实际上s2的指向就变了,因为你不可以去改变一个String,)

Java运行环境有一个字符串池,由String类维护。执行语句String str="abc"时,首先查看字符串池中是否存在字符串"abc",假如存在则直接将"abc"赋给str,假如不存在则先在字符串池中新建一个字符串"abc",然后再将其赋给str。执行语句String str=new String("abc")时,不管字符串池中是否存在字符串"abc",直接新建一个字符串"abc"(留意:新建的字符串"abc"不是在字符串池中),然后将其付给str。前一语句的效率高,后一语句的效率低,由于新建字符串占用内存空间。String str = new String()创建了一个空字符串,与String str=new String("")相同。
String的不变性的机制显然会在String常量内有大量的冗余。如:"1" + "2" + "3" +......+ "n" 产生了n+(n+1)个String对象!因此Java为了更有效地使用内存,JVM留出一块特殊的内存区域,被称为“String常量池”。对String多么照顾啊!当编译器遇见String常量的时候,它检查该池内是否已经存在相同的String常量。如果找到,就把新常量的引用指向现有的String,不创建任何新的String常量对象。



四、怎么检查字符串在字符串常量池中
    public static boolean inPool(String s) {
        String s2 = s.intern();
        if (s2 == s)
            return true;
        return false;
    }

五、intern方法的作用

 当调用 intern 方法时,假如池已经包含一个即是此 String 对象的字符串(用 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并返回此 String 对象的引用。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics