您的位置 首页 java

字符串常量池与StringBuilder

文章目录

一、 字符串 常量池

 public  static   void  main( string [] args) {
 
        String s1 = "abc";
        String s2 = "abc";
        String s3 = new String("abc");
        String s4 = new String("abc");
        System.out.println(s1 == s2);
        System.out.println(s1 == s3);
        System.out.println(s3 == s4);
    }  

上面两种创建 String 对象的方式相同吗?

Java 程序中,“ ” 双引号 引起来的字面类型的常量经常频繁使用,为了使程序的运行速度更快、更节省内存,Java为8种基本数据类型和 String类 都提供了常量池。

1.使用 字符常量 直接赋值:

 public static void main(String[] args) {
 
        String s1 = "abc";
        String s2 = "abc";
        System.out.println(s1 == s2);
  }  

在直接用字面常量赋值String时,先在常量池里找,是否有这个字符串,如果没有则创建,我们发现常量池并没有abc,所以我们创建一个“abc”。

当第二次创建”abc”字符串赋给s2时直接指向就行.

s1和s2指向的是同一块引用,所以s1 == s2。

2.通过new创建String类对象:

只要new对象,它的引用就是唯一的.

使用常量串创建String类型对象的效率更高,而且更节省空间。

3.intern方法:

intern 是一个native方法(Native方法指:底层使用C++实现的,看不到其实现的源代码),该方法的作用是手动将创建的String对象添加到常量池中。

 public static void main(String[] args) {
 
        char[] ch = new char[]{
 'a','b','c'};
        String s1 = new String(ch);
        String s2 = "abc";
        System.out.println(s1 == s2);
    }  

我们可见s1 和 s2指向不同的引用

 public static void main(String[] args) {
 
        char[] ch = new char[]{
 'a','b','c'};
        String s1 = new String(ch);
        s1.intern();
        String s2 = "abc";
        System.out.println(s1 == s2);
    }  

intern()方法是将s1中的引用放入常量池中.当s2创建时,就会指向常量池的那个引用.

二、字符串的不可变性

String是一种不可变对象. 字符串中的内容是不可改变。

String的源码中,注解中写到String是一个常量,不可修改.

我们在来看String类型是如何存储字符串的

可能有人说因为被final修饰,所以不能修改,首先这是一个很大的误区,final修饰只能说明value引用的对象不能修改,而不是说value引用的值不能修改.

我们随便打开一个String的方法,这里打开的是 toUpperCase 方法,可以发现:所有涉及到修改字符串内容的方法都是创建一个新对象返回.

String为什么要设计成不可变的?

  1. 方便实现字符串对象池. 如果 String 可变, 那么对象池就需要考虑写时拷贝的问题了.
  2. 不可变对象是 线程 安全的.
  3. 不可变对象更方便缓存 hash code , 作为 key 时可以更高效地保存到 HashMap 中.

三、字符串修改

字符串是不能修改的,每次修改都会创建新对象,效率非常低下.

 public static void main(String[] args) {
 
        String str = "wo"+"yao"+"jin"+"da"+"chang";
        System.out.println(str);
    }  

当然是可以正常输出的,我们看一下汇编.

我们会发现创建了许多 StringBuilder 对象,去拼接字符串,这样效率十分低下。

 public static void main(String[] args) {
 
        long start = System.currentTimeMillis();
        String s = "";
        for(int i = 0; i < 10000; ++i){
 
            s += i;
        }
        long end = System.currentTimeMillis();
        System.out.println(end - start);
        start = System.currentTimeMillis();
        StringBuffer sbf = new StringBuffer("");
        for(int i = 0; i < 10000; ++i){
 
            sbf.append(i);
        }
        end = System.currentTimeMillis();
        System.out.println(end - start);
        start = System.currentTimeMillis();
         stringBuilder  sbd = new StringBuilder();
        for(int i = 0; i < 10000; ++i){
 
            sbd.append(i);
        }
        end = System.currentTimeMillis();

        System.out.println(end - start);
    }  

我们发现在对String进行修改时,String与 StringBuffer 和StringBuilder相差几百倍.

四、StringBuilder与StringBuffer的方法

这里都是StringBuffer和StringBuilder的一些方法.

1. append

拼接字符串

 public static void main(String[] args) {
 
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("wo yao jin da chang!");
        System.out.println(stringBuilder);
    }  

2.reverse

字符串逆置

 public static void main(String[] args) {
 
        StringBuilder stringBuilder = new StringBuilder("abcd");
        stringBuilder.reverse();
        System.out.println(stringBuilder);
    }  

3.delete

删除指定范围内的字符

 public static void main(String[] args) {
 
        StringBuilder stringBuilder = new StringBuilder("abcd");
        stringBuilder.delete(0,2);
        System.out.println(stringBuilder);
    }  

String与StringBuilder相互转换:

String和StringBuilder最大的区别在于String的内容无法修改,而StringBuilder的内容可

以修改。频繁修改字符串的情况考虑使用StringBuilder

1.String变为StringBuilder

 public static void main(String[] args) {
 
        //调用StringBuilder 构造方法 
        String str = "abc";
        StringBuilder stringBuilder = new StringBuilder(str);
    }  
 public static void main(String[] args) {
 
        //append拼接字符串
        String str = "abc";
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(str);
        System.out.println(stringBuilder);
    }  

1.StringBuilder变为String

我们可以看一下StringBuilder的 toString ()方法返回的是一个String对象.

 public static void main(String[] args) {
 
        //StringBuilder的toString()方法
        StringBuilder stringBuilder = new StringBuilder("abc");
        String str = stringBuilder.toString();
        System.out.println(str);
    }  

四、StringBuilder与StringBuffer区别

String、StringBuffer、StringBuilder的区别:

1.String的内容不可修改,StringBuffer与StringBuilder的内容可以修改.

2.StringBuffer与StringBuilder大部分功能是相似的

3.StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操作

StringBuffer中的每个方法加入了 synchronized ,它就相当于是一把锁,只要有第一个人访问这个方法,那么这个方法就只能等第一个人访问完成之后,剩下的人才能访问.

 String str = new String("abc"); 
String str = new String("ab") + new String("c");  

文章来源:智云一二三科技

文章标题:字符串常量池与StringBuilder

文章地址:https://www.zhihuclub.com/200326.shtml

关于作者: 智云科技

热门文章

网站地图