Java基础之String类

字符串String 可以说是最常用的类
一般问题:
String类的不可变怎么做到的?为什么?

首先String类是由final修饰的,不可被继承。
其次String类的char[]数组 是被私有化的,被private修饰,且未提供get()/set()方法。

原因:
1. String类使用太频繁,所有为了搭配字符串常量池使用。
2. 为了线程安全,在多线程环境下 final 可以保证安全
3. 为了同一个String类的hashcode唯一,只需要计算一次就缓存了hashcode,方便做为map的key。

String和StringBuilder和StringBuffer区别

不同点
4. String类的char[]是私有的,其它俩都是可被修改的。
5. String类的每个方法都是返回一共新的String。
6. StringBuilder是单线程下的,而StringBuffer做了多线程安全性的设计
7. 因为StringBuilder和StringBuffer都是可修改的。所以会有扩容机制。  
8. StringBuilder扩容机制:如果当前字符+新增字符大于数组大小扩容,扩容为当前数组*2 + 2. 直接new一个新数组,然后System.arraycopy

相同点
都是不可被继承的类。

深入理解
主要就是字符串常量池的问题
一些代码判断

String a = "123";//在字符串常量池创建一个对象
String b = "123";//直接从字符串常量池中拿
System.out.println(a == b);//true


String b = new String("123");//在字符串常量池创建一个对象,另外在堆创建一个对象
String a = "123";//获取字符串常量池中的
String c = b.intern();//通过b获取字符串常量池中的
System.out.println(a == b);//false
System.out.println(a == c);//true

这俩个示例,主要是说明,字符串常量池的作用。如果字符串常量池有某个对象,之后通过字面量的方式获取的都是同一个。
代码示例2

String a = new String("123") + new String("321"); 
String b = "123321";
String c = a.intern();
System.out.println(a == b);//false
System.out.println(c == b);//true
a 会在堆上创建 "123" "321" "123321" 但是因为没有字面量,所以字符串常量池中并无"123321"

String a = new String("123") + new String("321");
String c = a.intern();
String b = "123321";
System.out.println(a == b);//true
System.out.println(c == b);//true

a == b 是 调用了a.intern() 之后不会再字符串常量池创建一个新的对象,而是直接记录了堆上"123321"的引用。 这就导致 a == b 因为是同一个引用。

原因:是因为堆内存的改变。 在1.6之前,字符串常量池在方法区由永久代实现。1.7被移动到了堆里面。所以在一个堆中就可以直接记录指针,不必浪费资源。

总结:主要就是字符串常量池位置的改变,导致字符串常量池创建对象的规则变化。如果堆中已经存在对象,直接保存指向对象的指针,而不新创建一个对象。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值