1.String类
- String对象代表不可变的Unicode字符序列,因此可以将String对象成为“不可变对象”;
- 字符串内容全部存储到value[]数组中,而变量value是final类型的,也就是常量(只能被初始化一次),这是“不可变对象”的典型定义方式
subString()是字符串的截取操作
在遇到字符串常量之间的拼接时,编译器会做出优化,在编译期间就会完成字符串的拼接,因此,在使用“==”进行String对象之间的比较时,要特别注意
常量池:是指在编译期被确定,并被保存在已编译的.class文件中的一些数据,它包括了关于类、方法、接口等中的常量,也包括字符串常量。
例1:
public static void main(String[] args) {
String str1 = "abcde";
String str2 = "abcde";
System.out.println(Integer.toHexString(str1.hashCode()));
System.out.println(Integer.toHexString(str2.hashCode()));
str1 = str1+"fg";
System.out.println(Integer.toHexString(str1.hashCode()));
}
运行结果:
内存分析:
例2:
public static void main(String[] args) {
String str1 = "hello";
String str2 = "world";
String str3 = "helloworld";
System.out.println(str1+str2);
System.out.println(str3);
System.out.println(str3 == (str1+str2));
System.out.println(str3.equals(str1+str2));
System.out.println(str3 == ("hello"+"world"));
}
Java中直接使用" == "比较的是两个字符串的引用地址;
equals方法比较两字符串的内容;
运行结果:
内存分析:
例3:
public static void main(String[] args) {
String str1 = "hello";
String str2 = new String("hello");
String str3 = "he"+"llo";
String str4 = new String("he")+new String("llo");
System.out.println(str1 == str2); //false;
System.out.println(str1 == str3); //true;
System.out.println(str3 == str2); //false;
System.out.println(str4 == str3); //false;
}
运行结果:
内存分析:
- str1 :在编译时被放在类文件常量池中;
- str2 :在堆中产生一个新的对象;
- str3 :字符串拼接在编译时完成,此时常量池已经有一个str1指向的“hello”,str3直接指向常量池中的“hello”;
- str4:先在堆中各自产生一个对象,最后产生一个新的对象,地址存放在str4中
例4:
public static void main(String[] args) {
String str1 = new String("hello");
String str2 = "hello";
System.out.println(str1 == str2);//false
String str3 = "he"+new String("llo");
System.out.println(str1 == str3);
System.out.println(str2 == str3);
String str4 = "he"+"llo";
System.out.println(str4 == str2);
char[] array = {'h','e','l','l','o'};
String str5 = new String(array);
System.out.println("=============");
System.out.println(str1 == str5);
System.out.println(str2 == str5);
System.out.println(str3 == str5);
System.out.println(str4 == str5);
}
运行结果:
内存分析:
例5:
public static void main(String[] args) {
StringBuffer stringBuffer = new StringBuffer("Hello");
System.out.println(stringBuffer);
System.out.println(Integer.toHexString(stringBuffer.hashCode()));
stringBuffer.append("world");//追加
System.out.println(stringBuffer);
System.out.println(Integer.toHexString(stringBuffer.hashCode()));
System.out.println("=============stringBuilder==============");
StringBuilder stringBuilder = new StringBuilder("Hi");
System.out.println("java");
System.out.println(Integer.toHexString(stringBuilder.hashCode()));
stringBuilder.append("world");//追加
System.out.println(stringBuilder);
System.out.println(Integer.toHexString(stringBuilder.hashCode()));
}
运行结果:
例6:
2.StringBuffer和StringBuilder
StringBuffer和StringBuilder非常类似,均代表可变的字符序列,这两个类都是抽象类AbstractStringBuilder的子类,用法几乎一模一样
abstract class AbstractStringBuilder implements Appendable, CharSequence {
/**
* The value is used for character storage.
*/
char[] value;
下面代码省略;
}
- AbstractStringBuilder内部也是一个字符数组,但这个字符数组没有用final修饰,随时可以修改,所以StringBuilder和StringBuffer称为“可变字符数组”
- StringBuilder和StringBuffer的区别
(1)StringBuffer是JDK1.0提供的类,线程安全,做线程同步检查(单线程),效率低;
(2)StringBuilder是JDK1.5提供的类,线程不安全,不做线程同步检查(多线程),因此效率较高。 - StringBuilder的常用方法:
1.重载的public StringBuilder append(…)方法
可以为该StringBuilder对象添加字符序列,仍然返回自身对象
2.方法public StringBuilder delete(int start,int end)
可以删除从start开始到end-1为止的一段字符序列,仍然返回自身对象
3.方法public StringBuilder deleteCharAt(int index)
移除此序列指定位置上的char,仍然返回自身对象
4.重载的public StringBuilder insert(…)方法
可以为该StringBuilder对象指定位置插入字符序列,仍然返回自身对象
5.方法public StringBuilder reverse()
用于将字符序列逆序,仍然返回自身对象
6.方法public String toString()
返回此序列中数据的字符串表示形式
和String类类似的方法:
public int indexOf(String str)
public int indexOf(String str,int fromIndex)
public String substring(int start)
public String substring(int start,int end)
public int length()
char charAt(int index)