之前的讲解过程中说到并使用过,String
可以采用直接赋值的方式进行处理,这一点类似于基本数据类型。这种方式较为常用。
范例:直接赋值实例化对象
public class StringDemo {
public static void main(String args[]) {
// str是一个对象,那么“hello”就应该保存在堆内存之中
String str = "Hello" ;
System.out.println(str) ;
}
}
String是一个类,类中必定提供有构造方法。而在String类中恰好提供了如下构造方法:
public String (String str) ;
public class StringDemo {
public static void main(String args[]) {
// 既然String是类,可以通过关键字new进行对象实例化
String str = new String("Hello") ;
System.out.println(str) ;
}
}
众所周知,基本数据类型变量通过==
进行是否相等的比较,那么String呢?
范例:观察String直接使用==的情况
public class StringDemo {
public static void main(String args[]) {
// 通过关键字new进行对象实例化
String str1 = "Hello" ;
String str2 = new String("Hello") ;
System.out.println(str1 == str2) ;
}
}
两个字符串内容是相同的,但是输出却是false,为什么?需要内存分析:
要知道,==
进行的是数值的比较(char
比较的是字符的编码。也是数值)。如果==
用在String之中,所比较的就是两个对象(str1、str2)所保存的内存地址的数值,而并没有比较对象的内容。
这里暂时先学习这个方法的变形:public boolean equals(String str) ;
范例:进行String对象内容比较
public class StringDemo {
public static void main(String args[]) {
// 通过关键字new进行对象实例化
String str1 = "Hello" ;
String str2 = new String("Hello") ;
System.out.println(str1.equals(str2)) ;
}
}
==
和equals()
的区别==
进行的是数值比较,比较的是两个字符串对象的内存地址数值;equals()
可以进行字符串内容的比较在任何语言的底层上面都不会提供有直接的字符串类型,现在所谓的高级语言只是为了方便用户开发所提供的一个支持。所以在Java中本身也没有直接提供字符串常量的概念,所有使用""
定义的内容本质上来讲都是String类的匿名对象。
范例:观察字符串操作
public class StringDemo {
public static void main(String args[]) {
String str = "Hello" ;
System.out.println(str.equals("Hello")) ; // 通过str对象调用String类
System.out.println("Hello".equals(str)) ; // "Hello"是匿名对象,当然也可以调用String类中的任意方法
}
}
可以看出String str = "Hello" ;
就是给一个匿名对象"Hello"
设置名字str
,并且匿名对象一定保存在堆内存之中。
提醒:在日后的开发过程中,如果要判断用户的输入是否等于指定的字符串,一定要把指定字符串写在前面。
public class StringDemo {
public static void main(String args[]) {
// 用户输入操作暂时没讲解,这里暂时用input代替
String input = null ; // 用户输入为空
System.out.println(input.equals("Hello")) ;
}
}
在进行用户数据接收的时候必须要考虑用户没有输入数据的问题,这时会出现如图所示异常。
因此要把指定字符串写在前面。因为任何的字符串常量都是String类的匿名对象,所以该对象永远不可能为null。
public class StringDemo {
public static void main(String args[]) {
// 用户输入操作暂时没讲解,这里暂时用input代替
String input = null ; // 用户输入为空
System.out.println("Hello".equals(input)) ;
}
}
两种实例化模式中使用哪一种更好?二者的区别?
public class StringDemo {
public static void main(String args[]) {
// str是一个对象,那么“hello”就应该保存在堆内存之中
String str = "Hello" ;
}
}
public class StringDemo {
public static void main(String args[]) {
// str是一个对象,那么“hello”就应该保存在堆内存之中
String str1 = "Hello" ;
String str2 = "Hello" ;
String str3 = "Hello" ;
System.out.println(str1 == str2) ;
System.out.println(str1 == str3) ;
System.out.println(str2 == str3) ;
}
}
可以看出,创建新对象并没有开辟新的内存空间,而是三个栈内存指向同一个堆内存。
使用new实例化对象的方法会开辟两块内存空间,其中有一块堆内存空间成为垃圾内存空间。除此之外,也会对字符串共享产生问题。
通过22、字符串相等比较我们知道,通过直接赋值和new实例化的同一个字符串无法比较用==
比较是否相同,因为new出来的对象没有入池。
但是并不意味着new出来的字符串不能进入到对象池保存,关键:可以手工处理——使用String类中的public String intern() ;
方法进行手工入池操作。
public class StringDemo {
public static void main(String args[]) {
String str1 = "Hello" ;
String str2 = new String("Hello").intern() ;
System.out.println(str1 == str2) ;
}
}
intern()
方法手工入池。字符串一旦定义不可改变。
再次强调:在任何语言的底层实现的都是字符数组,数组的最大缺陷:长度固定,所以在定义字符串常量的时候本身它的内容是不可改变的。
范例:观察程序
public class StringDemo {
public static void main(String args[]) {
String str1 = "Hello" ;
str1 += "World" ;
System.out.println(str1) ;
}
}
equals()
方法实现;