1.String 类的对象实例化方式
a.直接赋值:
String str = "Hello";
b.构造方法赋值:
String str = new String ("Hello");
2.字符串相等比较
a. “==”操作
String str1 = new String ("Hello");
String str2 = "Hello";
System.out.println(str1 == str2);
输出结果:false
b. public boolean equals(Object anObject)方法比较
String str1 = new String ("Hello");
String str2 = "Hello";
System.out.println(str1.equals (str2));
结果:true
内存分析:
由图可以很清楚的看到两者的地址不一致。
总结:
“==”本身用于数值比较,用于对象之中进行操作的时候比较的是对象保存的内存地址数值,而非对象内容。而public
boolean equals(Object anObject)方法可以进行对象内容比较的操作。
观察public boolean equals(Object anObject)方法在底层的运行过程:
public boolean equals(Object anObject) {
if (this == anObject) { // 判断内容是否相同
return true;
}
if (anObject instanceof String) { // 判断类型是否相同
String aString = (String)anObject;
if (coder() == aString.coder()) {
return isLatin1() ? StringLatin1.equals(value, aString.value)
: StringUTF16.equals(value, aString.value);
}
}
return false;
}
注:
JVM的共享设计:采用直接赋值的方法进行String类的赋值操作,该实例化对象将自动保存到String类的对象池中,
下次有访问使用直接赋值方式进行String类对象声明,若对象池中有指定内容,则直接进行引用而不用开辟新的内存空间。
验证:
String str1 = "Hello";
String str2 = "Hello";
System.out.println(str1 == str2);
结果:true
内存分析:
3.字符串常量是String类的匿名对象
字符串常量是String类的匿名对象,即所有用 ” ” 定义的内容本质上都是String类的匿名对象。
验证:
String str = "Hello";
System.out.println("Hello".equals(str));
结果:true
4.String类两种赋值操作比较
直接赋值的内存分析前面已经有了,现在看看构造方法的内存分析。
a.构造方法内存分析 String str = new String (“hello”);
分析:()优先级最高,先在内存中开辟空间存放Hello,然后new关键字又开辟新的空间,两块空间地址不一致,最后造成内存空间浪费。
b.构造方法的手工入池操作 public String intern()方法
API中关于intern()方法的介绍:
例如:
String str1 = new String ("Hello").intern();
String str2 = "Hello";
System.out.println(str1.equals (str2));
结果:true
5.Sting类字符串常量不可变更
String str = " Hello";
String str += " World";
String str += " !";
System.out.println(str);
结果:Hello World !
内存分析:
运行中造成大量内存空间浪费!!!
6.字符数组与String类
char [] data = {"H","e","l","l","o"};
String str1 = new String(data);
String str2 = "Hello";
System.out.println(str1 == str2);
结果:false
内存分析:
7.关于字符串在堆内存中的存储位置
看以下的代码:
String str = new String("ab");
System.out.println("ab" == str);
System.out.println("ab" == str.intern());
System.out.println(str == str.intern());
结果:
false
true
false
由结果可以看出字符串是直接存放在常量池里的。
内存分析:
8.String类构造器
1.StringBuilder类,初始容量是16个字符,可以自行指定长度,也可以动态添加。
常用方法:
·StringBuilder append(String str)方法,将str指定的字符串追加到字符串生成器中。
用法:声明的字符串生成器.append(str);
·StringBuilder append(StringBuffer sb)方法,将sb指定的字符串缓存StringBuffer的值追加到字符串生成器中。
用法:声明的字符串生成器.append(StringBuffer sb);
例如:StringBuffer sb = new StringBuffer("xyz");
StringBuilder builder = new StringBuilder();
builder.append(sb);
·StringBuilder insert(int offset,String str)方法,将指定的字符串str添加到offset指定的位置。
用法:声明的字符串生成器.inser(int offset,String str);
例如:String s1 = "int";
String s2 = "ser";
StringBuilder builder = new StringBuilder(s1);
builder.insert(2,s2);
System.out.println(builder);
结果:insert
· StringBuilder delete(int start,String end)方法,移除字符串生成器中指定位置的字符串。
用法:声明的字符串生成器.delete(int start,String end(不包括));
·String toString()方法,将字符串生成器转换为字符串,转换后字符串生成器的值不变。
用法:声明的字符串生成器的值.toString();
2.StringBuilder类和StringBuffer类的使用场景
·StringBuilder类用于单线程中
·StringBuffer类用于多线程中
总结
String类使用原则:
1.字符串使用直接赋值法;
2.字符串比较使用equals()方法;
3.字符串不应改变太多。
4.对于循环的的对字符进行扩充或删减操作,要使用StringBuilder的append方法和delete方法。
参考资料: