一、基本用法
字符串是Java中特殊的类,使用方法像基本数据类型,被广泛应用在Java编程中。Java没有内置的字符串类型,而是在标准Java类库中提供了一个String类来创建和操作字符串。String是不可变的,因为该类中使用final关键字修饰字符数组来保存字符串,即private final char value[]。
常用方法 |
功能 |
indexOf() |
返回指定字符的索引 |
charAt() |
返回指定索引的字符 |
subString() |
截取字符串 |
split() |
分割字符,返回字符数组 |
length() |
返回字符串长度 |
getByte() |
返回字符串的byte类型数组 |
toLowerCase |
转为小写字母 |
toUpperCase |
转为大写字母 |
trim() |
去除字符串两端空白 |
equal() |
字符串比较 |
(一) 字符串定义
// 1.直接定义字符串 String s1 = "fuxing"; // 2.使用String类定义 String s2 = new String("fuxing");
1. 区别
第一种方式是先检验字符串常量中有没有"fuxing",如果字符串常量池中没有,则创建一个,然后用s1指向常量池中的对象,有则直接指向。
第二种方式是直接在堆内存空间创建一个新的对象。
且s1和s2并不相等,一个是堆内存的String对象,一个是常量池中的String对象
(二) new String("fuxing")到底创建了几个对象?
通过 new 创建字符串的方式可能会创建 1 个或 2 个对象,如果常量池中已经存在此字符串只会在堆上创建一个变量,并指向字符串常量池中的值,如果字符串常量池中没有相关的字符,会先创建字符串在返回此字符串的引用给堆空间的变量
(三) String和int相互转换
【String转int】
在 String转换int时,String的值一定是整数,否则会报数字转换异常(java.lang.NumberFormatException)。
public static void main(String[] args) { String str = "123"; int n = 0; // 第一种转换方法:Integer.parseInt(str) n = Integer.parseInt(str); System.out.println(n); // 123 // 第二种转换方法:Integer.valueOf(str).intValue() n = 0; n = Integer.valueOf(str).intValue(); System.out.println(n); // 123 }
【int转String】
public static void main(String[] args) { int num = 10; // 第一种方法:String.valueOf(i); 注意:参数i不能为空,否则会报空指针异常(NullPointerException) num = 10; String str = String.valueOf(num); System.out.println("str:" + str); // 第二种方法:Integer.toString(i); num = 10; String str2 = Integer.toString(num); System.out.println("str2:" + str2); // 第三种方法:"" + i; String str3 = num + ""; System.out.println("str3:" + str3); }
(四) 去除字符串中的空格
String str = " hello "; //hello两边时空格 System.out.println(str.length()); // 输出 7 System.out.println(str.trim().length()); // 输出 5
(五) 截取字符串
【从索引位置开始至结尾】
public static void main(String[] args) { String str = "12345"; String result = str.substring(3); System.out.println(result); // 输出:45 }
【截取指定范围】
public static void main(String[] args) { String str = "12345"; // 起始索引从0开始,终止索引从1开始 String result = str.substring(1,3); System.out.println(result); // 输出:23 }
(六) 分割字符串
public static void main(String[] args) { String Colors = "Red,Black,White,Yellow,Blue"; String[] arr1 = Colors.split(","); // 不限制元素个数 String[] arr2 = Colors.split(",", 3); // 限制元素个数为3 System.out.println("所有颜色为:"); for (int i = 0; i < arr1.length; i++) { System.out.println(arr1[i]); } System.out.println("前三个颜色为:"); for (int j = 0; j < arr2.length; j++) { System.out.println(arr2[j]); } }
二、StringBuffer & StringBuilder
(一) StringBuffer
【创建方式】
// 1.定义一个空的字符串缓冲区,含有16个字符的容量 StringBuffer str1 = new StringBuffer(); // 2.定义一个含有10个字符容量的字符串缓冲区 StringBuffer str2 = new StringBuffer(10); // 3.定义一个含有(16+4)的字符串缓冲区,"福星高照"为4个字符 StringBuffer str3 = new StringBuffer("福星高照"); // capacity()方法返回字符串的容量大小 System.out.println(str1.capacity()); // 输出 16 System.out.println(str2.capacity()); // 输出 10 System.out.println(str3.capacity()); // 输出 20
【追加字符串】
StringBuffer buffer = new StringBuffer("hello"); // 创建一个 StringBuffer 对象 String str = "World"; buffer.append(str); // 向StringBuffer对象追加str字符串到末尾,类似于字符串的连接 System.out.println(buffer.substring(0)); // HelloWorld
【其他常用方法】
StringBuffer sb = new StringBuffer("hello"); // 1.替换字符 sb.setCharAt(1,'E'); System.out.println(sb); // 输出:hEllo // 2.反转字符串 sb.reverse(); System.out.println(sb); // 输出:olleh // 3.删除字符串 sb.deleteCharAt(2); System.out.println(sb); // 输出:helo
(二) String、StringBuffer和StringBuilder的对比
【StringBuilder】
StringBuilder类是 JDK 1.5 新增的类,它也代表可变字符串对象。实际上,StringBuilder和StringBuffer功能基本相似,方法也差不多。不同的是,StringBuffer是线程安全的,而StringBuilder则没有实现线程安全功能,所以性能略高。因此在通常情况下,如果需要创建一个内容可变的字符串对象,则应该优先考虑使用StringBuilder类。
【三者关联】
三者都实现 CharSequence接口。CharSequence是一个定义字符串操作的接口,它只包括length()、charAt(int index)、subSequence(int start, int end) 这几个 API。
【三者区别】
对比方向 |
String |
StringBuffer |
StringBuilder |
线程安全性 |
安全(可理解为常量) |
安全(对方法或调用的方法加了同步锁) |
非线程安全 |
性能 |
最低(每次改变生成新的对象) |
正常(仅对本身进行操作,不会创建) |
较快 |
适用场景 |
操作少量的数据 |
多线程下操作大量字符串 |
单线程下操作大量字符串 |
三、注意事项
(一) String 有长度限制吗?是多少?
https://blog.csdn.net/weixin_59624686/article/details/131560058
1. 编译时限制:65534
我们知道字符串常量会被放入方法区的常量池中,JVM 规范对常量池有所限制。常量池中的每一种数据项都有自己的类型。Java 中的 UTF-8 编码的 Unicode 字符串在常量池中以CONSTANT_Utf8 类型表示。
CONSTANT_Utf8的数据结构如下:
CONSTANT_Utf8_info { u1 tag; u2 length; u1 bytes[length]; }
我们重点关注下长度为 length 的那个 bytes 数组,这个数组就是真正存储常量数据的地方,而 length 就是数组可以存储的最大字节数。length 的类型是 u2,u2 是无符号的 16 位整数,因此理论上允许的的最大长度是 2^16-1=65535。但是由于 JVM 需要 1 个字节表示结束指令,所以编译时 String 最大长度不能超过 65534。
2. 运行时限制:231-1
字符串的内容是由一个字符数组 char[] 来存储的,由于数组的长度及索引是整数,且 String 类中返回字符串长度的方法 length() 的返回值也是 int ,所以通过查看 java 源码中的类 Integer 我们可以看到 Integer 的最大长度不能超过 2^31 -1。
但是这个也是理论上的长度,实际的长度还要看你JVM的内存。最大的字符串会占用多大的内存为 4GB。计算方式如下:
(2^31-1)*2*16/8/1024/1024/1024 = 4GB
所以在最坏的情况下,一个最大的字符串要占用4GB的内存。如果你的虚拟机不能分配这么多内存的话,会直接报错的。
JDK9 以后对 String 的存储进行了优化。底层不再使用 char 数组存储字符串,而是使用 byte 数组。对于 LATIN1 字符的字符串可以节省一倍的内存空间。