一. 实例化String对象:
1. 实例化String类的两种方式;(String首字母大写,则一看就知道它为一个类!)
前面我说了,实例化对象不止一种方法,只要能开辟一个堆内存空间,则都能为实例化成功,而使用new关键字只是其中的一种!
第一种方法:直接实例化
比如:
class StringDemo1{
public static void main(String[] args){
String name = "Nishuibaichuan";
System.out.println("姓名:" + name);
}
}
第二种方法:使用new关键字实例化
比如:
class StringDemo2{
public static void main(String[] args){
String name = new String("Nishuibaichuan");
System.out.println("姓名:" + name);
}
}
2. 两种实例化方式的区别:
(1)首先,一个字符串就是String 的匿名对象.为什么这样说啊?因为我们知道类中的方法,在另一个类中使用的话,必须的先实例化该类的对象,从而来调用该方法.用对象.方法()调用;
验证:
public class StringTest2 {
public static void main(String[] args) {
System.out.println("nishui".equals("nishui"));
}
}
运行结果: true
由以上代码可知:一个字符串就是String 的匿名对象!
String name = "Nishuibaichuan";故这样实例化String对象,就表示将一个堆内存空间的指向传给了栈内存(name)空间.
在String类的实例化方式中,直接赋值的好处就是可以有效的节省内存空间的使用,因为赋值后的字符串,只要内容一样,他们就指向同一个堆内存空间。为什么这么说啊?因为,采用直接赋值的方式存储一个字符串后,再存储另一个相同的字符串时,他发现在这个常量池中已经有了这个字符串的存在,那么他就不在开辟另一个堆内存空间存放此字符串了,而是让此字符串指向那个和他相同的字符串存储的堆内存空间!
举例验证:
public class StringTest2 {
public static void main(String[] args) {
String str1 = "nishui";//直接定义
String str2 = "nishui";//使用new关键字定义
String str3 = "nishui";//引用传递
System.out.println("str1 == str2: " + (str1 == str2) );
System.out.println("str1 == str3: " + (str1 == str3) );
System.out.println("str2 == str3: " + (str2 == str3) );
}
}
运行结果:
str1 == str2: true
str1 == str3: true
str2 == str3: true
(2)使用new String()的方式实例化对象:
public class StringTest2 {
public static void main(String[] args) {
String str2 = new String("nishui");
}
由以上代码和以上概念可知:我们在上面曾经说过,一个字符串就是String的匿名对象,那么既然是对象那么肯定就用堆内存空间的指向啊,但是根据上面代码知道使用了new 关键字,而new关键字的作用也是开辟一个堆内存空间,那么这杨的话,岂不是重复开辟堆内存空间了?这样的话,其中开辟的一个堆内存空间就为垃圾空间,等待着java的垃圾回收机制Gc回收!
总结区别:使用直接直接赋值的方式实例化String对象, 只需要一个开辟一个堆内存空间,而使用new String()的话,则需要开辟2个堆内存空间,而其中的一个堆内存空间还会变为垃圾空间,所以,在开发中最好使用直接赋值的方式为对象开辟堆内存空间.
二: == 和equals()方法的比较
1. == :他比较的是地址值是否相等;
举例:
public class StringTest1 {
public static void main(String[] args) {
String str1 = "nishui";//直接定义
String str2 = new String("nishui");//使用new关键字定义,存放在ox127中(顺便取得地址值)
String str3 = str2;//引用传递str3和str2指向同一块内存空间,都指向ox127地址
System.out.println("str1 == str2: " + (str1 == str2) );
System.out.println("str1 == str3: " + (str1 == str3) );
System.out.println("str2 == str3: " + (str2 == str3) );
}
}
运行结果:
str1 == str2: false
str1 == str3: false
str2 == str3: true
由上代码可知:String str1 = "nishui";直接定义,存放在0x123地址中(顺便取得地址值),
String str2 = new String("nishui");使用new关键字定义,存放在ox127地址中(顺便取得地址值);
String str3 = str2;//引用传递str3和str2指向同一块内存空间,都指向ox127地址;
由此可以知道 "==" 比较的是地址,因为str2和str3指向同一地址,故返回true,其余返回false;
2 . String类中的 equals()方法:他比较的是内容是否相等;
举例:
package Nsbc.club;
public class StringTest1 {
public static void main(String[] args) {
String str1 = "nishui";//直接定义
String str2 = new String("nishui");//使用new关键字定义
String str3 = str2;//引用传递
System.out.println("str1.equals(str2): " + (str1.equals(str2)) );
System.out.println("str1.equals(str3): " + (str1.equals(str3)) );
System.out.println("str2.equals(str3): " + (str2.equals(str3)) );
}
}
运行结果:
str1.equals(str2): true
str1.equals(str3): true
str2.equals(str3): true
由此可以知道equals():他比较的是内容是否相等,因为str1,str2和str3的值相等,故返回true;
三. 字符串的内容不可改变
实际上字符串内容的改变,并不是其内容真的改变了,而是内存空间的引用关系的改变.
举例:
public class StringTest3 {
public static void main(String[] args) {
String str = "nishui";
str = str + "baichuan";//其实这并没有改变字符串的内容,这只是改变了堆内存地址的指向!
System.out.println(str);
}
}
在开发中尽量少用这样的方法,因为这样的话要断开连接2次,这样的话性能很低,如果非要使用的话,就该使用StringBuffer类,笔者会在下一篇文章中写出.