妈妈再也不用担心我的面试之String类详解

其实在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不在这个区间所以需要重新开辟不同的地址存储,所以导致不同

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值