面试必问系列
String是字符串常量,一旦创建就不能修改。对于已经存在的String对象的修改都是重新创建一个新的对象,然后把新的值保存进去。String类是final修饰的,不能被继承。覆盖了equals方法和hashCode()方法。
String str1 = "hello";
String str2 = "world";
String str3 = str1 + str2;
String str4 = new String("hello");
一张图明白字符串创建时的引用过程。通过内存图就很容易判断出字符串的值或对象的引用是否相同了。(==和equals的区别)

字符串的常用操作
| 数据类型 | 字符串转换为其他数据类型的方法 | 其它数据类型转换为字符串的方法1 | 其他数据类型转换为字符串的方法2 |
|---|---|---|---|
| byte | Byte.parseByte(str) | String.valueOf([byte] bt) | Byte.toString([byte] bt) |
| int | Integer.parseInt(str) | String.valueOf([int] i) | Int.toString([int] i) |
| long | Long.parseLong(str) | String.valueOf([long] l) | Long.toString([long] l) |
| float | Float.parseFloat(str) | String.valueOf([float] f) | Float.toString([float] f) |
| double | double.parseDouble(str) | String.valueOf([double] d) | Double.toString([double] b) |
| char | str.charAt() | String.valueOf([char] c) | Character.toString([char] c) |
| boolean | Boolean.getBoolean(str) | String.valueOf([boolean] b) | Boolean.toString([boolean] b) |
//定义一个字符串
String str = "Life is like the ocean. Only the strong willed can reach the other shore.";
//输出字符串
System.out.println(str);
//Life is like the ocean. Only the strong willed can reach the other shore.
/***1、length()方法***/
//得到字符串长度
int length = str.length();
System.out.println("字符串的长度为:"+length);
//字符串的长度为:73
/***2、charAt()方法***/
//得到索引为7的字符
char ch = str.charAt(10);
System.out.println("字符串中的第11个字符为:"+ch);
//字符串中的第11个字符为:k
/***3、getChars()方法***/
//定义容量为80的字符数组,用于存储从字符串中提取出的一串字符
char chardst[] = new char[80];
str.getChars(0,14,chardst,0);
//错误,输出的是地址
System.out.println("字符数组中存放的内容为:"+chardst);
//字符数组中存放的内容为:[C@1540e19d
//直接输出不会输出地址,原因是char[]重写了toString方法
System.out.println(chardst);
//Life is like t
String str1 = "elapant";
String str2 = "ELEPANT"; //定义两个字符串
String str3 = "Apple";
String str4 = "apple";
/***1、compareTo方法***/
//不忽略字符串字符大小写
if(str1.compareTo(str2)>0){
System.out.println(str1+">"+str2);
//elapant>ELEPANT
}else if(str1.compareTo(str2) == 0){
System.out.println(str1+"="+str2);
}else{
System.out.println(str1+"="+str2);
}
/***2、compareToIgnoreCase()方法***/
//忽略字符串字符大小写
if(str1.compareToIgnoreCase(str2)>0){
System.out.println(str1+">"+str2);
}else if(str1.compareToIgnoreCase(str2) == 0){
System.out.println(str1+"="+str2);
}else{
System.out.println(str1+"<"+str2);
//elapant<ELEPANT
}
/***3、equals()方法***/
//不忽略字符串字符大小写
if(str3.equals(str4)){
System.out.println(str3+"="+str4);
}else{
System.out.println(str3+"!="+str4);
//Apple!=apple
}
/***4、equalsIgnoreCase()方法***/
//忽略字符串字符大小写
if(str3.equalsIgnoreCase(str4)){
System.out.println(str3+"="+str4);
//Apple=apple
}else{
System.out.println(str3+"!="+str4);
}
/***将字符串类型转换为其他数据类型***/
//字符串类型转换为布尔类型
boolean bool0 = Boolean.getBoolean("false");
System.out.println(bool0);
//字符串类型转换为整形
int int0 = Integer.parseInt("9");
System.out.println(int0);
//9
//字符串类型转换为长整形
long long0 = Long.parseLong("1024");
System.out.println(long0);
//1024
//字符串类型转换为单精度浮点型
float float0 = Float.parseFloat("1.521");
System.out.println(float0);
//1.521
//字符串类型转换为双精度浮点型
double double0 = Double.parseDouble("1.52123");
System.out.println(double0);
//1.52123
//字符串类型转换为byte型
byte byte0 = Byte.parseByte("127");
System.out.println(byte0);
//127
//字符串获取单个字符
char char0 = "hello".charAt(0);
System.out.println(char0);
//h
/***将其他数据类型转换为字符串类型方法1***/
//将布尔类型转换为字符串类型
String strBool1 = String.valueOf(bool0);
System.out.println(strBool1);
//false
//将整形转换为字符串类型
String strInt1 = String.valueOf(int0);
System.out.println(strInt1);
//9
//将长整型转换为字符串类型
String strLong1 = String.valueOf(long0);
System.out.println(strLong1);
//1024
//将单精度浮点型转换为字符串类型
String strFloat1 = String.valueOf(float0);
System.out.println(strFloat1);
//1.521
//将double类型转换为字符串类型
String strDouble1 = String.valueOf(double0);
System.out.println(strDouble1);
//1.52123
//将byte转换为字符串类型
String strByte1 = String.valueOf(byte0);
System.out.println(strByte1);
//127
//将字符型转换为字符串类型
String strChar1 = String.valueOf(char0);
System.out.println(strChar1);
//h
/***将其他数据类型转换为字符串类型方法1***/
//将布尔类型转换为字符串类型
String strBool2 = Boolean.toString(bool0);
System.out.println(strBool2);
//false
//将整形转换为字符串类型
String strInt2 = Integer.toString(int0);
System.out.println(strInt2);
//9
//将长整型转换为字符串类型
String strLong2 = Long.toString(long0);
System.out.println(strLong2);
//1024
//将单精度浮点型转换为字符串类型
String strFloat2 = Float.toString(float0);
System.out.println(strFloat2);
//1.521
//将double类型转换为字符串类型
String strDouble2 = Double.toString(double0);
System.out.println(strDouble2);
//1.52123
//将byte转换为字符串类型
String strByte2 = Byte.toString(byte0);
System.out.println(strByte2);
//127
//将字符型转换为字符串类型
String strChar2 = Character.toString(char0);
System.out.println(strChar2);
//h
/***1、indexOf()方法查找字符首个出现位置格式1,2***/
//String str = "Life is like the ocean. Only the strong willed can reach the other shore.";
//找到第一个空格所在的索引
int index1 = str.indexOf(" ");
//找到索引10以后的第一个空格所在索引
int index2 = str.indexOf(" ",10);
System.out.println("第一个空格所在索引为:"+index1);
//第一个空格所在索引为:4
System.out.println("索引10以后的第一个空格所在索引为:"+index2);
//索引10以后的第一个空格所在索引为:12
/***2、lastIndexOf()方法查找字符最后出现位置格式1,2***/
//找到最后一个空格所在的索引
int index3 = str.lastIndexOf(" ");
//找到索引10以后的第一个空格所在索引
int index4 = str.lastIndexOf(" ",10);
System.out.println("最后一个空格所在索引为:"+index3);
//最后一个空格所在索引为:66
System.out.println("索引10以前最后一个空格所在索引为:"+index4);
//索引10以前最后一个空格所在索引为:7
/***3、indexOf()方法查找子字符串第一次出现位置格式1,2***/
//找到"is"子字符串第一次出现位置的索引
int index5 = str.indexOf("is");
//找到索引5以后子字符串"the"第一个出现位置所在索引
int index6 = str.indexOf("the",5);
System.out.println("子字符串is第一次出现位置的索引号为:"+index5);
//子字符串is第一次出现位置的索引号为:5
System.out.println("索引5以后子字符串the第一次出现位置的索引号为:"+index6);
//索引5以后子字符串the第一次出现位置的索引号为:13
/***4、lastIndexOf()方法查找子字符串最后一次出现位置格式1,2***/
int index7 = str.lastIndexOf("the");
int index8 = str.lastIndexOf("the",18);
System.out.println("子字符串the最后一次出现位置的索引号为:"+index7);
//子字符串the最后一次出现位置的索引号为:62
System.out.println("索引号5以后子字符串the最后一次出现位置的索引号为:"+index8);
//索引号5以后子字符串the最后一次出现位置的索引号为:13
/***字符串截取与拆分***/
//String str = "Life is like the ocean. Only the strong willed can reach the other shore.";
System.out.println("字符串为:"+str);
System.out.println("字符串长度为:"+length);
/***1、substring()方法截取出第一个单词和最后一个单词***/
//首先配合indexOf()和lastIndexOf()方法找到第一个单词和最后一个单词前后空格的索引号
//第一个单词的左范围索引为0,最后一个单词的右范围索引为length-1
//找到第一个空格所在位置
int firstIndex = str.indexOf(‘ ‘);
//找到最后一个空格所在位置
int lastIndex = str.lastIndexOf(‘ ‘);
System.out.println("第一个空格的索引号为:"+firstIndex);
System.out.println("最后一个空格的索引号为:"+lastIndex);
//利用substring()方法根据第一个和最后一个单词的索引范围截取出第一个和最后一个单词
//截取出第一个单词
String firstWord = str.substring(0,firstIndex);
//截取出最后一个单词
String lastWord = str.substring(lastIndex+1,length);
System.out.println("第一个单词为:"+firstWord);
//第一个单词为:Life
System.out.println("最后一个单词为:"+lastWord);
//最后一个单词为:shore.
/***1、split()方法拆分出所有单词***/
String stringArray[] = str.split(" "); //根据空格要求拆分出所有单词保存到字符串数组中
System.out.println("拆分之后的各个词汇为:"); //输出提示信息
for(int i = 0;i<stringArray.length;i++){
System.out.print(stringArray[i]+"\t");
}
//拆分之后的各个词汇为:
//Life is like the ocean. Only the strong willed can reach the other shore.
/***字符串替换与修改***/
String str5 = "HELLO";
String str6 = "world";
System.out.println("str5 = "+str5);
System.out.println("str6 = "+str6);
/***1、concat()方法将两字符串合并***/
String str7 = str5.concat(str6);
System.out.println("str5和str6合并后的字符串为:"+str7);
//str5和str6合并后的字符串为:HELLOworld
/***2、toLowerCase()方法将str5字符全部转换为小写***/
String str8 = str5.toLowerCase();
System.out.println("str5的字符全部转换为小写:"+str8);
//str5的字符全部转换为小写:hello
/***3、toUpperCase()方法将str6字符全部转换为大写***/
String str9 = str6.toUpperCase();
System.out.println("str6的字符全部转换为大写:"+str9);
//str6的字符全部转换为大写:WORLD
/***4、实现字符串的替换,原字符串内容不变***/
String str10 = str5.replaceFirst("(?i)HELLO","你好");
String str11 = str6.replaceFirst("(?-i)world","世界");
System.out.println("替换后的str5:"+str10);
//替换后的str5:你好
System.out.println("替换后的str6:"+str11);
//替换后的str6:世界
StringBuffer是字符串可变对象,可以对字符串进行操作,修改字符串原有值时不会新建一个对象。使用了synchronized关键字,执行效率较慢,但是线程安全。StringBuffer没有覆盖equals方法和hashCode()方法。可以动态的拼接字符换,使用 append() 方法。
StringBuffer类跟String类一样定义成final形式,主要是为了“效率”和“安全性”的考虑,若StringBuffer 被继承,由于它的高使用率,可能会降低它的性能。
jdk1.5 发行之后,有一个等价的对象被补充-StringBuilder。但是StringBuilder不支持线程同步,他支持StringBuffer的所有方法,速度更快。
StringBuilder也是字符串可变对象,同StringBuffer一样,定义成final形式,可以对字符串进行操作,也不会新建对象。执行效率高效,但是线程不安全。
String,StringBuffer,StringBuilder。三者都被final修饰,区别就是String声明的是不可变的对象,每次操作必然产生一个新的对象;StringBuffer和StringBuilder都继承自抽象类AbstractStringBuilder;StringBuffer具备线程安全性;在使用场景上,并发必选StringBuffer,迭代必选StringBuilder,普通场景选String,避免中途不必要的类型转换开销。
在运行速度方面,StringBuilder > StringBuffer > String,在线程安全方面,如果一个StringBuffer对象在字符串缓冲区被多个线程使用时,StringBuffer中很多方法可以带有synchronized关键字,所以可以保证线程是安全的,但StringBuilder的方法则没有该关键字,所以不能保证线程安全,有可能会出现一些错误的操作。所以如果要进行的操作是多线程的,那么就要使用StringBuffer,但是在单线程的情况下,还是建议使用速度比较快的StringBuilder。一个线程访问一个对象中的synchronized(this)同步代码块时,其他试图访问该对象的线程将被阻塞。
在Java的字符串中,其实最底层的实现就是通过一个字符数组来保存String字符串的,抓住这一点,其实很多设计方法,方法的实现方式就显而易见了。
在String中的是final char value[],不可变字符数组。而StringBuffer和StringBuilder都继承自抽象类AbstractStringBuilder,都维护了AbstractStringBuilder中的char value[]字符数组。
原文:https://www.cnblogs.com/apangne/p/13354606.html