深度解析Java中String类的创建与使用
在java中String字符串不是一个基本数据类型,而是String对于char[]的组合与封装,而在C++中string同样也是封装了char数组,且以’\0’结束。
而String却不需要"\0"来结束,且String中的值不可修改,只能重新创建一个新的对象,然后用String来指向该对象。
在理解String的创建之前,我们需要先了解的常量池和堆、栈:
-
栈(stack):在函数中定义的一些基本类型的变量数据和对象的应用变量都在函数的栈内存中分配。
-
堆:堆内存用来存放由new创建的对象和数组。栈中的变量指向堆内存中的变量,这就是java中的指针
-
方法区:方法区和堆一样,被所有的线程共享。用于存储虚拟机加载的类信息、长俩个、静态变量、即时编译器编译后的代码等数据。
-
常量池:常量池值的是在编译器被确定,并被保存在已编译的.class文件中的一些数据。在程序被执行的时候,常量池回存储在方法区(method Area),而不是堆中
1. 字符串直接赋值给String类
1.1 通过==来比较两种创建String方式的地址差别
先来看看以下代码
public class test {
public static void function(){
String str1="test";
String str2=new String("test");
System.out.println(str1.equals("test"));//true
System.out.println(str1==str2);//false
}
public static void main(String[] args) {
function();
}
}
根据上面的定义
String str="test";
"test"是放在常量池中,是一个变的量,等待其他的String来调用
我们在这里创建一个str1,可以使得str1指向test
可以看作:
- 在创建str1时,str1直接找到常量池中的"test"字符串,进而引用到堆中
- 在创建str2时,堆区中先到常量池中寻找"test",如果没有,则在常量池种创建,如果有,则直接调用给堆区,但由于是在堆中创建,地址值与之前肯定会有不同
不仅如此,若是:
public class test {
public static void function(){
String str1=new String("abc");
String str2=new String("abc");
System.out.println(str1==str2);
}
public static void main(String[] args) {
function();
}
}
可见,str1和str2在这里也并不是引用同一堆区,因为new会在堆区创建一个新的对象,地址必然不会相同。
1.2 ==和equals的区别
public class test {
public static void function(){
String str1="test";
String str2=new String("test");
System.out.println(str1==str2);//false
System.out.println(str1.equals(str2));//true
}
public static void main(String[] args) {
function();
}
}
在java中,equals和= =默认都是比较地址的,但String对equals进行了重写,因而获得了一比较对象值的功能,因此这里返回的是true。
2. String与字符串的+
public class test {
public static void function(){
String str1=new String("abc");
String str2=new String("abc");
String str3=str1+str2;
String str4 ="abc"+"abc";
String str5 ="abcabc";
System.out.println(str3==str4);//false
System.out.println(str3==str5);//false
System.out.println(str4==str5);//true
}
public static void main(String[] args) {
function();
}
}
在上面的代码中,我们看到了str4和str3 明明值都是一样由连两个字符串相加而成的 ,但与str5的地址却又不一样。
- 在java中的两个String 对象相加不会在常量池中创建一个新的对象
- 但如果是两个字符串相加,在常量池中会新增一个对象,使得str4==str5
但如果我们对str1、str2稍作调整,如下:
public class test {
public static void function(){
final String str1="Uzumaki";
final String str2="Naruto";
String str3=str1+str2;
String str4="Uzumaki"+"Naruto";
System.out.println(str3==str4);//true
}
public static void main(String[] args) {
function();
}
}
我们可以看到,虽然同样也是两个不同的相加,但是给str1和str2加上了final效果完全不一样了!!
可见,常量池中对于两个final String相加获得的字符串会新创建进入常量池中