Java String总结

1.String字符串常量池

JVM为了提高性能和减少内存开销,内部维护了一个字符串常量池,每当创建字符串常量时,JVM首先检查字符串常量池,如果常量池中已经存在,则返回池中的字符串对象引用,否则创建该字符串对象并放入池中。

因此下述结果返回true。

1 String a = "abc";
2 String b = "abc";
3 System.out.print(a == b); //true

但与创建字符串常量方式不同的是,当使用new String(String str)方式等创建字符串对象时,不管字符串常量池中是否有与此相同内容的字符串,都会在堆内存中创建新的字符串对象。

因此,下面代码片段有如下结果。

1 String a = "Hello";
2 String b = new String("Hello");
3 System.out.println(a == b);  //false
4 System.out.println(a.equals(b)); //true

即使字符串内容相同,字符串常量池中的字符串与通过new String(..)等方式创建的字符串对象之间没有直接的关系,但是,可以通过字符串的intern()方法找到此种关联。intern()方法返回字符串对象在字符串常量池中的对象引用,若字符串常量池中尚未有此字符串,则创建一新的字符串常量放置于池中。

于是,很据如上理解,很自然的,可以得到如下结果。

1 String a = "Hello";
 2 System.out.println(a == a.intern()); //true
 3 
 4 String b = new String("corn");
 5 String c = b.intern();
 6 
 7 System.out.println(b == c); //false
 8 
 9 String d = "corn";
10 
11 System.out.println(c == d); //true

2.String/StringBuilder/StringBuffer区别

String是不可变字符串对象,StringBuilder和StringBuffer是可变字符串对象(其内部的字符数组长度可变),StringBuffer线程安全,StringBuilder非线程安全。

3.既然String是不可变字符串对象,如何才能改变让其可变?

既然String对象中没有对外提供可用的public setters等方法,因此只能通过Java中的反射机制实现。因此,前文中说到的String是不可变字符串对象只是针对“正常情况下”。而非必然。

public static void stringReflection() throws Exception {
 2 
 3     String s = "Hello World";
 4 
 5     System.out.println("s = " + s); //Hello World
 6 
 7     //获取String类中的value字段
 8     Field valueField = String.class.getDeclaredField("value");
 9 
10     //改变value属性的访问权限
11     valueField.setAccessible(true);
12 
13     char[] value = (char[]) valueField.get(s);
14 
15     //改变value所引用的数组中的第5个字符
16     value[5] = '_';
17 
18     System.out.println("s = " + s); //Hello_World
19 }

由此可见Java中反射的强大之处。

原文地址:https://www.cnblogs.com/xiarongjin/p/8309680.html