其实在java中String并不能算是一个基本类型,回归到String的本质其实在jdk1.8以前他是一个final修饰的char数组,1.9以后他是一个final修饰的byte数组;由开发者将其封装成String类;其实我们也可以从代码中来证明String是一个类的事实:
public class String1 {
public static void main(String[] args) {
String string = "sss";
System.out.println("sss".equals(string));
}
}
true
这里我们可以看到 "sss" 这个常量可以使用equals方法进行对象相等这个判断,所以我们可以得出结论 没有字符串这个常量,有的只有String类的匿名对象。
这里使用equals我们有一个小技巧,也就是把字符串常量写在前面:
public class String1 {
public static void main(String[] args) {
String input = null; //假设是一个输入
System.out.println(input.equals("sss"));
}
}
Exception in thread "main" java.lang.NullPointerException
at String1.main(String1.java:5)
这里我们用户并没有输出,这样我们在进行比较时候就会报错, 但是如果我们
public class String1 {
public static void main(String[] args) {
String input = null; //假设是一个输入
System.out.println("sss".equals(input));
}
}
将字符串写在前面,我们可以通过equals提供一个可以回避null的判断来避免错误,字符串是一个匿名对象,只要是对象就会开辟堆内存空间,所以不会报错。
现在我们来解释一下字符串的比较
我们先来看一下int类型的 == 判断
public class String1 {
public static void main(String[] args) {
int x = 10;
int y = 10;
System.out.println(x == y);
}
}
这里代码是对基本类型进行判断。但是如果我们使用 == 进行String类的比较呢?
public class String1 {
public static void main(String[] args) {
String str1 = "ss";
String str2 = new String("ss");
System.out.println(str1 == str2);
}
}
false
首先我们避开代码不谈,我们先来说一下这个new, new的功能其实就是在内存中开辟堆内存空间,所以说str2是重新开辟了一块内存空间
所以说我们可以得出一个结论
“==” 用作数值的比较,但是如果用作对象的比较上则比较的内存的地址数值
现在我们就像判断两个对象的比较该怎么办。用equals这个类提供的方法,来直接对字符串进行比较。
public class String1 {
public static void main(String[] args) {
String str1 = "ss";
String str2 = new String("ss");
System.out.println(str1.equals(str2));
}
}
true
下面我们在继续看一段代码
public class String1 {
public static void main(String[] args) {
String str1 = "sss";
String str2 = "sss";
System.out.println(str1 == str2);
}
}
true
这里我们发现运行结果返回的是true,所以我们可以判断这里指向的是他同一块堆内存空间
主要原因是java底层提供一个专门的字符串池(字符串数组)
str1会首先在在这个字符串池中开辟一块 "sss" 的堆内存空间
这时候我们再有一个str2的时候 他会优先查找池 , 如果池中有这个数据则会优先使用池中数据,
如果没有,则会在池中在开辟内存空间
对于字符串而言在池中实现自动保存,可以提升操作性能
public class String1 {
public static void main(String[] args) {
String str1 = new String("sss");
}
}
现在我们来看一下之前这段代码。基于我们上面的分析来看。"sss"其实就是一个匿名对象开辟一块内存空间, 但是我们的关键字new的功能也会开辟一块堆内存空间,我们只会使用一块内存空间,所以由字符串常量所定义的匿名对象就会成为垃圾空间。
总结:我们使用
public class String1 {
public static void main(String[] args) {
String str1 = "sss";
}
}
这种方式来进行会相对节约一部分内存的使用
接下来让我们再次蹂躏我们之前的代码
public class String1 {
public static void main(String[] args) {
String str1 = "sss";
String str2 = new String("sss");
}
}
综合来看我们的str1是使用我们java实现的字符串池(也是堆内存)来进行存储
str2 我们是使用new开辟的堆内存空间来存储,
所以说我们的运行结果就是false
public class String1 {
public static void main(String[] args) {
String str1 = "sss";
String str2 = new String("sss");
System.out.println(str1 == str2);
}
}
综合以上就是我了解的String方面的问题
==============================================================
补充一个Integer类型的== 判断
public class String1 {
public static void main(String[] args) {
Integer a = 10;
Integer a1 = 10;
Integer b = 200;
Integer b1 = 200;
System.out.println(a == a1);
System.out.println(b == b1);
}
}
true
false
因为Integer : -127 +127 之前a a1 的值在这个区间 源码中Integer的区间定义是通过缓存实现 ,b b1的比较直接从缓存中取出,所以相同
但是b b1不在这个区间所以需要重新开辟不同的地址存储,所以导致不同