1. 介绍
Java中的String属于引用数据类型,Java专门在堆中准备了一个字符串常量池。我们在开发时,字符串使用的频率是很高的,因此将这些字符串放在常量池中可以省去对象的创建过程,提高效率。常量池属于一种缓存技术,缓存技术是一种可以提高程序执行效率的手段。
String s1 = “hello”;
String s2 = “hello”;
System.out.println(s1 == s2); //这里输出的结果是true,说明两者指向的是同一个对象
注:字符串字面量在编译时就已经确定了将其放到字符串常量池中,JVM在会将字符串全部放入字符串常量池。
字符串一旦创建是不可变的。查看源码后发现是因为其前面使用了final修饰。这里的不可变指的是字面量不能变,就比如String s1 = “hello”;这里的 “hello”就不能变为"hello2025",如果使用了字符串拼接操作之后,常量池中会存在“hello”和"hello2025",可以看到原先的 “hello”还是 “hello”,只不过创建了一个新的对象 “hello2025”。其次s1的指向是可以变得,可以从原先指向 “hello”,变成指向 “hello2025”。
上图是String的源码,这里有两个final:
- 第一个final,这里的final不是字符串不可变的原因,这里的final是说明String这个类不能被继承了
- 第二个final,这里的final才是字符串不可变的原因,这里的final说明在字符串创建时,就已经确定了数组的大小,前面加了final修饰之后,说明这个数组就不可变了。而且前面还有private修饰,private修饰的东西外部不能进行操作,这样从外部也无法进行改变。
2. 字符串的拼接
//这段代码运行的结果为false,需要注意的是使用+号进行字符串拼接时,拼接好的字符串不会放入字符串常量池中,而是会放在堆中
//底层原因是因为,使用+号进行操作时
//底层会创建一个StringBuilder对象来进行字符串的拼接,拼接完成之后使用toString()转换为String对象
String s1 = “abc”;
String s2 = “def”;
String s3 = s1 + s2;
String s4 = “abcdef”;
System.out.println(s3 == s4); //false
//这里有一个方法intern(),这个方法的作用可以将字符串对象加入字符串常量池中
String ss3 = s3.intern();
System.out.println(ss3 == s3); //true
//这里运行的结果为true
//是因为进行创建时,在编译阶段就会进行拼接,然后存入字符串常量池中
//此时在字符串常量池中,没有“aaa”,也没有“bbb”,只有“aaabbb”
//注意点,只有+两边都是字面量的时候,才是这样,一旦有一边不是字面量,则就属于上面的情况
String s5 = “aaa” + “bbb”; //相当于String s5 = “aaabbb”;
String s6 = “aaabbb”;
System.out.println(s5 == s6); //true
3. 常用的构造方法
方法 | 描述 |
---|---|
String(byte[] bytes) | 根据字节数组创建一个新的字符串对象,默认使用平台默认的字符集进行解码 |
String(byte[] bytes, int offset, int length) | 根据字节数组的指定部分创建一个新的字符串对象,默认使用平台默认的字符集进行解码 |
String(byte[] bytes, String charsetName) | 根据字节数组和指定的字符集名称创建一个新的字符串对象 |
String(byte[] bytes, Charset charset) | 根据字节数组和指定的字符集创建一个新的字符串对象 |
String(char[] value) | 根据字符数组创建一个新的字符串对象 |
String(char[] value, int offset, int count) | 根据字符数组的指定部分创建一个新的字符串对象 |
String(String original) | 通过复制现有字符串创建一个新的字符串对象 |
示例:
//String(byte[] bytes) | 根据字节数组创建一个新的字符串对象,默认使用平台默认的字符集进行解码
byte[] b1 = {97, 98, 99};
String s1 = new String(b1);
System.out.println(s1);
//String(byte[] bytes, int offset, int length) | 根据字节数组的指定部分创建一个新的字符串对象,默认使用平台默认的字符集进行解码
byte[] b2 = {97, 98, 99, 100, 101, 102};
String s2 = new String(b2, 1, 3);
System.out.println(s2);
//String(byte[] bytes, String charsetName) | 根据字节数组和指定的字符集名称创建一个新的字符串对象
byte[] b3 = {97, 98, 99, 100, 101, 102};
String s3 = new String(b3, 1, 3, "UTF-8");
System.out.println(s3);
//String(byte[] bytes, Charset charset) | 根据字节数组和指定的字符集创建一个新的字符串对象
byte [] b4 = {97, 98, 99, 100, 101, 102};
String s4 = new String(b4, 1, 3, Charset.defaultCharset());
System.out.println(Charset.defaultCharset());
System.out.println(s4);
//String(char[] value) | 根据字符数组创建一个新的字符串对象
char[] c1 = {'a','b','c'};
String s5 = new String(c1);
System.out.println(s5);
//String(char[] value, int offset, int count) | 根据字符数组的指定部分创建一个新的字符串对象
char[] c2 = {'a', 'b', 'c', 'd', 'e', 'f'};
String s6 = new String(c2, 1, 3);
System.out.println(s6);
//String(String original) | 通过复制现有字符串创建一个新的字符串对象
//被@IntrinsicCandidate标注,这个注解的作用是告诉编译器,
//该方法或构造函数是一个内在的候选方法,可以被优化和替换为更高效的代码。因此它是不建议使用的
String s7 = new String(s6);
System.out.println(s7);
输出结果为:
4. 常用的方法
这里的常用方法很多,因此就不用表格列举出来了, 直接在代码里列出示例
//charAt(int index):返回索引处的char值
String s = "hello world";
char c = s.charAt(0);
System.out.println(c); //h
//length():获取字符串长度
String s1 = "hello world";
int len = s1.length();
System.out.println(len); //11
//isEmpty():判断字符串是否为空
String s2 = "";
boolean b = s2.isEmpty();
System.out.println(b); //true
String s3 = "hello world";
boolean b1 = s3.isEmpty();
System.out.println(b1); //false
//equals(Object anObject):判断两个字符串是否相等
String s4 = "hello world";
String s5 = "hello world";
boolean b2 = s4.equals(s5);
System.out.println(b2); //true
//equalsIgnoreCase(String anotherString):判断两个字符串是否相等,忽略大小写
String s6 = "hello world";
String s7 = "HELLO WORLD";
boolean b3 = s6.equalsIgnoreCase(s7);
System.out.println(b3); //true
//contains(CharSequence s):判断当前的字符串中是否包含某个子字符串
String s8 = "hello world";
boolean b4 = s8.contains("hello");
System.out.println(b4); //true
//startsWith(String prefix): 判断当前字符串是否以某个字符串开头
String s9 = "hello world";
boolean b5 = s9.startsWith("hello");
System.out.println(b5); //true
//endsWith(String suffix):判断当前字符串是否以某个字符串结尾
String s10 = "hello world";
boolean b6 = s10.endsWith("world");
System.out.println(b6); //true
//compareTo(String anotherString):两个字符串按照字典顺序比较大小
String s11 = "apple";
String s12 = "banana";
int comparison = s11.compareTo(s12);
System.out.println(comparison); // -1
//compareToIgnoreCase(String str):两个字符串比较大小,忽略大小写
String s13 = "APPLE";
int comparisonIgnoreCase = s11.compareToIgnoreCase(s13);
System.out.println(comparisonIgnoreCase); // 0
//indexOf(String str): 获取当前字符串中str字符串的第一次出现时的下标
String s14 = "hello world";
int index = s14.indexOf("world");
System.out.println(index); //6
//indexOf(String str, int fromIndex):从当前字符串的fromIndex下标开始往右搜索,获取当前字符串中str字符串的第一次出现处的下标
String s15 = "hello world";
int index1 = s15.indexOf("world", 5);
System.out.println(index1); //6
//lastIndexOf(String str):获取当前字符串中str字符串的最后一次出现处的下标
String s16 = "hello world";
int lastIndex = s16.lastIndexOf("o");
System.out.println(lastIndex); //7
//lastIndexOf(String str, int fromIndex):从当前字符串的fromIndex下标开始往左搜索,获取当前字符串中str字符串的最后一次出现处的下标
int lastIndex1 = s16.lastIndexOf("o", 6);
System.out.println(lastIndex1); //4
//getBytes():将字符串转换成字节数组。默认按照系统默认字符集
byte[] bytes = s16.getBytes();
System.out.println(Arrays.toString(bytes)); // [104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]
//getBytes(String charsetName):将字符串按照指定字符集的方式进行编码
byte[] bytesWithCharset = s16.getBytes("UTF-8");
System.out.println(Arrays.toString(bytesWithCharset)); // [104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]
//getBytes(Charset charset):将字符串按照指定字符集的方式进行编码
byte[] bytesWithCharset4 = s16.getBytes(Charset.defaultCharset());
System.out.println(Arrays.toString(bytesWithCharset4)); // [104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]
//toCharArray():将字符串转换字符数组
char[] charArray = s16.toCharArray();
System.out.println(Arrays.toString(charArray)); // [h, e, l, l, o, , w, o, r, l, d]
//toLowerCase():转小写
String s17 = s16.toLowerCase();
System.out.println("Lowercase: " + s17); // Lowercase: hello world
//toUpperCase():转大写
String s18 = s16.toUpperCase();
System.out.println("Uppercase: " + s18); // Uppercase: HELLO WORLD
//concat(String str):进行字符串的拼接操作
//concat方法参数只能时字符串类型,拼接时不会创建StringBuilder对象
//拼接完成后返回一个新的String对象。拼接null会出现空指针异常
String s19 = s16.concat("!!!");
System.out.println(s19); //hello world!!!
//substring(int beginIndex):从指定下标beginIndex开始截取子字符串
String s20 = s19.substring(7);
System.out.println(s20); //orld!!!
//substring(int beginIndex, int endIndex):从指定开始下标和结束下标开始截取字符串,类似区间的左闭右开
String s21 = s19.substring(3,5);
System.out.println(s21); //lo
//trim():去除字符串前后空白(只能去除ASCII码中的空格和制表符)
String s22 = " Hello, World! ";
String s23 = s22.trim();
System.out.println(s22); // Hello, World!
System.out.println(s23); //Hello, World!
//strip():去除字符串前后空白,支持所有的编码形式的空白,可以将全角空格去除,\u3000是全角空格
String s24 = s22.strip();
System.out.println(s24); //Hello, World!
//stripLeading():去除前空白
String s25 = s22.stripLeading();
System.out.println(s25); //Hello, World!
//stripTrailing(): 去除后空白
String s26 = s22.stripTrailing();
System.out.println(s26); // Hello, World!
/**
* 以下是一些静态方法,作用都是将非字符串类型的数据转换为字符串形式
* valueOf(boolean b)
* valueOf(char c)
* valueOf(char[] data)
* valueOf(char[] data, int offset, int count)
* valueOf(double d)
* valueOf(float f)
* valueOf(int i)
* valueOf(long l)
* valueOf(Object obj)
*/
String booleanStr = String.valueOf(true);
System.out.println(booleanStr); //true
String charStr = String.valueOf('a');
System.out.println(charStr); //a
String charArrayStr = String.valueOf(new char[] {'H', 'e', 'l', 'l', 'o'});
System.out.println(charArrayStr); //Hello
String charArrayStr2 = String.valueOf(new char[] {'H', 'e', 'l', 'l', 'o'}, 1, 3);
System.out.println(charArrayStr2); //ell
String doubleStr = String.valueOf(1.23);
System.out.println(doubleStr); //1.23
String floatStr = String.valueOf(1.23f);
System.out.println(floatStr); //1.23
String intStr = String.valueOf(123);
System.out.println(intStr); //123
String longStr = String.valueOf(123L);
System.out.println(longStr); //123
String objectStr = String.valueOf(new Object());
System.out.println(objectStr); //java.lang.Object@1b6d3586
这里的方法虽然很多,但是用法都挺简单的,有时间可以看着做个了解。