目录
JDK中String类的声明:
String类被final修饰:被final修饰的类无法被继承,Strring 类不存在子类,这样就可以保证所有使用JDK的人,用到的String类是同一个。继承和方法覆写带来灵活性的同时,也会带来许多子类行为不一致的问题。
1、创建字符串的四种方式:(方式一和方式四最常用)
方式一:直接赋值(String str = "hello world";)
方法二:通过构造方法产生对象(String str1 = new String("hello world";))
方法三:通过字符数组产生对象
char[] data = new char[]{'a','b','c'};
String str3 = new String(data);
方式四:通过String的静态方法valueOf(任意数据类型)->转为字符串
String str4 = String.valueOf(10);
public static void main(String[] args) {
String str1 = "hello world";
String str2 = new String("hello world");
char[] data = new char[]{'a','b','c'};
String str3 = new String(data);
String str4 = String.valueOf(10);
}
2、字符串的字面量(也是字符串的对象)
字面量:直接写出来的数值就称之为字面量。如10->int类型字面量;true->boolean类型字面量;
“abc”->String类型字面量->就是一个字符串的对象
3、字符串比较
所有引用数据类型在比较是否相等时,使用equals方法比较。JDK的常用类,都已经覆写了equals方法,直接使用即可。
a.区分大小写的比较 public boolean equals (Object object){};
b.不区分大小写的比较 public boolean equalsIgnoreCase (String anotherString){};
c.比较两个字符串的大小关系 public int compareTo(String anotherString){};
字符串也实现了Comparable接口,覆写compareTo方法。字符串的compareTo方法按照字符串内部的每个数组进行ASCII码的比较。
//equals的比较是区分大小写的比较
String str1 = new String("hello");
String str2 = new String("hello");
String str3 = new String("Hello");
//true
System.out.println(str1.equals(str2));
//false
System.out.println(str1.equals(str3));
//equalsIgnoreCase是不区分大小写的比较
//true
System.out.println(str1.equalsIgnoreCase(str3));
//compareTo 比较两个字符串的大小
String str4 = "abc";
String str5 = "AbC";
System.out.println(str4.compareTo(str5));
4、关于字符串的常量池问题
当使用直接赋值法产生字符串对象时,JVM会维护一个字符串的常量池,若该对象在堆中还不存在,则产生一个新的字符串对象加入字符串的常量池中。当继续使用直接赋值法产生字符串对象时,JVM发现该引用指向的内容在常量池中已经存在了,则此时不再新建字符串对象,而是复用已有对象 。
5、手工入池—String 类提供的 intern 方法
调用intern方法会将当前字符串引用指向的对象保存到字符串的常量池中。
(1)若当前常量池中已经存在了该对象,则不再产生新的对象,返回常量池中String对象。
(2)若当前常量池中不存在该对象,则将该对象入池,返回入池后的地址
String str1 = new String("hello");
str1.intern();
String str2 = "hello";
System.out.println(str1 == str2);
String str1 = new String("hello");
str1 = str1.intern();
String str2 = "hello";
System.out.println(str1 == str2);
char[] data = new char[]{'a','b','c'};
String str1 = new String(data);
str1.intern();
String str2 = "abc";
System.out.println(str1 == str2);
6、字符串的不可变性:
指的是字符串的内容不可变,而不是字符串的引用不可变。
String类的所有针对字符串的操作方法都不会修改原字符串,而是产生了一个新的字符串!
String str = "hello";
str = str + "world";
str += "!!!";
System.out.println(str);
这里的不可变指的是“hello”、“world”、“helloworld”、“!!!”、“helloworld!!!” 这些字符串对象一旦声明后就无法修改其内容。
为什么字符串的对象无法修改内容而其他类的对象能修改内容?
字符串保存的值实际在数组中保存,String类外部无法访问这个value数组(String并没有提供关于value属性的getter 和setter方法,对于String类的外部而言,value完全无法使用)
7、修改字符串的内容
(1)在运行时通过反射破坏value数组的封装(了解,不推荐)
(2)更换使用StringBuilder 或者StringBuffer类。(若需要频繁进行字符串的拼接,使用StringBuiler类的append方法)
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("hello");
stringBuilder.append("world");
stringBuilder.append("!!!");
System.out.println(stringBuilder);
}
关于StringBuilder类的具体应用:
StringBuilder类和String类是两个独立的类,StringBuilder就是为了解决字符串拼接问题产生的。因为String的对象无法修改内容,为了方便字符串的拼接操作,产生了StringBuilder类,StringBuilder类的对象是可以修改内容的。
(2-1)StringBuilder 和String 类的相互转换
//String类变为StringBuilder类
//(1)构造方法
StringBuilder stringBuilder = new StringBuilder("ABC");
//(2)append方法拼接
stringBuilder.append("hello");
//StringBuilder类还原为String类
String str = stringBuilder.toString();
System.out.println(str);
(2-2)因为StringBuilder类可以修改内容,因此具备一些String类不具备的修改内容的功能(除append方法外)
a.字符串反转操作,StringBuilder类提供的reverse();
b.删除指定范围的数据 delete(int start, int end): [start , end)
c.插入操作 insert(int start,各种数据类型):将新元素插入当前对象,插入后新元素的起始索引为start。
StringBuilder stringBuilder = new StringBuilder("hello");
stringBuilder.append("world");
//字符串反转操作,StringBuilder类提供的reverse()方法
// stringBuilder.reverse();
//删除指定范围内的数组[)
stringBuilder.delete(5,10);
//插入操作 hello10
stringBuilder.insert(5,10);
//heFly llo10
stringBuilder.insert(2,"Fly ");
//还原为字符串
String str = stringBuilder.toString();
System.out.println(str);
(2-3)String、StringBuilder、StringBuffer的区别:
a.String的对象无法修改,StringBuilder、StringBuffer的对象的内容可以修改
b.StringBuilder线程不安全,但性能较高;StringBuffer线程安全,但性能较差。
8、字符和字符串的相互转换。
字符串的内部实际上就是使用字符数组存储的。
(1)字符数组转为字符串
a.通过构造方法
b.将字符数组的部分内容转为字符串对象 public String(char value[], int offset,int count) {};
(2) 字符串转为字符数组(非常重要!)
a.取出字符串中指定索引的字符 public char charAt(int index){};
b.将字符串中的内容转为字符数组 (String -> char[]) public char[] toCharArray(){};
此时产生了一个新的字符数组,将字符串的内容复制过去的,原字符串的内容不变!
public static void main(String[] args) {
//将字符串中的内容转为字符数组
String str = "hello";
char[] data = str.toCharArray();
System.out.println(data);
data[0] = 'H';
//字符串内容不可变
System.out.println(str);
// //取出字符串中指定索引的字符
// String str = "hello";
// //取出索引为2的字符->l
// System.out.println(str.charAt(2));
// //将字符数组的部分内容转为字符串对象
// char[] ch = new char[]{'a','b','c'};
// //offset表示字符数组开始的索引;count表示转换的字符个数
// String str = new String(ch,1,2);
// System.out.println(str);
// //构造方法
// char[] ch = new char[]{'a','b','c'};
// String str = new String(ch);
// String str1 = String.valueOf(ch);
// System.out.println(str);
// System.out.println(str1);
}
(3)如何判断一个字符串的对象是由纯数字组成的?
public class StringInterconersion {
//传入一个String对象,判断是否由纯数字组成
public static boolean isNumber(String str){
//首先转为字符数组处理
char[] data = str.toCharArray();
//循环遍历data中的每个字符,判断这个字符是否是数字字符
//['0'...'9']
for (int i = 0; i < data.length; i++) {
//找到反例
// if (data[i] < '0' || data[i] > '9') {
// return false;
// }
//JDK中的实现 Character是char的包装类,
// isDigit()方法判断字符data[i]是否是数字
if(!Character.isDigit(data[i])){
return false;
}
}
return true;
}
public static void main(String[] args) {
String str = "123";
String str1 = "12a3";
//true
System.out.println(isNumber(str));
//false
System.out.println(isNumber(str1));
}
}
9、字符串和字节的相互转换
(将字符串保存到文件中或者通过网络传输时都要用到字节数组)
(1)byte数组转为字符串(按照ASCII码值)
a.通过构造方法
b.将byte数组的部分内容转为字符串对象 public String(byte bytes[], int offset,int length) {};
(2)字符串转为byte数组
a.将字符串以字节数组的形式返回(按照当前默认的编码格式) public byte[] getBytes(){};
b.按照指定的编码格式转为字节数组 public byte[] getBytes( String charsetName) throws unsupportedEncodingException
在UTF-8编码下,一个汉字3个字节;在GBK编码下,一个汉字两个字节
10、字符串的查找
a.判断一个子字符串是否存在 public boolean contains(CharSequence s){};
b.判断是否以指定字符串开头 public boolean startWith(String prefix){};
c.判断是否以指定字符串结尾 public boolean endWith(String suffix){};
public static void main(String[] args) {
String str = "hello world";
//判断str中是否包含子字符串“hello”
System.out.println(str.contains("hello"));
//判断str是否以指定的字符串开头(严格校验)
System.out.println(str.startsWith("hello"));
System.out.println(str.startsWith("hello1"));
//判断str是否以指定的字符串结尾(严格校验)
System.out.println(str.endsWith("world"));
System.out.println(str.endsWith("world1"));
//从头开始查找指定字符串的位置,查到了返回位置的开始索引,查不到返回-1;
System.out.println(str.indexOf("hello"));//0
System.out.println(str.indexOf("hello1"));//-1
System.out.println(str.indexOf("world"));//6
//从指定位置开始查找子字符串位置
System.out.println(str.indexOf("hello",0));//0
System.out.println(str.indexOf("hello",2));//-1
System.out.println(str.indexOf(" ",3));//5
//由后向前查找子字符串位置
System.out.println(str.lastIndexOf("world"));//6
System.out.println(str.lastIndexOf("worl3"));//-1
System.out.println(str.lastIndexOf(" "));//5
//从指定位置右后向查找
System.out.println(str.indexOf(" ",2));//true
//从指定位置开始判断是否以指定字符串开头
System.out.println(str.startsWith("ello",1));
}
11、字符串的替换(替换操作不会修改原字符串的内容)
public static void main(String[] args) {
String str = "hello world";
//将字符串中所有的“l" 替换成“—”
System.out.println(str.replaceAll("l","-"));
//将字符串中第一个出现的的“l" 替换成“—”
System.out.println(str.replaceFirst("l","-"));
}
12、字符串的拆分操作
public static void main(String[] args) {
String str = "Hello java Hello world";
//按照给定的子字符串,将字符串全部拆分
String[] data1 = str.split(" ");
System.out.println(Arrays.toString(data1));
//若str中没有指定的拆分的子字符串,拆分后仍然得到原字符串
String[] data2 = str.split("/");
//[Hello java Hello world]
System.out.println(Arrays.toString(data2));
//1
System.out.println(data2.length);
//按照给定的子字符串,将字符串部分拆分,拆分后的个数为limit
String[] data3 = str.split(" ",2);
System.out.println(Arrays.toString(data3));
}
当按照指定的字符拆分字符串得到一个空数组:传入的字符是个特殊字符,需要转义处理“\\”。
13.字符串的截取处理
public static void main(String[] args) {
String str = "helloworld";
//从索引为5的位置开始直至末尾
System.out.println(str.substring(5));//world
//从索引为0的位置开始,到索引为5的位置之前结束[0, 5)
System.out.println(str.substring(0,5));//hello
}
14、字符串的其他常用操作
public static void main(String[] args) {
String str = " hello world hello java ";
String str1 = " HELLO WORD HELLO JAVA ";
System.out.println(str);
//去掉字符串中的左右空格,保留中间空格
System.out.println(str.trim());
//字符串转大写
System.out.println(str.toUpperCase(Locale.ROOT));
//字符串转小写
System.out.println(str1.toLowerCase(Locale.ROOT));
//取得字符串长度
System.out.println(str.length());//24
//判断是否为空数组,但不是null,而是长度为0
String str2 = "";
System.out.println(str.isEmpty());//false
System.out.println(str2.isEmpty());//true
}
15、小练习:将字符串的首字母大写处理
public class StringAnother {
public static void main(String[] args) {
String str = "hello";
String str2 = "";
String str3 = "q";
System.out.println(FirstUpper(str));
System.out.println(FirstUpper(str2));
System.out.println(FirstUpper(str3));
}
public static String FirstUpper(String str){
//首先判空处理
if (str == null|| str.isEmpty()){
return null;
}
//边界条件(只有一个字母)
if(str.length()==1){
return str.toUpperCase(Locale.ROOT);
}
//此时str长度大于1
//截取 + 大写
return str.substring(0,1).toUpperCase(Locale.ROOT)+str.substring(1);
}
}