字符串常量池与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"); 

这项行代码分别创建多少个对象?(之前常量池没有存储过任何字符串)

  1. 2个
  2. 6个
  • 96
    点赞
  • 74
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 90
    评论
Java语言程序设计 第6章 字符串 Java语言程序设计(第3版)第06章-字符串全文共31页,当前为第1页。 6.1.1 1 String类 2 3 主要内容 Java语言程序设计(第3版) 格式化输出 StringBuilderJava语言程序设计(第3版)第06章-字符串全文共31页,当前为第2页。 6.1.1 String类 Java语言程序设计(第3版) Java语言程序设计(第3版)第06章-字符串全文共31页,当前为第3页。 6.1.1 使用字符串字面值创建String对象。 String str = "Java is cool"; 使用String类的构造方法。 String str = new String("Java is cool"); 这两种方式有区别,后面说明。 创建字符串对象 Java语言程序设计(第3版) Java语言程序设计(第3版)第06章-字符串全文共31页,当前为第4页。 6.1.1 字符串基本操作 Java语言程序设计(第3版) 字符串在内存的表示。设有下面声明: String str = new String("Java is cool"); 这个字符串共有12个字符,每个字符有一个下标,下标从0开始。 str.charAt(6)返回字母s。 Java语言程序设计(第3版)第06章-字符串全文共31页,当前为第5页。 6.1.1 字符串基本操作 Java语言程序设计(第3版) 问题描述 编写一个方法判断字符串是否是回文串。 public static boolean isPalindrome(String s) 思路:取出字符串的第一个和最后一个比较,若不相同,程序结束,返回false。若相等,比较第二个字符和倒数第二字符,直到比较到字符串的中间字符为止,若都相等,则是回文,返回true。 Java语言程序设计(第3版)第06章-字符串全文共31页,当前为第6页。 6.1.1 字符串查找 Java语言程序设计(第3版) int indexOf(int ch) int lastIndexOf(int ch) 找到返回下标值,找不到返回-1。 Java语言程序设计(第3版)第06章-字符串全文共31页,当前为第7页。 6.1.1 字符串转换为数组 Java语言程序设计(第3版) char[] toCharArray() byte[] getBytes() Java语言程序设计(第3版)第06章-字符串全文共31页,当前为第8页。 6.1.1 字符串比较 Java语言程序设计(第3版) 不能使用"=="号来比较字符串内容是否相等 比较内容是否相等: boolean equals(String str) boolean equalsIgnoreCase(String str) s1 s2 Hello Hello 字符串常量池 s1 s2 Hello Java语言程序设计(第3版)第06章-字符串全文共31页,当前为第9页。 6.1.1 字符串比较 Java语言程序设计(第3版) 比较大小: int compareTo(String str) 小于,返回值小于0 等于,返回值等于0 大于,返回值大于0 判断前缀、后缀和包含 boolean startsWith(String prefix) boolean endsWith(String suffix) boolean contains(String str) String s1 = "ABC"; String s2 = "ABE"; System.out.println( s1.compareTo(s2); 输出-2 Java语言程序设计(第3版)第06章-字符串全文共31页,当前为第10页。 6.1.1 字符串的拆分和组合 Java语言程序设计(第3版) String[] split(String regex) static String join(CharSequence delimiter, CharSequence... elements) boolean matches(String regex) Java语言程序设计(第3版)第06章-字符串全文共31页,当前为第11页。 6.1.1 String对象的不变性 Java语言程序设计(第3版) 一旦创建一个String对象,就不能对其内容进行改变。 s Hello,world s.replace('o','A'); HellA,wArld s = s.substring(0,6).concat("Java"); Hello,Java s s.toUpperCase(); HELLO,JAVA System.out.println(s); String s = "Hello,wo

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

熬夜磕代码丶

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

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

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

打赏作者

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

抵扣说明:

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

余额充值