*阿炮的Java笔记002号*-最厉害的类是String

老生常谈…对于大佬们根本都不用看的博客!
对于像我这种菜鸡还是得一步一步的来!如果有错误请大佬们指点指点!

为什么说String是最厉害的

String这个类高频的使用,以前的String的基础是char数组,后来因为经常使用变成了byte数组。因此可能这个篇文章会很长!

String

  1. 具有不可变性
       private final char value[];  //前期
       private final byte[] value;  //后期

final 修饰的char(byte)数组 不可被更改

  1. 创建方式
       String s1 = "hello";
       String str = new String("hello");
       String s1 = new String("1");
       String s2=s1.intern();

问题:

       String s1 = "hello";
       String s2 = new String("hello");
       System.out.println(s1==s2); //false

       String s1 = "hello";
       String s2 = new String("hello");
       String s3 = s2.intern();
       System.out.println(s1==s3); // true

为什么s2经过intern()方法变成s3后,s1和s3就相等了呢?
因为String拥有一个常量池。
众所周知,==进行的是内存地址的比较。
①:

  1. 如果字符串常量池中已经有“hello”,则通过new创建了一个对象。
  2. 如果字符串常量池中不存在“hello”,则通过new创建了一个对象,一个是在解析常量池的时候JVM自动创建。

②:
intern方法会从字符串常量池中查询当前字符串是否存在,若存在则返回其引用;若不存在就会将当前字符串放入常量池中,并返回其引用。只需牢记返回的是字符串常量池的引用(即哈希表中的值)即可。

  1. 创建了两个对象实例,其引用一个在字符串常量池中,一个返回给s,如上图。
  2. intern()方法会会从字符串常量池中查询当前字符串是否存在,发现存在,返回的是字符串常量池的引用(地址)。
  3. s3是赋值为字符串常量池的引用。 故 s2和s3地址一样。

String Pool(字符常量池)

字符串常量池(String Pool)是一个固定大小的 HashTable,故不存在两个相同的字符串。
String Pool是放在本地内存的,是C++写的,里面放的是字符串对象的引用,真实的字符串对象是在堆里。

String Pool的位置

Java 6及以前,字符串常量池存放在永久代。
Java 7 字符串常量池的位置调整到Java堆内。
Java8元空间,字符串常量在堆。
由此可见String Pool因为性能原因进行了几次改革。
提问: 为什么将StringTable从永久代调整到堆中 ?

  1. 永久代的默认比较小
  2. 永久代垃圾回收频率低

使用String Pool的优点

为了避免频繁的创建和销毁对象而影响系统性能,实现了对象的共享。
节省内存空间:编译阶段就把所有的字符串文字放到一个常量池中,常量池中所有相同的字符串常量被合并,只占用一个空间。
比较字符串时,== 比 equals()快。

String真的具有不可变性吗?

String s = "abc";  
System.out.println(s);//abc
s = "123";  
System.out.println(s);//123

看到这段,可能对String是不可变对象产生了疑惑,因为从打印结果可以看出,s的值的确改变了。
其实,因为s只是一个String对象的引用,并不是String对象本身。

  1. 首先先在方法区的运行时常量池创建一个String对象"abc",然后在Java栈中创建一个String对象的引用s,并让s指向"abc" 。在这里插入图片描述

  2. 在方法区的运行时常量池创建一个新的String对象"123",然后让引用s重新指向这个新的对象,而原来的对象"abc"还在内存中,并没有改变。
    在这里插入图片描述
    由此可见String具有不可变性。但是我们能不能通过一些奇技将String进行改变呢?
    答案是:是可以的,我们可以通过反射是可以修改String这种不可变对象的。让s始终指向同一个String对象,进行反射操作之后,String对象的内容是可以发生了变化。不信的话,可以在CSDN找找其他大佬是否写过!!

有的人会问:String拼接是怎么回事?与上同理不过运用到了StringBuilder的这个对象。

三小只:String,Stringbuffer,StringBuilder

String

  • String类是一个不可变的类,一旦创建就不可以修改。
  • String是final类,不能被继承
  • String实现了equals()方法和hashCode()方法

StringBuffer

  • 继承自AbstractStringBuilder,是可变类。
  • StringBuffer是线程安全的
  • 可以通过append方法动态构造数据。

StringBuilder

  • 继承自AbstractStringBuilder,是可变类。
  • StringBuilder是非线性安全的。
  • 执行效率比StringBuffer高。
    注意:面试高频考点

toString()、String.valueOf()、(String)强转

  1. toString(),可能会抛空指针异常
    因为java.lang.Object类里已有public方法.toString(),所以java对象都可以调用此方法。但在使用时要注意,必须保证object不是null值,否则将抛出NullPointerException异常。
  2. String.valueOf(),返回字符串“null”
    不会出现空指针异常,而且是静态的方法,直接通过String调用即可。
    如果为null,String.valueOf()返回结果是字符串“null”。而不是null。
  3. (String)强转,不推荐
    将Object类型转为String类型,使用(String)强转时,最好使用instanceof做一个类型检查,以判断是否可以进行强转,否则容易抛出ClassCastException异常。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

史上最菜的山炮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值