String类不能被继承
通过源码可以看到String类前面加了final修饰,因此String类是不能够被继承的。将其设置为不能被继承的原因是为了减少歧义。
字符串(String)的不可变性
String创建好之后值是不可以被改变的,这里指的是在堆中的字符串的值是不可以被改变。
示例:
String是引用数据类型,但是这里作为方法参数传递的时候,效果跟基本数据类型是一样的。也就是说在堆中创建出来的字符串”monkey”是不能被改变的,如果要修改,系统会在堆中重新开辟内存空间将”good”放入,然后将change方法中的s重新引用这个新的内存地址上的”good”。
String不可变的主要原因是其底层使用了一个final修饰的byte数组(jdk9之后版本中),final修饰的变量是不能被改变的。在jdk8版本中,String底层使用的是final修饰的char数组。这个版本之间的变化。
字符串常量池
我们声明的字符串会放到一个叫做字符串常量池的地方,这样可以减少内存的使用,字符串常量池是堆的一部分。
上面代码中,创建s1时,字符串常量池中还不存在堆中monkey的引用,因此jvm会在常量池中创建一个引用指向堆中的这个字符串对象,创建s2时,jvm会去常量池中搜索,此时常量池中有monkey的引用,所以就不创建了,直接让s2指向之前创建的monkey,所以s1和s2指向的是同一个堆内存中的对象。
创建s3时,因为使用了new关键字,所以会在堆中开辟一块内存地址将其放入,s3指向这个新的内存地址,所以s3和s1指向的不是同一个内存地址。
创建s4时,使用了new关键字,会在堆中开辟一块内存地址,s4指向这个内存地址,然后字符串常量池中没有指向good的引用,所以会再重新开辟一块空间,将good放入,然后在字符串常量池中指向这个地址。
开发中建议使用String s = “monkey1024”;这种方式创建字符串对象,可以减少堆内存的使用。
注意:比较两个字符串是否一致最好使用equals方法。
String类常用方法
char charAt(int index);获取index位置的字符
boolean contains(CharSequence s);判断字符串中是否包含某个字符串
boolean endsWith(String endStr);判断是否是以某个字符串结尾
boolean equalsIgnoreCase(String anotherString);忽略大小写比较两个字符串是否相等
byte[] getBytes();转换成byte数组
int indexOf(String str);取得指定字符在字符串的位置
int indexOf(String str, int fromIndex);从指定的下标开始取得指定字符在字符串的位置
int lastIndexOf(String str);从后面开始取得指定字符在字符串最后出现的的位置
int length();获取字符串的长度
String replaceAll(String s1,String s2);替换字符串中的内容
String[] split(String s);根据指定的表达式拆分字符串
boolean startsWith(String s);判断是否是以某个字符串开始
String substring(int begin);根据传入的索引位置截子串
String substring(int beginIndex, int endIndex);根据传入的起始和结束位置截子串
char[] toCharArray();将字符串转换为char数组
void toUpperCase();转换为大写
void toLowerCase();转换为小写。
String trim();去除首尾空格。
String valueOf(Object obj);将其他类型转换为字符串类型。