您的位置:首页 > 编程语言 > Java开发

深入 String 类

2016-03-16 11:05 447 查看
一,

public class String00
{
public static void main(String[] args)
{
// 下面是 jdk 文档中关于字面值字符串对象的说明:
// 原文:All string literals in Java programs, such as "abc", are
// implemented as instances of this class.
// 译文:Java 程序中所有的字符串字面值,例如 "abc" 等, 都是作为 String 类的实例被实现的。

// 输出 true,说明 s1 与 s2 的引用值相等。
// 这是由于 Java 中由 String 类维护一个 String Pool,
// 当通过字面值方式给一个字符串对象赋值时,
// 首先,会检查 String Pool 中有无该字符串,有,
// 直接返回该字符串的地址值,无,先在其中创建这个字符串,然后返回其地址值。
// 针对以下代码:
// 执行 s1 = "qp"; 时,String Pool 中没有字符串对象 "qp",
// 于是首先创建该对象,然后返回其地址值;
// 执行 s2 = "qp"; 时,String Pool 中已经存在字符串对象 "qp",
// 因此直接返回其地址值,也就是说,这行代码不会创建一个新的对象。
// 由于 s1 与 s2 指向同一个地址,所以最后判断结果为 true。
String s1 = "qp";
String s2 = "qp";
System.out.println(s1 == s2);
System.out.println("------------------");

// 使用加法连接字符串时会生成新的字符串对象,而不是向原有的 String 对象追加内容。
// 输出 false,说明 str 与 str3 的引用值不相等。
// 与下面的标号为 ① 的代码段结合起来看 < 该代码段执行结果亦为 false >
// 执行 str3 = str1 + str2; 时,相当于执行
// str3 = new String(str1 + str2);
// 这种使用 new 关键字给字符串对象赋值的方式执行流程为:
// 首先,检查 String Pool 中是否存在字符串 str1 + str2,
// 存在,直接在 heap 中创建字符串对象,然后返回其地址值
// 反之,则先在 String Pool 中创建该对象,然后再在 heap 中创建同样的一个对象,并返回其地址值。
// 这就是以下语句段返回 false 的原因。
String str = "hello";
String str1 = "hel";
String str2 = "lo";
String str3 = str1 + str2; // 运行时确定,在堆上,相当于new
System.out.println(str == str3);
System.out.println("------------------");
// ①
String str4 = new String("hel" + "lo");
System.out.println(str == str4);
System.out.println("-------------------");
// 直接进行 str5 = "hel" + "lo";
// 相当于 str5 = "hello";
// 故而会返回 true
String str5 = "hel" + "lo"; // 不涉及堆 编译时确定
System.out.println(str == str5);
System.out.println("--------------------");
// 补充:String Pool 位于栈中。
// intern() 返回字符串池中的字符串的引用,若没有该字符串(由equals判定),则新加入字符串再返回引用
String str6 = (str1 + str2).intern();
System.out.println(str == str6);
}
}


二,

Example 3.10.5-1. String Literals

The program consisting of the compilation unit (§7.3):

package testPackage;
class Test {
public static void main(String[] args) {
String hello = "Hello", lo = "lo";
System.out.print((hello == "Hello") + " ");
System.out.print((Other.hello == hello) + " ");
System.out.print((other.Other.hello == hello) + " ");
System.out.print((hello == ("Hel"+"lo")) + " ");
System.out.print((hello == ("Hel"+lo)) + " ");
System.out.println(hello == ("Hel"+lo).intern());
}
}


class Other { static String hello = "Hello"; }


and the compilation unit:

package other;
public class Other { public static String hello = "Hello"; }


produces the output:

true true true true false true


This example illustrates six points:

1. Literal strings within the same class (§8) in the same package (§7) represent references

to the same String object (§4.3.1).

2. Literal strings within different classes in the same package represent references to the

same String object.

3. Literal strings within different classes in different packages likewise represent references

to the same String object.

4. Strings computed by constant expressions (§15.28) are computed at compile time and

then treated as if they were literals.

5. Strings computed by concatenation at run-time are newly created and therefore distinct.

6. The result of explicitly interning a computed string is the same string as any pre-existing

literal string with the same contents.

只要在编译时可以确定字符串的值,这个字符串都会存到String Pool中,并返回在Pool上的引用。

三,

/*
* StringBuffer 类与 String 类不同
* StringBuffer 类所定义的是一个可变的字符串
* 如同 JDK 中所述:
* A string buffer is like a String, but can be modified. At any point in time
* it contains some particular sequence of characters, but
* the length and content of the sequence can be changed through certain method
* calls.
*/
public class TestStringBuffer
{
public static void main(String[] args)
{
StringBuffer buffer = new StringBuffer();
buffer.append("hello").append(",world").append("!");
System.out.println(buffer);

String str = buffer.toString();
System.out.println(str);

buffer.append(true);
System.out.println(buffer);

String s1 = Integer.toString(10);
String s2 = String.valueOf(20);
System.out.println(s1 + s2);
}
}


hello,world!
hello,world!
hello,world!true
1020


四,

1. String,StringBuffer,StringBuilder均实现了CharSequence接口;

2. String对象具有不变性,只可读。任何看起来修改了String值的情况,都会创建一个新的String对象;

3. Java里面和C++不同的是,不允许重载运算符,用于String的+、+=是Java中仅有的两个重载过的操作符,所以说,Java里面的=,就是对于引用的赋值操作;

4. 对String类型的+操作实际上是通过创建并操作StringBuilder对象实现的,所以,当使用+处理的字符串比较复杂时,就应该选择创建StringBuilder对象,再使用StringBuilder中所提供的丰富的方法完成字符串的构建;

5. 在没有引入StringBuilder之前,Java使用的是StringBuffer,StringBuffer是线程安全的,因此开销大于StringBuilder,也就是说,使用StringBuilder速度更快。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  string java