24.1.String类的细节
- 字符串的字符使用 Unicode字符编码,一个字符(不区分字母还是汉字)占两个字节
- String类常用构造器
String s1 = new String();
String s2 = new String(String original); 常量
String s3 = new String(char[] a);
String s4 = new String(char[] a,int startIndex,int count);
- String 是 final 类,不能被其他的类继承
- String 有属性
private final char value[];
用于存放字符串内容
注意:value 是一个 final 类型,不能指向新的地址,但是单个字符内容是可以变化的
- String 类实现了接口
Serializable
说明String可以串行化,可以在网络运输;实现了接口Comparable
说明String对象可以比较大小
24.2.两种创建String
方式一:直接赋值 String s1 = "cyx";
先从常量池查看是否有"cyx"数据空间,如果有,直接指向;如果没有则重新创建,然后指向。s1最终指向的是 常量池 的空间地址
方式二:调用构造器String s2 = new String("cyx");
先在堆中创建空间,里面维护了 value属性,指向常量池的cyx空间。如果常量池没有 “cyx”,重新创建,如果有,直接通过 value指向。s2最终指向的是 堆 中的空间地址。
24.3.实例理解
String a = "cyx";
a指向常量池的 “cyx”
String b = new String("cyx");
b指向堆中对象
System.out.println(a.equals(b));
输出 true,内容比较
System.out.println(a==b);
输出 false,地址比较
System.out.println(a==b.intern());
输出 true,都指向常量池
当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(用 equals(Object)方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并返回此 String 对象的引用
b.intern()
方法最终返回的是常量池的地址(对象)
System.out.println(b==b.intern());
输出 false,地址不同
24.4.字符串的特性
- String是一个final类,代表不可变的字符序列
- 字符串是不可变的。一个字符串对象一旦被分配,其内容是不可变的,即创建后放入常量池,不会被更改。
例子:
以下语句创建了几个对象:
- 。
String s1 = "hello";
s1 = "haha";
共创建了 2 个对象,在常量池里创建了"hello"和"haha"两个字符串对象,s1先指向"hello"对象,后指向"haha"对象
String a = "hello" + "abc";
创建了 1 个对象,编译器会做一个优化,判断创建的常量池对象是否有引用指向,若没有,则会
String a = "hello" + "abc"; --> String a = "helloabc";
创建一个对象
String a = "hello"; //创建 a对象
String b = "abc"; //创建 b对象
String c = a + b;
创建了 3 个对象,底层是
String sb = new StringBuilder(); sb.append(a); sb.append(b);
sb是在堆中,并且append是在原来字符串的基础上追加的。
24.5.String类的常见方法
equals()
:区分大小写,判断内容是否相等equalsIgnoreCase()
:忽略大小写的判断内容是否相等length()
:获取字符的个数,字符串的长度indexOf()
:获取字符在字符串中第1次出现的索引,索引从0开始,如果找不到,返回 -1lastIndexOf
:获取字符在字符串中最后1次出现的索引,索引从0开始,如找不到,返回 -1substring()
:截取指定范围的子串trim()
:去前后空格charAt()
:获取某索引处的字符,注意不能使用 Str[index] 这种方式,区别于C++toUpperCase()
:全部转换成大写toLowerCase()
:全部转换成小写concat()
:拼接字符串,只能用于字符串的拼接
在String类中,字符串拼接既可以使用concat方法,也可以直接用连接符 + 进行连接,两者的异同点:
相同点1:concat方法 和直接用 “+” 连接符拼接都可以对两个字符串进行拼接。
相同点2:两种拼接方法都会重新形成一个新的字符串,这是因为字符串的内容永远不可变,所以拼接一定会形成一个新的字符串。
不同点:concat只能拼接字符串;但是"+“连接符可以将字符串与非字符串类型拼接到一起(注意:只要两个当中有一个是字符串类型,用”+"连接符就会拼接成一个新的字符串)
除此之外,当我们生成一个class文件,再进行反编译的时候,通过concat源码可以发现,用连接符 + 进行连接,StringBuilder创建了更多的对象,而concat却没有,它使用的String类的内部实现。
总结:当进行两个字符串连接的时候,我们应该优先考虑用 concat() 函数。
当需要连接字符串和其他非字符串类型的变量的时候,cancat无法满足需求,我们就要优先考虑使用 “+” 连接运算符。
参考自:https://blog.csdn.net/wtt15100/article/details/108014448
replace()
:替换字符串中的字符
方法执行后,返回的结果才是替换过的,对自身执行的变量没有任何影响
split()
:分割字符串,返回一个数组toCharArray()
:转换成字符数组compareTo()
:比较两个字符串的大小,如果前者大,则返回正数;后者大,则返回负数;如果相等,返回0
- 如果长度相同,并且每个字符也相同,就返回 0
- 如果长度相同或者不相同,但是在进行比较时,可以区分大小,就返回
if (c1 != c2) { return c1 - c2; }
- 如果前面的部分都相同,就返回
str1.len - str.len
format()
:格式字符串
%s
,%d
,%.2f
,%c
称为占位符- 这些占位符由后面变量来替换
%s
表示后面由 字符串来替换%d
是整数来替换%.2f
表示使用小数来替换,替换后,只会保留小数点两位,并且进行四舍五入的处理%c
使用char 类型来替换
String formatStr = "我的姓名是%s 年龄是%d 有%.2f元钱";
String info = String.format(formatStr,name,age,price);