String
String在前面一直用于声明一个字符串,,从其给出的命名要求来看,String类定义时单词的首字母大写,所以String本身也是一个类本类,但是此类在使用时却有很多的要求,而且此类在java中也算是一个比较特殊的类,这次就讲解String类的作用及使用上的一些限制。
一. 实例化String对象
【直接为String对象赋值】
public class StringDemo01{
public static void main(String[] args){
String name="LiXingHua" //实例话String对象
System.out.println("姓名:"+name);
}
}
运行结果为:
姓名:LiXingHua
在String的使用上还有另外一种形式的实例化方法,就是直接调用String类中的构造方法,在String类存在以下的构造方法:
public String(String original)
所以上例中还可以通过以下方法来编写
【用第二种方式实例化】
public class StringDemo02{
public static void main(String[] args){
String name=new String("LiXingHua");
System.out.println("姓名:"+name);
}
}
结果如下:
姓名:LiXingHua
上述两种方法效果相同,都可使用。区别在后面会讲到。
二. String的内容比较
对于基本数据类型可以通过“==”进行内容的比较
【使用“==”进行比较】
public class StringDemo03{
public static void main(String[] args){
int x=30;
int y=30;
System.out.println("两个数字的比较结果:"+(x==y));
}
}
程序运行结果为:
两个数字的比较结果:true
可以发现,两个数字的比较结果相等,同理字符串的比较操作类似。
【比较两个字符串的内容】
public class StringDemo04{
public static void main(String args[]){
String str1 = "hello" ; // 直接赋值
String str2 = new String("hello") ; // 通过new赋值
String str3 = str2 ; // 传递引用
System.out.println("str1 == str2 --> " + (str1==str2)) ; // false
System.out.println("str1 == str3 --> " + (str1==str3)) ; // false
System.out.println("str2 == str3 --> " + (str2==str3)) ; // true
}
};
运行结果为:
str1 == str2 --> false
str1 == str3 --> false
str2 == str3 --> true
上例中String类型的内容都相同,但是比较结果却有所不同,是因为每个String对象保存的内容是堆内存的引用地址,真正的内容保留在堆内存中。如果要只判断字符串的内容是否相同,可以用下面的方法来判断:
public class StringDemo05{
public static void main(String args[]){
String str1 = "hello" ; // 直接赋值
String str2 = new String("hello") ; // 通过new赋值
String str3 = str2 ; // 传递引用
System.out.println("str1 equals str2 --> " + (str1.equals(str2))) ; // true
System.out.println("str1 equals str3 --> " + (str1.equals(str3))) ; // true
System.out.println("str2 equals str3 --> " + (str2.equals(str3))) ; // true
}
};
运行结果为:
str1 equals str2 --> true
str1 equals str3 --> true
str2 equals str3 --> true
因为equals()方法只是将内容进行比较,所以返回结果为true。
三. String两种实例化方式的区别
String有两种实例化方式,一种是通过直接赋值的方式,另一种是使用标准化的new调用构造方法完成实例化。这两种方式的区别,以及用那种好吶?
在讨论这个问题之前,要明确的是一个字符串就是一个String类型的匿名对象,匿名对象就是已经开辟了堆内存空间并可以直接使用的对象。
直接赋值的方法:
String str1=”Hello”
这段代码实际上就是把在堆内存中开辟好的堆内存使用空间的使用权给了str1对象。使用这种方法的一个好处就是如果一个字符串已经被一个名称所引用,则以后再有相同的字符串声明时,就不会再开辟新的堆内存空间,而继续使用已经开辟好的堆内存。
【例】
public class StringDemo07{
public static void main(String args[]){
String str1 = "hello" ; // 直接赋值
String str2 = "hello" ; // 直接赋值
String str3 = "hello" ; // 直接赋值
System.out.println("str1 == str2 --> " + (str1==str2)) ; // true
System.out.println("str1 == str3 --> " + (str1==str3)) ; // true
System.out.println("str2 == str3 --> " + (str2==str3)) ; // true
}
};
运行结果:
str1 == str2 --> true
str1 == str3 --> true
str2 == str3 --> true
从结果看出,所有结果都为“true”,也就是说三个字符串指向的堆内存地址空间都是同一个,所以,当String使用直接赋值的方式之后,只要是以后声明的字符串内容相同,则都不会再开辟新的内存空间。如下图:
下面为使用new String()的方式实例化String对象的代码:
public class StringDemo08{
public static void main(String args[]){
String str1 = new String("hello") ;
}
};
使用new关键字,不管如何都会开辟一个新的空间,但是此时,此空间的内容还是hello,上面的代码实际上是开辟了两个内存空间,但是真正使用的只是一个使用关键字new开辟的空间,另外一个就是垃圾空间。如图:
通过上面的对比,对于字符串的操作就采用直接赋值的方式完成,而不需要采用构造方法传递字符串的方式完成,这样就可以避免产生垃圾空间。当然,在String类中也存在一些其它的构造方法。
四. 字符串的内容不可改变
在使用String类进行操作时还有一个特性是特别重要的,那就是字符串的内容一旦声明则不可改变。
【修改字符串的内容】
public class StringDemo09{
public static void main(String args[]){
String str = "hello" ; // 声明字符串
str = str + " world!!!" ; // 修改字符串
System.out.println("str = " + str) ;
}
};
运行结果为:
str = hello world!!!
从程序的运行结果发现,String对象的内容确实已经修改了,但是内容不是真正的修改,而是通过内存地址的“断开-连接”变化完成的,而字符串中的内容并没用任何的变化。如图:
(String类的常用方法在这里就不在叙述, 详细情况可以在JDK文档中查看)