String 的一些认识:
- String对象是不可变,所以使用 final 修饰
- 字符串拼接,合理利用 StringBuilder(线程非安全),StringBuffer 线程安全
- 常用方法就不详细介绍
■构造函数
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
- 实现 java.io.Serializable 接口,支持序列化
- 实现Comparable 接口,实现比较
- 实现CharSequence 接口,实现字符的一些方法
■String 的一些重载
public class StringPlusTest { public static void main(String[] args) { String mango = "mango"; String s = "abc" + mango + "def" + 47; //底层使用 StringBuilder 进行拼接 System.out.println(s); } }
javap 反编译,jvm码显示: 我们看到jvm其实调用了StringBuild 来处理字符串拼接
■字符串对象
public class StringTest { public static void main(String[] args) throws Exception { String a = "chenssy"; String b = "chenssy"; String c = new String("chenssy"); System.out.println("--------------修改前值-------------------"); System.out.println("a = " + a); System.out.println("b = " + b); System.out.println("c = " + c); //修改String的值 Field a_ = String.class.getDeclaredField("value"); a_.setAccessible(true); char[] value=(char[])a_.get(a); value[4]='_'; //修改a所指向的值 System.out.println("--------------修改后值-------------------"); System.out.println("a = " + a); //chen_sy System.out.println("b = " + b); //chen_sy System.out.println("chenssy"); //chen_sy System.out.println("c = " + c); //chen_sy } }
我们知道字符串的分配和其他对象分配一样,是需要消耗高昂的时间和空间的,而且字符串我们使用的非常多。JVM为了提高性能和减少内存的开销,在实例化字符串的时候进行了一些优化:使用字符串常量池。每当我们创建字符串常量时,JVM会首先检查字符串常量池,如果该字符串已经存在常量池中,那么就直接返回常量池中的实例引用。如果字符串不存在常量池中,就会实例化该字符串并且将其放到常量池中。由于String字符串的不可变性我们可以十分肯定常量池中一定不存在两个相同的字符串(这点对理解上面至关重要)。
- a, b, c 引用与 jvm 常量池的交互
■正则表达式 (#todo#)