String:字符串,使用一对双引号“”引起来表示。
String声明为final的,不可以被继承
String实现了Serializable接口:表示字符串是支持序列化的。(序列化在IO流会提及)
String实现了Comparable接口:表示String可以比较大小
String内部定义了final char[] value用于存储字符串数据
String:代表不可变的字符序列,有着不可变的特性; 简称:不可变性
通过字面量的方式(区别于new)给一个字符串赋值,此时的字符串值声明在字符串常量池中。
字符串常量池中是不会存储相同内容的字符串的。
不可变的特性
指的是在方法区中,有着字符串常量池,比如你声明了一个字符串叫“abc”,赋值给一个变量s1,你又声明一个变量s2,你也赋值“abc”。其实他俩指向的地址是一样的。不会说你再声明一个相同的内容而去给你新增。
体现:
当对字符串重新赋值时,需要重新指定内存区域赋值,不能使用原有的value进行赋值。
意思就是你不能把原来的值更改,在字符串常量池中会再创一个你重新赋值的值,把新值的地址给你需要重新赋值的变量
当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。
当调用String的replace方法时,修改指定的字符或字符串时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。
举例:
@Test
public void test1() {
String s1 = "abc";
String s2 = "abc";
// s1 = "hello";
System.out.println(s1 == s2);
System.out.println(s1);
System.out.println(s2);
System.out.println("************");
String s3 = "abc";
s3 += "def";
System.out.println(s3);
System.out.println("************");
String s4 = "abc";
String s5 = s4.replace('a', 'd');
System.out.println(s4);
System.out.println(s5);
}
复制代码
String实例化方式
本质上this.value = new char[0],创建了一个长度为0的char型数组
String s1 = new String();
比如()里写"hello",相当于底层创建了长度为5的char数组;this.value = original.value
String s2 = new String(String original);
this.value = Arrays.copyOf(value,value.length),将char数组的内容复制给s3
String s3 = new String(char[] a);
从char数组的starIndex下标开始,放count个元素给s4
String s4 = new String(char[] a,int starIndex,int count);
Q:String s1 = "abc" 与 String s1 = new String("abc")的区别
String的实例化有两种方式:
通过字面量定义的方式
通过new + 构造器的方式
@Test
public void test(){
//1.通过字面量定义的方式
//此时的s1和s2的数据javaEE声明在方法区中的字符串常量池中
String s1 = "javaEE";
String s2 = "javaEE";
//2.通过new + 构造器的方式
//此时的s3和s4保存的地址值,是数据在堆空间中开辟空间以后对应的地址值
String s3 = new String("javaEE");
String s4 = new String("javaEE");
System.out.println(s1 == s2); //true
System.out.println(s1 == s4); //false
System.out.println(s3 == s4); //false
}
复制代码
Q:String s = new String("abc");方式创建对象,在内存中创建了几个对象?
A:两个;一个是堆空间中new结构,另一个是char[]对象的常量池中的数据:"abc"
String的拼接操作
常量和常量的拼接结果是在常量池中。且常量池中不会存在相同内容的常量。
只要其中有一个是变量,结果就在堆中。
@Test
public void test1(){
String s1 = "javaEE";
String s2 = "hello";
String s3 = "javaEEhello";
String s4 = "javaEE" + "hello";
String s5 = s1 + "hello";
String s6 = "javaEE" + s2;
String s7 = s1 + s2;
System.out.println(s3 == s4); //true
System.out.println(s3 == s5); //false
System.out.println(s3 == s6); //false
System.out.println(s3 == s7); //false
System.out.println(s5 == s6); //false
System.out.println(s5 == s7); //false
System.out.println(s6 == s7); //false
}
复制代码
如果拼接的结果调用intern()方法,返回值就在常量池中
String s8 = s5.intern();//返回得到的s8使用的是常量池中已经存在的"javaEEhello"
System.out.println(s3 == s8); //true
复制代码
String的常用方法
比较重要的:length()、charAt()、compareTo()
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 test(){
String s1 = "HelloWorld";
System.out.println(s1.length()); //字符串长度
System.out.println(s1.charAt(0)); //取字符串第一个位置元素
System.out.println(s1.isEmpty()); //判断字符串是否为空
String s2 = s1.toLowerCase(); //s1不变,把s1所有字母变成小写给s2
System.out.println(s1);
System.out.println(s2);
String s3 = " he ll o wor ld ";
String s4 = s3.trim();//去除s3前面和后面的空格,中间的空格依然保存
System.out.println(s3);
System.out.println(s4);
String s5 = "HelloWorld";
String s6 = "helloworld";
System.out.println(s5.equals(s6)); //比较s5和s6的内容是否一样
System.out.println(s5.equalsIgnoreCase(s6)); //忽略大小写,比较s5和s6的内容是否一样
String s7 = s5.concat("def"); //concat()和 "+"用法一致
System.out.println(s7);
String s8 = "abc";
String s9 = "abe";
System.out.println(s8.compareTo(s9));//比较大小,a跟a比,依次,c的码比e小2
String s10 = "北京天安门广场";
String s11 = s10.substring(2); //从索引为2的元素开始
System.out.println(s11);
String s12 = s10.substring(2, 5); //不包括索引为5的元素
System.out.println(s12);
}
复制代码
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
@Test
public void test1(){
String s1 = "helloworld";
boolean b1 = s1.endsWith("ld");//根据需要写几个字符,判断是否以写的字符为结尾。注意区分大小写
System.out.println(b1);
boolean b2 = s1.startsWith("He"); //判断是否以写的字符为开始。注意区分大小写
System.out.println(b2);
boolean b3 = s1.startsWith("ll",2); //判断指定位置是否以写的字符为开始
System.out.println(b3);
String s2 = "wo";
System.out.println(s1.contains(s2)); //判断一个字符串是否包含另一个字符串
System.out.println(s1.indexOf("lo")); //返回指定的字符串在此字符串中第一次出现的位置
System.out.println(s1.indexOf("lo",5)); //从索引5的位置开始找lo这个子字符串
String s3 = "helloworlord";
System.out.println(s3.lastIndexOf("or")); //从后往前找or这个子字符串,返回索引位置
System.out.println(s3.lastIndexOf("or",8)); //从索引8开始往左寻找or
}
复制代码
替换:
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 test2(){
//replace既可以替换单个字符也可以替换字符串
String s1 = "北北爱吃北京的北京烤鸭";
String s2 = s1.replace('北', '南');
System.out.println(s1);
System.out.println(s2);
String s3 = s1.replace("北京", "南京");
System.out.println(s3);
System.out.println("*************************");
String str = "12hello34world5java7891mysql456";
//把字符串中的数字替换成,,如果结果中开头和结尾有,的话去掉
String string = str.replaceAll("\d+", ",").replaceAll("^,|,$", ""); //\d以及^|$是正则表达式的内容
System.out.println(string);
System.out.println("*************************");
str = "12345";
//判断str字符串中是否全部有数字组成,即有1-n个数字组成
boolean matches = str.matches("\d+");
System.out.println(matches);
String tel = "0571-4534289";
//判断这是否是一个杭州的固定电话
boolean result = tel.matches("0571-\d{7,8}");
System.out.println(result);
System.out.println("*************************");
str = "hello|world|java";
String[] strs = str.split("\|");
for (int i = 0; i < strs.length; i++) {
System.out.println(strs[i]);
}
System.out.println();
s2 = "hello.world.java";
String[] strs2 = s2.split("\.");
for (int i = 0; i < strs2.length; i++) {
System.out.println(strs2[i]);
}
}
复制代码
String与其他类转换
与包装类、基本数据类型
String转换为基本数据类型、包装类
调用包装类的静态方法:parseXxx(str)
@Test
public void test(){
String s1 = "123";
int num = Integer.parseInt(s1);
}
复制代码
基本数据类型、包装类 转换为 String
调用重载的valueOf(xxx) 或 加上 ""
@Test
public void test(){
int num = 123;
String s1 = String.valueOf(num);
String s2 = num + "";
}
复制代码
与char[]数组
String 转换为 char[]数组
使用String的toCharArray()方法
@Test
public void test(){
String s1 = "123abc";
char[] charArray = s1.toCharArray();
for (int i = 0; i < charArray.length; i++) {
System.out.print(charArray[i]);
}
}
复制代码
char[]数组 转换为 String
调用String的构造器
@Test
public void test(){
char arr[] = {'h','e','l','l','o'};
String s = new String(arr);
System.out.println(s);
}
复制代码
与byte[]数组
String 转换为 byte[]数组
调用String的getBytes()
@Test
public void test(){
String s1 = "abc123";
byte[] bytes = s1.getBytes();
System.out.println(Arrays.toString(bytes));//遍历
}
复制代码
编码:字符串 ---> 字节
解码:字节 ---> 字符串
byte[]数组 转换为 String
调用String的构造器
@Test
public void test(){
String s1 = "abc123";
byte[] bytes = s1.getBytes();
String s = new String(bytes);//解码
System.out.println(s);
}
复制代码
注意:
转换成byte[]数组时可以指定编码集,默认为utf-8,如果用其他的,当解码时(字节 ---> 字符串)如果不明确指定则会出现乱码。原因就是编码集和解码集不一致。