String(字符串常量)概述
在API中是这样描述:
1 | /*String 类代表字符串。Java 程序中的所有字符串字面值(如 "abc" )都作为此类的实例实现。 |
需要注意的是:String是一个不可变对象,可以认为是特殊的常量,因此存在方法区的运行时常量池中,可以被共享使用(享元模式),而不是创建一个新对象,但是这样的做法仅仅适合于通过=符号进行的初始化
由此引申出许多判断各种情况下,string对象是否相等的判断
常见的String == 比较
首先,我们在比较两个string对象之前,需要了解:
- 通过构造方法创建(new创建)的String对象,存放在java虚拟机的堆内存,堆内存里存放的是字符串常量的地址,字符串常量存放在方法区的常量池中;
- 直接赋值:通过直接赋值所创建的对象直接是方法区中的常量池中的字符串常量。
下面列举一些常见的比较例子:
1 | String s1 = "Hello"; |
分析:
- s1 = = s2 很容易可以判断出来。s1 和 s2 都指向了方法区常量池中的Hello。
- s1 = = s3 这里要注意一下,因为做+号的时候,会进行优化,自动生成Hello赋值给s3,所以也是true
- s1 = = s4 s4是分别用了常量池中的字符串和存放对象的堆中的字符串,做+的时候会进行动态调用,最后生成的仍然是一个String对象存放在堆中。
- s1 = = s9 在JAVA9中,因为用的是动态调用,所以返回的是一个新的String对象。所以s9和s4,s5这三者都不是指向同一块内存
- s1 = = s6 为啥s1 和 s6地址相等呢? 归功于intern方法,这个方法首先在常量池中查找是否存在一份equal相等的字符串如果有的话就返回该字符串的引用,没有的话就将它加入到字符串常量池中,所以存在于class中的常量池并非固定不变的,可以用intern方法加入新的
String、StringBuffer、StringBuilder。
- String 和 StringBuffer、StringBuilder 的区别在于 String 声明的是不可变的对象,每次操作都会生成新的 String 对象,然后将指针指向新的 String 对象;
- 而 StringBuffer、StringBuilder 可以在原有对象的基础上进行操作,所以在经常改变字符串内容的情况下最好不要使用 String。
- StringBuffer 和 StringBuilder 最大的区别在于,StringBuffer 是线程安全的,而 StringBuilder 是非线程安全的;
- 但 StringBuilder 的性能却高于 StringBuffer,所以在单线程环境下推荐使用 StringBuilder,多线程环境下推荐使用 StringBuffer。
如何将字符串反转
使用 StringBuilder 或者 stringBuffer 的 reverse() 方法。
1 | // StringBuffer reverse |
String 类的常用方法都有那些?
- indexOf():返回指定字符的索引。
- charAt():返回指定索引处的字符。
- replace():字符串替换。
- trim():去除字符串两端空白。
- split():分割字符串,返回一个分割后的字符串数组。
- getBytes():返回字符串的 byte 类型数组。
- length():返回字符串长度。
- toLowerCase():将字符串转成小写字母。
- toUpperCase():将字符串转成大写字符。
- substring():截取字符串。
- equals():字符串比较。