String的特性
- String类:代表字符串。Java 程序中的所有字符串字面值(如 “abc” )都作为此类的实例实现。
- String是一个final类,代表不可变的字符序列。
- 字符串是常量,用双引号引起来表示。它们的值在创建之后不能更改。
- String对象的字符内容是存储在一个字符数组value[]中的。
/**
* String 字符串使用""来表示
* 1.String被声明为final,不能被继承。
* 2.String实现了serializable接口,表示字符串支持序列化
* 实现了Comparable接口,表示字符串可比较大小
* 3.String内部定义了final char[] value用于存储字符串数据
* 4.String代表不可变的字符串序列 即不可变性:
* 体现:1.当对字符串重新赋值时,需重写指定内存区域值,不能使用原有的value进行赋值
* 2.当对现有的字符串进行连接操作时,也需要指定内存区域进行赋值,不能使用原有的value进行赋值
* 5.通过字面量赋值的方式(区别于new)给一个字符串赋值,此时的字符串值声明在字符串常量池中
* 6.常量池中不会存储相同内容的字符串。
*/
//不可变性
@Test
public void stringTest(){
String s1 = "abc";//字面量的定义方式
String s2 = "abc";
System.out.println(s1 == s2);//true
s1 = "hello";
System.out.println(s1);//hello
System.out.println(s2);//abc
System.out.println("-------------------");
String s3 = "abc";
s3 += "def";
System.out.println(s3);//abcdef
System.out.println("------------");
String s4 = "abc";
String s5 = s4.replace("a","m");
System.out.println(s4);
System.out.println(s5);
System.out.println(System.identityHashCode(s4));//打印s4的内存地址
System.out.println(System.identityHashCode(s5));
}
String对象的创建
String str = "hello";
//本质上this.value = new char[0];
String s1 = new String();
//this.value = original.value;
String s2 = new String(String original);
//this.value = Arrays.copyOf(value, value.length);
String s3 = new String(char[] a);
String s4 = new String(char[] a,int startIndex,int count);
/**
* String的实例化方式:
* 一:通过字面量定义的方式;
* 二:通过new + 构造器的方式;
*/
@Test
public void testDefine(){
//通过字面量定义的方式:此时s1和s2的数据javaEE声明在方法区中的常量池中。
String s1 = "javaEE";
String s2 = "javaEE";
//通过new+构造器的方式:此时s3和s4的数据保存地址是在堆空间中开辟空间以后对应的地址值。
String s3 = new String("javaEE");
String s4 = new String("javaEE");
System.out.println(s1 == s2);//true
System.out.println(s1 == s3);//false
System.out.println(s1 == s4);//false
System.out.println(s3 == s4);//false
System.out.println("----------------");
Person p1 = new Person("tom", 12);
Person p2 = new Person("tom", 12);
System.out.println(p1.name.equals(p2.name));//true
System.out.println(p1.name == p2.name);//true
}
字符串对象是如何存储的
字符串拼接方面
/**
* 结论:
* 常量与常量的拼接结果在常量池。且常量池中不会存在相同内容的常量。
* 只要其中有一个是变量,结果就在堆中
* 如果拼接的结果调用intern()方法,返回值就在常量池中
*/
@Test
public void testPinJie(){
String s1 = "javaEE";
String s2 = "hadoop";
String s3 = "javaEEhadoop";
String s4 = "javaEE"+"hadoop";
String s5 = s1 + "hadoop";
String s6 = "javaEE" + s2;
String s7 = s1 + s2;
System.out.println(s1 == s2);//false
System.out.println(s3 == s4);//true
System.out.println(s3 == s5);//false
System.out.println(s3 == s6);//false
System.out.println(s5 == s6);//false
System.out.println(s3 == s7);//false
System.out.println(s5 == s7);//false
System.out.println(s6 == s7);//false
//intern方法将返回值强制放在常量池
String s8 = s5.intern();
System.out.println(s3 == s8);//true
}
String类的常用方法:
-
int length():返回字符串的长度: return value.length
-
char charAt(int index): 返回某索引处的字符return value[index]
-
boolean isEmpty():判断是否是空字符串:return value.length==0
-
String toLowerCase():使用默认语言环境,将 String 中的所有字符转换为小写
-
String toUpperCase():使用默认语言环境,将 String 中的所有字符转换为大写
-
String trim():返回字符串的副本,忽略前导空白和尾部空白
-
boolean equals(Object obj):比较字符串的内容是否相同
-
boolean equalsIgnoreCase(String anotherString):与equals方法类似,忽略大小写
-
String concat(String str):将指定字符串连接到此字符串的结尾。 等价于用“+”
-
int compareTo(String anotherString):比较两个字符串的大小
-
String substring(int beginIndex):返回一个新的字符串,它是此字符串的从
-
beginIndex开始截取到最后的一个子字符串。
-
String substring(int beginIndex,int endIndex) :返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串。
-
boolean endsWith(String suffix):测试此字符串是否以指定的后缀结束
-
boolean startsWith(String prefix):测试此字符串是否以指定的前缀开始
-
boolean startsWith(String prefix, int toffset):测试此字符串从指定索引开始的 子字符串是否以指定前缀开始
-
boolean contains(CharSequence s):当且仅当此字符串包含指定的 char 值序列时,返回 true
-
int indexOf(String str):返回指定子字符串在此字符串中第一次出现处的索引
-
int indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出 现处的索引,从指定的索引开始
-
int lastIndexOf(String str):返回指定子字符串在此字符串中最右边出现处的索引
-
int lastIndexOf(String str, int fromIndex):返回指定子字符串在此字符串中最后 一次出现处的索引,从指定的索引开始反向搜索 注:indexOf和lastIndexOf方法如果未找到都是返回-1
-
String replace(char oldChar, char newChar):返回一个新的字符串,它是 通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
-
String replace(CharSequence target, CharSequence replacement):使 用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。
-
String replaceAll(String regex, String replacement) : 使 用 给 定 的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
-
String replaceFirst(String regex, String replacement) : 使 用 给 定 的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。
-
boolean matches(String regex):告知此字符串是否匹配给定的正则表达式。
-
String[] split(String regex):根据给定正则表达式的匹配拆分此字符串。
-
String[] split(String regex, int limit):根据匹配给定的正则表达式来拆分此字符串,最多不超过limit个,如果超过了,剩下的全部都放到最后一个元素中。
/**
* - int length():返回字符串的长度: return value.length
* - char charAt(int index): 返回某索引处的字符return value[index]
* - boolean isEmpty():判断是否是空字符串:return value.length==0
* - String toLowerCase():使用默认语言环境,将 String 中的所有字符转换为小写
* - String toUpperCase():使用默认语言环境,将 String 中的所有字符转换为大写
* - String trim():返回字符串的副本,忽略前导空白和尾部空白 (用户名密码除空格)
* - boolean equals(Object obj):比较字符串的内容是否相同
* - boolean equalsIgnoreCase(String anotherString):与equals方法类似,忽略大小写
* - String concat(String str):将指定字符串连接到此字符串的结尾。 等价于用“+”
* - int compareTo(String anotherString):比较两个字符串的大小
* - String substring(int beginIndex):返回一个新的字符串,它是此字符串的从
* - beginIndex开始截取到最后的一个子字符串。
* - String substring(int beginIndex,int endIndex) :返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串。
*
*/
@Test
public void test1(){
String s1 = "HelloWorld";
System.out.println(s1.length());//10
System.out.println(s1.charAt(0));//H
System.out.println(s1.charAt(9));//d
//System.out.println(s1.charAt(10));//越界
//s1 = "";
System.out.println(s1.isEmpty()); //false
String s2 = s1.toLowerCase();
System.out.println(s1);//HelloWorld s1不可变,仍为原值
System.out.println(s2);//helloworld
String s3 = " hel lo wor l d ";
String s4 = s3.trim();
System.out.println(s3);// hel lo wor l d
System.out.println(s4);//hel lo wor l d
}
@Test
public void test2(){
String s1 = "HelloWorld";
String s2 = "helloworld";
System.out.println(s1.equals(s2)); //false
System.out.println(s1.equalsIgnoreCase(s2));//true
String s3 = "abc";
String s4 = s3.concat("def");
System.out.println(s4);
String s5 = "abc";
String s6 = new String("abe");
System.out.println(s5.compareTo(s6));//-2 涉及到字符串排序(通讯录联系人)
String s7 = "我是你爸爸";
String s8 = s7.substring(2);
System.out.println(s7);
System.out.println(s8); //你爸爸
String s9 = s7.substring(2,4); //(包前不包后)
System.out.println(s9); //你爸
}
/**
* * - boolean endsWith(String suffix):测试此字符串是否以指定的后缀结束
* * - boolean startsWith(String prefix):测试此字符串是否以指定的前缀开始
* * - boolean startsWith(String prefix, int toffset):测试此字符串从指定索引开始的 子字符串是否以指定前缀开始
* * - boolean contains(CharSequence s):当且仅当此字符串包含指定的 char 值序列时,返回 true
* * - int indexOf(String str):返回指定子字符串在此字符串中第一次出现处的索引
* * - int indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出 现处的索引,从指定的索引开始
* * - int lastIndexOf(String str):返回指定子字符串在此字符串中最右边出现处的索引
* * - int lastIndexOf(String str, int fromIndex):返回指定子字符串在此字符串中最后 一次出现处的索引,从指定的索引开始反向搜索 注:indexOf和lastIndexOf方法如果未找到都是返回-1
* * - String replace(char oldChar, char newChar):返回一个新的字符串,它是 通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
* * - String replace(CharSequence target, CharSequence replacement):使 用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。
* * - String replaceAll(String regex, String replacement) : 使 用 给 定 的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
* * - String replaceFirst(String regex, String replacement) : 使 用 给 定 的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。
* * - boolean matches(String regex):告知此字符串是否匹配给定的正则表达式。
* * - String[] split(String regex):根据给定正则表达式的匹配拆分此字符串。
* * - String[] split(String regex, int limit):根据匹配给定的正则表达式来拆分此字符串,最多不超过limit个,如果超过了,剩下的全部都放到最后一个元素中。
*/
@Test
public void test3(){
String s1 = "helloworld";
boolean b1 = s1.endsWith("ld");
System.out.println(b1);//true
boolean b2 = s1.startsWith("He");
System.out.println(b2); //false
boolean b3 = s1.startsWith("el", 1);
System.out.println(b3); //true
String str2 = "wo";
boolean contains = s1.contains(str2);
System.out.println(contains);//true
System.out.println(s1.indexOf("lo"));//3
System.out.println(s1.indexOf("lo1"));//-1
System.out.println(s1.indexOf("or", 5));//6
String str3 = "hellorworld";
System.out.println(str3.lastIndexOf("or"));//7
System.out.println(str3.lastIndexOf("or", 6));//4
}
/**
* String replace(char oldChar, char newChar):返回一个新的字符串,它是 通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
* String replace(CharSequence target, CharSequence replacement):使 用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子
* String replaceAll(String regex, String replacement) : 使 用 给 定 的 replacement 替换此字符串所有匹配给定的正则表达式
* String replaceFirst(String regex, String replacement) : 使 用 给 定 的 replacement 替换此字符串匹配给定的正则表达式
* 匹配
* boolean matches(String regex):告知此字符串是否匹配给定的正则表达式。
* 切片
* String[] split(String regex):根据给定正则表达式的匹配拆分此字符串。
* String[] split(String regex, int limit):根据匹配给定的正则表达式来拆分此字符串,最多不超过limit个,如果超过了,剩下的全部都放到最后一个元素中。
*/
@Test
public void test4(){
String str1 = "北京尚硅谷教育北京";
String str2 = str1.replace("北", "东");
System.out.println(str1);
System.out.println(str2);
String str3 = "an2djsffe52ds";
String replaceAllEd = str3.replaceAll("\\d+", ",");
System.out.println(replaceAllEd);//an,djsffe,ds
String str = "12345";
boolean matches = str.matches("\\d+");
System.out.println(matches);//true
String tel = "0571-4534289";
boolean res = tel.matches("0571-\\d{7,8}");
System.out.println(res);//true
String str4 = "hello|world|java";
String[] split = str4.split("\\|");
for (String s : split) {
System.out.println(s);
}
System.out.println();
}
String与基本数据类型,char数组,byte数组转换
-
字符串 -》 基本数据类型、包装类
- Integer包装类的public static int parseInt(String s):可以将由“数字”字符组成的字符串转换为整型。
- 类似地,使用java.lang包中的Byte、Short、Long、Float、Double类调相应的类方法可以将由“数字”字符组成的字符串,转化为相应的基本数据类型。
-
基本数据类型、包装类 -》 字符串
- 调用String类的public String valueOf(int n)可将int型转换为字符串
- 相应的valueOf(byte b)、valueOf(long l)、valueOf(float f)、valueOf(doubled)、valueOf(boolean b)可由参数的相应类型到字符串的转换
-
字符数组 -》字符串
- String 类的构造器:String(char[]) 和 String(char[],int offset,int length) 分别用字符数组中的全部字符和部分字符创建字符串对象。
-
字符串 -》字符数组
- public char[] toCharArray():将字符串中的全部字符存放在一个字符数组中的方法。
- public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin):提供了将指定索引范围内的字符串存放到数组中的方法。
-
字节数组 -》字符串
- String(byte[]):通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String。
- String(byte[],int offset,int length) :用指定的字节数组的一部分,即从数组起始位置offset开始取length个字节构造一个字符串对象。
-
字符串 -》字节数组
- public byte[] getBytes() :使用平台的默认字符集将此 String 编码为byte 序列,并将结果存储到一个新的 byte 数组中。
- public byte[] getBytes(String charsetName) :使用指定的字符集将此 String 编码到 byte 序列,并将结果存储到新的 byte 数组。
public class StringTransfer {
/**
* String与基本数据类型,包装类的转换
*/
@Test
public void string2Wrapper(){
String str1 = "12345";
int i = Integer.parseInt(str1);
System.out.println(i);
int num = 123;
String s = String.valueOf(num);
System.out.println(s);
}
/**
* String与char数组之间的转换
*/
@Test
public void String2CharArray(){
String str1 = "abc123";
char[] chars = str1.toCharArray();
for (char aChar : chars) {
System.out.println(aChar);
}
char[] chars2 = new char[]{'h','e','l','l','o'};
String s1 = new String(chars2);
System.out.println(s1);
}
/**
* String与byte数组之间的转换
*/
@Test
public void String2ByteArray() throws UnsupportedEncodingException {
String str = "abc123中国";
byte[] bytes = str.getBytes();//使用默认的字符集进行编码
System.out.println(Arrays.toString(bytes));//[97, 98, 99, 49, 50, 51, -28, -72, -83, -27, -101, -67] - utf-8中一个汉字三位
byte[] gbks = str.getBytes("gbk");
System.out.println(Arrays.toString(gbks));
System.out.println("*****************");
String str2 = new String(bytes);//使用默认的字符集进行解码
System.out.println(str2);
String str3 = new String(gbks);//字符集不一致,出现乱码
System.out.println(str3);
}
}
StringBuffer
- String,StringBuffer,StringBuilder的异同
- String:不可变的字符序列,底层使用char[]
- StringBuffer:可变的字符序列,线程安全,效率低,底层使用char[]
- StringBuilder: 可变的字符序列,线程不安全,效率高,底层同样使用char[]
源码分析:
String s1 = new String("abc"); -> char[] value = new char[]{'a','b','c'};
StringBuffer sb1 = new StringBuffer(); -> char[] value = new char[16];//底层创建了一个长度为16的char数组
StringBuffer sb2 = new StringBuffer("abd"); -> char[] value = new char["abc".length()+16];
问题1:
System.out.println(sb2.length()); //3
问题2:
如果要添加数据的底层数组存不下了,就要扩容底层数组。默认情况下要扩容到原容量的2倍+2,同时将原有数组中的元素复制到新数组中。
指导意义:
开发中建议使用StringBuffer(int capacity);或StringBuilder(int capacity);避免了数组复制。
常用方法:
- 常用方法总结:
- 增:append(xxx)
- 删:delete(int start,int end)
- 改:setCharAt(int n,char ch) / replace(int start,int end,String str)
- 查:charAt(int n)
- 插:insert(int offset,xxx)
- 长度:length()
- 遍历:for + charAt()