简述老生常谈的String类

字符串:String类

java中最常用的类,创建String有两种方式:

String str = new String(“Hello Word”);
String str = “Hello Word”;

由于字符串常量池优化现象,java官方建议使用第二种创建方式字符串。
在java中String是不可变的,其内部封装了一个char数组并且这个数组被final修饰。

从String类的源码中可以看出这个char数组被final所修饰

final的用途

final可以修饰类,方法,变量,被修饰的类不允许被继承,被修饰的方法只能赋值一次后不可以修改或再次赋值,被修饰的方法不可以被子类所重写。

字符串常量池

String str = new String(“Hello Word”);
String str = “Hello Word”;

还是这段代码为什么官方推荐我们使用第二种方法创建一个String
对象呢?
原因是因为在java中内存结构中有一个名叫方法区的东西,内部有一个常量池,在创建一个String对象时首先会去常量池中找对应的值如果有则使用,如果没有他会创建对象后将值存入常量池中,在java中字面量,常量或者字面量,常量的连接结果都将存储在常量池中。
其主要目的在于重用字符串,如果每次创建相同的值得对象是很浪费内存的
string的常量池优化
上面的图就可以解释为什么建议使用String s1= “abc“;的方式如果使用第二种java将会在堆内存中创建一个新的对象来引用常量池中的对象

我们来看下这段代码

String s1 = “abc”;
String s2 = new String(“abc”);
System.out.println(s1==s2);//false

    String s3 = "abc";
    System.out.println(s3==s1);//true

由于常量池优化现象我们很轻松的就能得出来结果了,我们来看看下面的代码

String s1 = “abc”;
String s2 = new String(“abc”).intern();
System.out.println(s1==s2);

这个大家觉得代码是什么结果呢?答案是true
intern():这个方法如果常量池中有对应的值将会从常量池里面获取,如果没有将会将值存放入常量池中然后 返回其引用,比较是根据自身的equals()方法。

String为什么是不可变的

String是final的所以是不可变的,那么为什么是final的呢?

  • 为了线程的安全
  • 为了实现常量池重用特性
  • 为了整个程序的安全运行
  • HashCode的不可变

1.首先String内部封装的是个被final关键字修饰的char数组,但是这仅仅是数组的引用地址不会改变,其发生作用的还有private,这样在多线程的情况下保证了线程的安全性。
2. 因为String是不可变的才能实现常量池的特性
3. 首先打开源代码可以看到String类就是final的,不允许被继承,所以无法通过继承String类来从写里面的方法
4. 由于字符串的不可变性,在创建出String类的同时HashCode就会被缓存起来,这也是为什么往往使用HashMap通常用String作为key的原因。

String的常用方法

1.charAt(int index) :返回 指定索引处的值。
2.indexOf(int ch):返回指定字符第一次出现的字符串内的索引
3.length().:返回此字符串的长度
4.startsWith(String prefix):是否指定位置开头
5.substring(int beginIndex) :截取字符串
6.toLowerCase() :将字符串转换成小写
7.toCharArray() :返回一个char数组
8.toUpperCase() :将字符串转换成大写
9.trim() :去掉收尾空白
10.split(String regex):使用正则表达式切割字符串
11.lastIndexOf(int ch) :返回最后一次出现的索引
12.endsWith(String suffix) :是否以给定字符结尾
13.
(+)号是java中唯一一个重载的运算符,在底层是用StringBuilder和append方法进行拼接然后调用toString()方法
如果进行大量的字符串拼接建议使用StringBuilder类或者tringBuffer类
这些就是本人对于String的理解,一位小白欢迎大神前来指正。

猜你喜欢

转载自blog.csdn.net/weixin_45118251/article/details/90498715