String类
1字符串中常用的构造方法
- 直接赋值:String中独有
String str = “abc”;
- 通过字符串构造方法产生字符串对象
String str = new String(“abc”);
- 任何一门高级语言字符串内部其实都是字符数组
char data={‘a’,’b’,’c’};
String str = new String(data);
- 调用字符串构的静态方法valueOf
String str = String.valueOf(“abc”);
字符串String本身并没有存储数据,数据都在内部的字符数组中储存,String类只是将字符数组套了一个类,并向外部提供了很多好用的方法
String = char[]+方法
2 String对象的比较
- ”==”比较两个字符串对象是否指向相同的地址(String引用指向的是存储在堆中的字符数组的首地址(首地址也存储在堆中))
- 使用equals方法判断两个字符串对象的内容是否相同,当两个字符数组内容对应完全相同,equals才返回true.(equals方法区分大小写)
equalsIgnoreCase:不区分字符串大小写
- 使用compareTo方法进行两个字符串大小的比较(默认区分大小写)
- 先按照两个字符串对应的字符进行编码比较,若碰到第一个不相等的字符,直接返回编码差值
- 若前k个字符完全相等(k是较小字符串的长度),则返回值为两个字符串的长度差
compareToIgnoreCase不区分大小写的比较用法如上
3字符串查找 其本质就是在其内部的字符数组中进行遍历查找
char charAt(int index):返回字符串上指定索引位置的字符
boolean contains(String regex):判断字符串中是否包含字串regex(自身也算字串)
字符串与其他类型的转换
不管什么类型转为字符串对象,都推荐使用String.valueOf(任意类型参数),当调用自定义类型时会默认调用toString方法进行转换,所以需要我们在自定义类型中覆写toString方法.
将字符串对象转为相应的基本类型:
使用各个包装类的parseXXX方法来进行转换.(这个转换有可能会报错,当转换为数值型变量时字符串中出现非数字会直接报错,当转换为布尔类型时只要字符串不是true就会转为false)
字符串常量池
Java中使用””括起来的字符串称为字符串常量,为了提高程序的运行速度,节省空间,JVM会维护一个字符串常量池
当字符串常量第一次出现,则产生新对象并将该对象置入常量池,若后续再出现该字符串常量则不会产生新对象,直接复用常量池中已有对象,直接赋值法会默认从常量池中取对象
通过构造方法new出的已有字符串对象,只是复制了字符串中常量池中的内容在堆中产生了新对象
Intern方法,入池方法,native本地方法
将手动创建的字符串对象置入常量池,并返回置入常量池后的地址(通过new的方法产生的字符串仍在堆中存储并不会置入常量池)
尝试将当前字符串对象置入常量池;
若常量池中不存在当前对象保存的内容则将当前对象置入常量池,若常量池中已存在当前对象所保存的内容则该方法直接返回常量池中的字符串对象地址
String 不可变
字符串对象一旦产生,这个对象内部的内容就无法再变
探究字符串对象不可变本质的原因
- 在JDK的源代码中String类被final修饰,所以String类没有子类,JDK关闭了String类的拓展功能.保证了String类的所有使用者用的都是同一个类,同一个方法.因此对String类来说没有多态
- 在JDK源代码中,String类保存数据的字符数组引用被private修饰,出了String类对外部完全隐藏,且String类并没有提供任何方法来访问和修改该数组.该数组引用是字符串对象内容的引用,所谓内容不可变实际上指的是字符数组所保存的内容无法被修改;
字符串对象不可变的根本原因:
用于具体存储内容的value数组在String类内部属于私有属性且未提供方法能让外部去访问或修改value数组因此字符串对象一旦产生对象内部的内容就无法被修改
总结:字符串设计成不可变的原因
- 方便实现字符串常量池,
- 不变的对象永远线程安全,不用考虑线程安全问题效率很高
- 不变的对象可以作为哈希表的key值,高效保存在哈希表中
若某些场景下需要频繁修改字符串内容可以使用以下两个类,他们所有的方法名称和具体使用都一模一样但尤其不同处
- StringBuffer:线程安全,效率较低
- StringBuilder:线程不安全效率较高,在不考虑线程安全的情况下优先考虑使用StringBuilder类(String类的”+=”操作在编译器会默认优化为StringBuilder的append方法)
StringBuilder和String是两个独立的类,字符串常量池中储存的都是String对象;
StringBuilder内部是可以修改的(不产生新对象)
String要转换为StringBuilder:
- 通过StringBuilder的构造方法
- 通过append方法