⭐写在前面⭐
🧭Java String类
📢今天我们进行 Java String类 的学习,感谢你的阅读,内容若有不当之处,希望大家多多指正,一起进步💯!!!
♨️如果觉得博主文章还不错,可以👍三连支持⭐一下哦😀
文章目录
- ☘️Java String类详解
- 🍀String类概述
- 🍀理解String的不可变性
- 🍀String的实例化方式
- 🍀String字符串不同拼接操作对比
- 🍀String常用方法
- 🍃int length()
- 🍃char charAt(int index)
- 🍃boolean isEmpty()
- 🍃String toLowerCase()
- 🍃String toUpperCase()
- 🍃String trim()
- 🍃boolean equals(Object obj)
- 🍃boolean equalsIgnoreCase(String anotherString)
- 🍃String concat(String str)
- 🍃int compareTo(String anotherString)
- 🍃String substring(int beginIndex)
- 🍃String substring(int beginIndex,int endIndex)
- 🍃boolean endsWith(String suffix)
- 🍃boolean startWith(String prefix)
- 🍃boolean startWith(String prefix,int toffset)
- 🍃boolean contains(CharSequence s)
- 🍃boolean indexOf(String str)
- 🍃boolean indexOf(String str,int formIndex)
- 🍃boolean lastIndexOf(String str)
- 🍃boolean lastIndexOf(String str,int fromIndex)
- 🍃boolean replace(char oldChar,charNewChar)
- 🍃String[] split(String regex)
- 🍀String与基本数据类型转换
- 🍀String与字符数组转换
- 🍀String与字节数组转换
☘️Java String类详解
🍀String类概述
String
类:代表字符串。Java程序中所有的字符串字面值(如“hello”)都可以作为此类的实例来实现。
String类部分源码
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
}
String
声明为final类,不可被继承。String
类实现了Serializable
接口:表示字符串支持序列化的;实现了Comparable
接口:表示字符串可以比较大小。String
类内部定义了一个被final修饰的char数组value来存储字符串数据,代表其不可变的字符序列,简称不可变性。
🍀理解String的不可变性
代码示例1
@Test
public void test01() {
String s1 = "hello";
String s2 = "hello";
System.out.println("**********************");
System.out.println(s1 == s2);
s1 = "abc";
System.out.println("**********************");
System.out.println(s1);
System.out.println(s2);
}
执行结果:
在示例1中,s1和s2一开始指向同一个对象“hello”(字符串保存在方法区的常量池中)。
后s1又指向“abc”,会先在常量池中看看有没有字符串“abc”,如果有直接指向其地址,没有就先创建字符串“abc”并指向其地址。
代码示例2
@Test
public void test02() {
String s1 = "abc";
String s2 = "abc";
System.out.println("**********************");
System.out.println(s1 == s2);
s1 += "def";
System.out.println("**********************");
System.out.println(s1);
System.out.println(s2);
}
执行结果:
在示例2中,s1和s2一开始指向同一个对象“abc”。
后s2进行拼接操作,得到字符串“abcdef”,底层会先调用StringBuilder(后面会进行详细讲解),创建StringBuilder实例,然后会先常量池中看看有没有字符串“abcdef”,如果有直接指向其地址,没有先在常量池中创建字符串后并指向。
代码示例3
@Test
public void test03() {
String s1 = "abc";
String s2 = s1.replace('a', 'A');
System.out.println("**********************");
System.out.println(s1);
System.out.println(s2);
}
执行结果:
一开始,s1指向常量池中的“abc”
后调用replace方法,替换字符串“abc”中的“a”为“A”,并没有修改原来的字符串,而是在常量池中新创建了一个字符创“Abc”,用引用s2接收。
🚀结论
字符串的不可变性:
🥇当对字符串重新赋值时,需要在常量池中新创建一个字符串对象,不能使用原有的value修改。
🥈当对现有的字符串进行拼接操作时,也需要重新在常量池中新创建一个字符串对象,不能使用原有的value修改。
🥉当调用String的replace()方法修改指定字符或字符串时,也需要重新在常量池中新创建一个字符串对象。
🍀String的实例化方式
String
的实例化的方式一共有两种,一种是通过字面量的方式,一种通过构造器new的方式。
@Test
public void test04() {
//字面量的方式
String s1 = "abc";
String s2 = "abc";
//new的方式
String s3 = new String("abc");
String s4 = new String("abc");
System.out.println("**********************");
System.out.println(s1);
System.out.println(s2);
System.out.println(s3);
System.out.println(s4);
System.out.println("**********************");
System.out.println(s1 == s2);
System.out.println(s1 == s3);
System.out.println(s1 == s4);
System.out.println(s3 == s4);
}
执行结果:
字面量的方式:字面量的方式来实例化,就是直接指向常量池中的地址的,先检查常量池中是否有该字符串,如果有直接指向,如果没有就先创建该字符串后指向该地址。
new + 构造器的方式:众所周知,new
的方式创建对象都是在堆上的,其会先在堆上创建一个String的一个对象,该对象的value属性然后就会在常量池中看看有没有该字符串,如果有直接指向,如果没有就先创建该字符串后指向该地址。
🐣小试牛刀
String s = new String("hello")
在内存中一共会创建几个对象呢?
🐥答:两个,一个是堆中new出来的String类的实例化对象,一个是在常量池中的对象“hello”。
🍀String字符串不同拼接操作对比
代码示例
@Test
public void test05() {
String s1 = "abc";
String s2 = "def";
String s3 = "abcdef";
String s4 = "abc" + "def";
String s5 = s1 + "def";
String s6 = "abc" + s2;
String s7 = s1 + s2;
System.out.println(s3 == s4);
System.out.println(s3 == s5);
System.out.println(s3 == s6);
System.out.println(s3 == s7);
System.out.println(s4 == s5);
System.out.println(s4 == s6);
System.out.println(s4 == s7);
System.out.println(s5 == s6);
System.out.println(s5 == s7);
System.out.println(s6 == s7);
}
执行结果:
通过结果我们发现当涉及到字符串拼接问题时,如果是两个常量拼接并不会创建一个新的对象,
String s4 = "abc" + "def";
和String s3 = "abcdef";
中s4和s3是同一个对象。但是一旦涉及到变量进行拼接的时候就会产生一个新的对象。
🍀String常用方法
🍃int length()
int length(): 返回字符串的长度 return value.length
@Test
public void test01() {
String s = "hello";
int length = s.length();
System.out.println(length);
}
执行结果:
🍃char charAt(int index)
char charAt(int index): 返回某索引处的字符 return value[index]
@Test
public void test02() {
String s = "hello";
char c1 = s.charAt(1);
char c2 = s.charAt(4);
System.out.println(c1);
System.out.println(c2);
}
执行结果
🌳 方法解读
把字符串映射到数组中,下标从0开始,到str.length-1结束,如果参数不在此范围内,会抛出异常。
🍃boolean isEmpty()
boolean isEmpty(): 返回某索引处的字符 return value.length == 0
@Test
public void test03() {
String s1 = "hello";
String s2 = "";
System.out.println(s1.isEmpty());
System.out.println(s2.isEmpty());
}
执行结果:
🍃String toLowerCase()
String toLowerCase(): 使用默认语言环境, 将String中的所有字符转换成小写
@Test
public void test04() {
String s = "HelLO";
String s1 = s.toLowerCase();
System.out.println(s1);
}
🍃String toUpperCase()
String toUpperCase(): 使用默认语言环境, 将String中的所有字符转换成大写
@Test
public void test05() {
String s = "HelLO";
String s1 = s.toUpperCase();
System.out.println(s1);
}
执行结果:
🍃String trim()
String trim(): 忽略 前导空白 和 尾部空白
@Test
public void test06() {
String s = " hell o ";
String trim = s.trim();
System.out.println(trim);
}
执行结果:
🍃boolean equals(Object obj)
boolean equals(Object obj): 比较字符串内容是否相同
@Test
public void test07() {
String s1 = "hello";
String s2 = "hello";
String s3 = "heLLo";
System.out.println(s1.equals(s2));
System.out.println(s1.equals(s3));
}
执行结果:
🍃boolean equalsIgnoreCase(String anotherString)
boolean equalsIgnoreCase(String anotherString): 比较字符串内容是否相同并且忽略大小写
@Test
public void test08() {
String s1 = "hello";
String s2 = "hello";
String s3 = "heLLo";
System.out.println(s1.equalsIgnoreCase(s2));
System.out.println(s1.equalsIgnoreCase(s3));
}
执行结果:
🍃String concat(String str)
String concat(String str): 将指定字符串连接到此字符串的结尾。等价于用“+”
@Test
public void test09() {
String s1 = "hello";
String s2 = s1.concat("world");
System.out.println(s2);
}
执行结果:
🍃int compareTo(String anotherString)
int compareTo(String anotherString): 比较两个字符串的大小
@Test
public void test10() {
String s1 = "abc";
String s2 = "abd";
int i = s1.compareTo(s2);
System.out.println(i);
}
执行结果:
🌳 方法解读
取两个字符串长度的最小值min,以ASCII码值比较两个字符串中前min个字符,如果不相同用前一个字符的ASCII码值 - 后一个字符的ASCII码值作为结果返回,如果前min个字符都完全相同就把前一个字符串的长度 - 后一个字符串的长度作为结果返回。
🍃String substring(int beginIndex)
String substring(int beginIndex): 返回一个新的字符串,它是此字符串的从biginIndex开始截取到最后的一个字符串 。
@Test
public void test11() {
String s1 = "hello";
System.out.println(s1.substring(2));
}
执行结果:
🍃String substring(int beginIndex,int endIndex)
String substring(int beginIndex,int endIndex): 返回一个新的字符串,它是此字符串的从biginIndex开始截取到endIndex(不包含)的一个字符串 。
@Test
public void test12() {
String s1 = "helloworld";
String substring = s1.substring(2, 5);
System.out.println(substring);
}
执行结果:
🌳 方法解读
截取下标从s1.substring(2, 5)
[2,5) 的字符串(不包含5下标)
🍃boolean endsWith(String suffix)
boolean endsWith(String suffix): 测试此字符串是否以指定的后缀结束 。
@Test
public void test13() {
String s1 = "helloworld";
System.out.println(s1.endsWith("ld"));
System.out.println(s1.endsWith("ll"));
}
执行结果:
🍃boolean startWith(String prefix)
boolean startWith(String prefix): 测试此字符串是否以指定的前缀开始 。
@Test
public void test13() {
String s1 = "helloworld";
System.out.println(s1.endsWith("ld"));
System.out.println(s1.endsWith("ll"));
}
执行结果:
🍃boolean startWith(String prefix,int toffset)
boolean startWith(String prefix,int toffset): 测试此字符串是否以从指定索引开始的字符串是否以指定前缀开始 。
@Test
public void test14() {
String s1 = "helloworld";
boolean b = s1.startsWith("low", 3);
System.out.println(b);
}
执行结果:
🍃boolean contains(CharSequence s)
boolean contains(CharSequence s): 当且仅当此字符串包含指定的char值序列时,返回true 。
@Test
public void test15() {
String s1 = "hello";
boolean b = s1.contains("hel");
System.out.println(b);
}
执行结果:
🍃boolean indexOf(String str)
boolean indexOf(String str): 返回指定子字符串在此字符串中第一次出现处的索引,如果没有找到返回-1。
@Test
public void test16() {
String s1 = "ccabccabccabccab";
int i = s1.indexOf("ab");
System.out.println(i);
}
执行结果:
🍃boolean indexOf(String str,int formIndex)
boolean indexOf(String str,): 返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始,如果没有找到返回-1 。
@Test
public void test17() {
String s1 = "ccabccabccabccab";
int i = s1.indexOf("abc", 4);
System.out.println(i);
}
执行结果:
🍃boolean lastIndexOf(String str)
boolean lastIndexOf(String str): 返回指定子字符串在此字符串中最右边出现处的索引,如果没有找到返回-1 。
@Test
public void test18() {
String s1 = "ccabccabccabccab";
int i = s1.lastIndexOf("ab");
System.out.println(i);
}
执行结果:
🍃boolean lastIndexOf(String str,int fromIndex)
boolean lastIndexOf(String str,int fromIndex): 返回指定子字符串在此字符串中最右边出现处的索引,从指定的索引开始反向搜索,如果没有找到返回-1 。
@Test
public void test19() {
String s1 = "ccabccabccabccab";
int i = s1.lastIndexOf("abc",8);
System.out.println(i);
}
执行结果:
🍃boolean replace(char oldChar,charNewChar)
boolean replace(char oldChar,charNewChar): 返回一个新的字符串,它是通过用newChar替换此字符串中所有的oldChar得来的 。
@Test
public void test20() {
String s1 = "ccabccabccabccab";
String s2 = s1.replace("abc", "ABC");
System.out.println(s2);
}
执行结果:
🍃String[] split(String regex)
String[] split(String regex): 根据给定的正则表达式的匹配来拆分此字符串,返回一个字符串数组。
@Test
public void test21() {
String s1 = "ccabccabccabccab";
String[] str = s1.split("a");//以 "a" 拆分字符串
System.out.println(Arrays.toString(str));
}
执行结果:
🍀String与基本数据类型转换
🍃字符串➡️基本数据类型,包装类
🌻
Integer
包装类的public static int parseInt(String s)
:可以将数字字符组成的字符串转换为整型。
🌻类似地,使用java.long包中的Byte
、Short
、Long
、Float
、Double
类调相应的类方法可以将由数字字符组成的字符串转换为相应的基本数据类型。
@Test
public void test22() {
String s = "123456";
int i = Integer.parseInt(s);
System.out.println(i);
}
执行结果:
🍃基本数据类型,包装类➡️字符串
🌻 调用
String
类的public static String valueOf(int n)
可将int类型转换为字符串。
🌻相应的valueOf(byte b)
、valueOf(long l)
、valueOf(float f)
、valueOf(double d)
、valueOf(boolean b)
可由参数的相应类型到字符串的转换。
@Test
public void test23() {
int n = 123456;
String s = String.valueOf(n);
System.out.println(s);
System.out.println(s.getClass());
}
执行结果:
🍀String与字符数组转换
🍃字符数组➡️字符串
🌻 String类的构造器:
String(char[])
和String(char[]
,int offset,int int count)分别用字符数组中的全部字符和部分字符。
@Test
public void test24() {
char[] arr = {'a', 'b', 'c', 'd', 'e', 'f'};
String s1 = new String(arr);
String s2 = new String(arr, 2, 3);
System.out.println(s1);
System.out.println(s2);
}
执行结果:
🍃字符串➡️字符数组
🌻 String类的构造器:
String(char[])
和String(char[],int offset,int int count)
分别用字符数组中的全部字符和部分字符。
@Test
public void test25() {
String s = "helloworld";
char[] charArray = s.toCharArray();
System.out.println(Arrays.toString(charArray));
}
执行结果:
🍀String与字节数组转换
🍃字节数组➡️字符串
🌻
String(byte[])
:通过使用平台的默认字符集解码指定的字符数组,构成一个新的字符串对象。
🌻String(byte[],int offset,int length)
:用指定字节数组的一部分,即从数组的其实位置offset开始取length个字节构造一个字符串对象。
@Test
public void test26(){
byte[] byteArray = {97, 98, 99};
String s = new String(byteArray);
System.out.println(s);
}
执行结果:
🍃字符串➡️字节数组
@Test
public void test27(){
String s = "abc";
byte[] bytes = s.getBytes();
System.out.println(Arrays.toString(bytes));
}
执行结果: