目录
String
String 对象是不可改变的。字符串一旦创建,内容不能再改变
字符串的构造方法:
String newString = new String(stringLiteral);
参数 StringLiteral 是一个括在双引号内的字符序列。下面的语句为字符串直接量 "Welcome to ]ava"创建一个 String 对象 message:
String message = new String(’'Wei come to Java");
Java 将字符串直接量看作 String 对象。所以,下面的语句是合法的:
String message = "Welcome to Java";
还可以用字符数组创建一个字符串。例如,下述语句构造一个字符串 "Good Day":
char[] charArray = {'C','o', 'o' , 'd' , ' ' , ' 0' , ' a' ,'y'};
String message » new String(charArray)
字符串的不可变性与对象池
字符串的不可变性(地址的引用)
String对象一旦被创建则不可修改,是不可变的。
所谓的修改是创建了新的对象,所指向的内存空间不变
public class text {
public static void main(String[] args) {
String s = "Java";
s = "HTML";
}
}
上述代码中,第一条语句创建了一个内容为"Java "的 String 对象,并将其引用賦值给 s。 第二条语句创建了一个内容为"HTML"的新 String 对象,并将其引用賦值给 s。陚值后 第一个 String 对象仍然存在,但是不能再访问它,因为变量 s 现在指向了新的对象。如图:
因为字符串在程序设计中是不可变的,但是又会频繁的使用,所以为了提高效率并节约内存,对具由相同字符序列的字符串直接使用同一个实例。这样的实例也称之为对象池(对象池与在包装类所说的常量池用处是一样的)
public class text {
public static void main(String[] args) {
String s1 = "welcom to Java";
String s2 = new String("welcom to Java");
String s3 = "welcom to Java";
System.out.println(s1 == s2);
System.out.println(s1 == s3);
}
}
执行结果:
字符串的一些常用方法:
代码如下
public class text {
public static void main(String[] args) {
String str = " 我爱 JAVA 编程 ";
//获取字符串的长度
int length = str.length();
System.out.println("字符串str的长度是:" + length);
//获取字母‘J’在字符串第一次出现的位置
int indexJ = str.indexOf("J");
System.out.println("字母\'J\'在字符串第一次出现的位置:" + indexJ);
//获取字母A在字符串最后一次出现的位置
int lastIndexA = str.lastIndexOf('A');
System.out.println("字母\'A\'在字符串最后一次出现的位置:" + lastIndexA);
//获取索引为8的字符
char charAt = str.charAt(str.length()-1-1);
System.out.println("索引为8的字符是:" + charAt);
//trim去字符串前后的空格
String trim = str.trim();
System.out.println("去首尾空格前:" + str);
System.out.println("去首尾空格后:" + trim);
//需求:去掉字符串中所有的空格,应该用replace方法
String replaceAll = str.replaceAll(" ", "");
System.out.println("去空格前:" + str);
System.out.println("去空格后:" + replaceAll);
}
}
执行结果:
格式化字符串:
String类包含静态的format方法,它可以创建一个格式化字符串。 调用该方法的语法是:
String.format(format, iteml, item2 itemfc)
这个方法很像 Printf 方法,只是 format 方法返回一个格式化的字符串,而 printf 方 法显示一个格式化的字符串。例如:
String s = String.format("%7.2f%6d% - 4s", 45.556, 14, "AB");
System.out.print!n(s);
显示(用|_|表示空格)
|_||_|45.56|_||_||_||_|14AB|_||_|
注意:
System.out.printf(format,item1,item2,...,itemk);
等价于
System.out.printf(String.format,item1,item2,...,itemk)
StringBuffer和StringBuilder
StringBuilder 和 StringBuffer 类似于 String 类,区别在于 String 类是不可改变的
StringBuilder 和 StringBuffer属于兄弟类(都是继承于AbstractStringBuilder),它们里的方法也差不多。下面,我主要是提及的是 StringBuilder。StringBuilder 和 StringBuffer的区别是:StringBuilder是线程不安全的,但是效率高,适合单线程使用; StringBuffer是线程安全的,所有的方法都synchronized 效率低,适合用于多线程。
关于String、StringBuffer和StringBuilder的执行效率问题
代码如下:
public class text {
public static void main(String[] args) {
//String循环10000次花费的时长
long startTime = System.currentTimeMillis();
String sb = new String("oracle");
for (int i = 0; i < 10000; i++) {
sb += "aa";
}
long endTime = System.currentTimeMillis();
System.out.println("String总共用时:" + (endTime - startTime));
//StringBuffer循环1000000次花费的时长
long startTime1 = System.currentTimeMillis();
StringBuffer sb1 = new StringBuffer("oracle");
for (int i = 0; i < 1000000; i++) {
sb1.append("aa");
}
long endTime1 = System.currentTimeMillis();
System.out.println("StringBuffer总共用时:" + (endTime1 - startTime1));
//StringBuilder循环1000000次花费的时长
long startTime2 = System.currentTimeMillis();
StringBuilder sb2 = new StringBuilder("oracle");
for (int i = 0; i < 1000000; i++) {
sb2.append("aa");
}
long endTime2 = System.currentTimeMillis();
System.out.println("StringBuilder总共用时:" + (endTime2 - startTime2));
}
}
执行结果:
上述代码中,String值循环了10000次,而StringBuilder 和 StringBuffer循环了1000000次,主要是因为String循环太多运行的时间太久,StringBuilder 和 StringBuffe循环太少,不能比较出他们的差距。
— 般来说,只要使用字符串的地方,都可以使用StringBuilder/StringBuffer类。StringBuilder/StringBuffer类比 String类更灵活。可以给一个 StringBuilder 或 String- Buffer 中添加、插入或追加新的内容,但是 String 对象一旦创建,它的值就确定了。
StringBuilder的方法
构造方法;
StringBuilder() --构建一个容量为15的空字符串构建器
StringBuilder(int capacity) --构造一个指定容器的字符串构建器
StringBuilder(String s) --构建一个指定字符串的构建器
常用的构造fan
append(String str) | 往末尾追加字符串 |
insert(int offset, String str) | 在指定位置插入字符串 |
char charAt(int index) | 返回此序列中指定索引处的char值 |
delete(int start, int end) | 删除此序列的子字符串中的字符 |
deleteCharAt(int index) | 删除指定索引处的字符 |
replace(int start, int end, String str) | 将此序列的子字符串中的字符替换为指定字符串中的字符。 |
String substring(int start) | 返回包含此字符序列中当前包含的字符子序列的新字符串 |
int indexOf(String str) | 返回指定子字符串第一次出现的字符串内的索引。 |
int lastIndexOf(String str) | 返回指定子字符串最后一次出现的字符串内的索引。 |
reverse() | 倒置字符 |
代码实例如下:
public class Test2 {
public static void main(String[] args) {
StringBuilder sb=new StringBuilder();
sb.append(12);
sb.append('c');
sb.append(true);
sb.append(new Student("王明"));
System.out.println(sb.length());
sb.insert(0, "000");//0-len StringIndexOutOfBoundsException
System.out.println(sb);
//钱,12456789.25
System.out.println(format(1245678.25));
System.out.println(sb.delete(0,2));
System.out.println(sb.replace(0, 1,"aaa"));
System.out.println(sb.reverse());
}
public static String format(double money) {
StringBuilder sb=new StringBuilder();
sb.append(money);
int index=sb.indexOf(".");
for (int i = index-3; i >0; i=i-3) {
sb.insert(i, ",");
}
return sb.toString();
}
}
class Student{
String name;
Student(String name){
this.name=name;
}
@Override
public String toString() {
return "Student [name=" + name + "]";
}
}
执行结果为:
-
小总结:
- String是常量,不可改变;StringBuffer与StringBuilder是变量
- 如果在编程的时候对字符串的操作比较频繁可以选择使用StringBuffer与StringBuilder
- 单线程的时候使用StringBuilder,多线程的时候使用StringBuffer
- StringBuffer与StringBuilder都是继承自AbstractStringBuilder。