1. String类基本特点
1.1 String类两种实例化方式
String可以直接采用赋值的形式进行处理,与基本数据类型相似。
范例:直接赋值实例化对象
代码
public class StringDemo {
public static void main(String args[]){
//str是一个对象,“hello”保存在对内存之中
String str = "hello";
System.out.println(str);
}
}
- 输出结果
hello
String本身是一个类,类中一定会提供构造方法,String类提供了以下构造方法:
- 构造:public String (String str);
第一个String是类名称,第二个String是参数类型
代码
public class StringDemo {
public static void main(String args[]){
// 该过程复合于传统做法,有类之后通过关键字new进行对象实例化
String str = new String ("hello");
System.out.println(str);
}
}
- 输出结果
hello
1.2 字符串比较
范例:基本数据类型比较
代码
public class StringDemo {
public static void main(String args[]){
int x = 10;
int y = 10;
System.out.println(x == y );
}
}
- 输出结果
true
范例:String类进行“==”比较
代码
public class StringDemo {
public static void main(String args[]){
String str1 = "hello";
String str2 = new String ("hello");
System.out.println(str1 == str2 );
}
}
- 输出结果
false
内存分析:
“==”本身比较的是数值,但如果用在对象中,那么比较的就是对象所保存的内存地址的数值。属于地址数值比较,而并没有比较对象的内容,所以不能使用。
进行内容比较,必须采用String提供的方法(暂时变形)。
- 内容比较:public boolean equals(String str);equals()区分大小写。
范例:进行字符串内容比较
代码
public class StringDemo {
public static void main(String args[]){
String str1 = "hello";
String str2 = new String ("hello");
System.out.println(str1.equals(str2));
}
}
- 输出结果
true
Q:请解释String类中“==”和“equals()”的区别。
- “==”:进行的是数值比较,比较的是两个字符串内存地址的数值;
- “equals()”: 进行字符串内容的比较。
1.3 字符串常量是String类的匿名对象
所有语言的底层上面都不可能提供有直接的字符串类型。现在所谓的字符串只是高级语言提供给用户方便开发的支持。在java中也没有直接提供有字符串常量的概念,所有使用“ “” ”定义的内容本质上都是String的匿名对象。
范例:观察字符串操作
代码
public class StringDemo {
public static void main(String args[]){
String str = "hello";
System.out.println("hello".equals(str));
}
}
- 输出结果
true
“String str = “hello” ;”本质上是将一个匿名的String类对象设置有名字,而且匿名对象保存在堆内存中。
提醒:
如果要判断用户输入的字符串是否等同于指定的字符串,那么一定要将字符串写在前面。
在数据接收时必须要考虑用户没有输入数据的问题,以下述代码为例,用户没有输入,则一定出现“NullPointException”问题。
- 比较的操作方法1:
代码
public class StringDemo {
public static void main(String args[]){
String input = null; // 假如由用户输入
System.out.println(input.equals("hello"));
}
}
- 输出结果
NullPointException
- 任何字符串常量都是String匿名对象,所以该对象永远不可能为null。
代码
public class StringDemo {
public static void main(String args[]){
String input = null; // 假如由用户输入
System.out.println("hello".equals(input));
}
}
- 输出结果
false
建议:把字符串写在前面。
1.4 String两种实例化的区别
1.采用直接赋值
String str = “hello”;
内存分析:
按照此模式继续进行如下操作。
代码
public class StringDemo {
public static void main(String args[]){
String str1 = "hello";
String str2 = "hello";
String str3 = "hello";
System.out.println(str1 == str2);
System.out.println(str1 == str3);
System.out.println(str2 == str3);
}
}
- 输出结果
true
true
true
内存分析:
从结果分析,它们指向了同一个内存地址。String类的设计使用了共享设计模式.
在JVM底层实际上会自动维护一个对象池(字符串对象池),如果采用直接赋值的模式进行String类实例化操作,那么该实例化对象将自动保存到对象池中,如果下次继续使用了直接赋值的模式,声明了String类的对象,如果对象池中有指定内容,那么将直接引用,如果没有,则开辟新的对象并保存在对象池之中以供下次使用。(所谓的对象池就是一个对象数组)
范例:观察与字符串常量比较
代码
public class StringDemo {
public static void main(String args[]){
String str = "hello";
System.out.println("hello" == str);
System.out.println("hello" == "hello");
}
}
- 输出结果
true
true
此时全部返回true,一方面与共享模式有关,一方面与JDK的版本有关,会存在差异。
2.采用构造方法
类对象采用构造方法进行实例化是标准做法。
范例:观察与字符串常量比较
代码
public class StringDemo {
public static void main(String args[]){
String str = new String ("hello");
}
}
内存分析:
如果使用构造方法将会开辟两块堆内存空间,并且有一块堆内存空间会成为垃圾空间,也会对字符串共享产生影响。
代码
public class StringDemo {
public static void main(String args[]){
// 该字符串常量并没有保存在对象池之中
String str1 = new String ("hello");
String str2 = "hello";
System.out.println(str1 == str2);
}
}
- 输出结果
false
进入对象池操作:public String intern();
代码
public class StringDemo {
public static void main(String args[]){
String str1 = new String ("hello").intern();
String str2 = "hello";
System.out.println(str1 == str2);
}
}
- 输出结果
true
内存分析:
Q:请解释String类中两种实例化方式的区别:
- 直接赋值:只会开辟一块堆内存空间,并且该字符串对象可以保存在对象池中以供下次使用。
- 构造方法:会开辟两块堆内存空间,一块会成为垃圾,并且不会保存在对象池中,需采用intern()方法手工入池。
使用直接赋值。
1.5 字符串常量不可变更
所有语言对于字符串的底层实现都是字符数组,数组最大的缺陷就是长度固定。字符串常量的内容是不可能改变的。
范例:观察如下代码
代码
public class StringDemo {
public static void main(String args[]){
String str = "hello";
str = str + "world";
str += "!!!";
System.out.println(str);
}
}
- 输出结果
helloworld!!!
以上字符串的变更时字符串对象的变更而不是字符串的内容,以上代码执行操作如下:
字符串上没有发生任何变化,但是字符串对象的引用一直在改变,而且会形成很多垃圾,由于String类的这个特点,如下代码不应出现:
代码
public class StringDemo {
public static void main(String args[]){
String str = "hello";
for(int x = 0 ; x < 1000; x++){
str += x;
}
System.out.println(str);
}
}
如果很多人都像这样使用,那么产生的垃圾就相当可观了。
2.总结
1.字符串使用采用直接赋值模式完成;
2.字符串比较使用equals()方法实现;
3.字符串内容不要改变太多。