字符串常量池

简介: 字符串常量池

一、字符串常量池
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);
}

1
2
3
4
5
6
7
8
9
上面两种创建String对象的方式相同吗?

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

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

public static void main(String[] args) {

    String s1 = "abc";
    String s2 = "abc";
    System.out.println(s1 == s2);

}
1
2
3
4
5

在直接用字面常量赋值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);
}

1
2
3
4
5
6

我们可见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);
}

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

二、字符串的不可变性
String是一种不可变对象. 字符串中的内容是不可改变。
String的源码中,注解中写到String是一个常量,不可修改.

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

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

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

方便实现字符串对象池. 如果 String 可变, 那么对象池就需要考虑写时拷贝的问题了.
不可变对象是线程安全的.
不可变对象更方便缓存 hash code, 作为 key 时可以更高效的保存到 HashMap 中.
三、字符串修改
字符串是不能修改的,每次修改都会创建新对象,效率非常低下.

public static void main(String[] args) {

    String str = "wo"+"yao"+"jin"+"da"+"chang";
    System.out.println(str);
}

1
2
3
4

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

我们会发现创建了许多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);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

我们发现在对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);
}

1
2
3
4
5

2.reverse
字符串逆置

public static void main(String[] args) {

    StringBuilder stringBuilder = new StringBuilder("abcd");
    stringBuilder.reverse();
    System.out.println(stringBuilder);
}

1
2
3
4
5

3.delete
删除指定范围内的字符

public static void main(String[] args) {

    StringBuilder stringBuilder = new StringBuilder("abcd");
    stringBuilder.delete(0,2);
    System.out.println(stringBuilder);
}

1
2
3
4
5

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);
}

1
2
3
4
5
public static void main(String[] args) {

    //append拼接字符串
    String str = "abc";
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append(str);
    System.out.println(stringBuilder);
}

1
2
3
4
5
6
7

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);
}

1
2
3
4
5
6

四、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个

相关文章
|
XML C# 数据格式
The data at the root level is invalid. Line 1, position 1.
The data at the root level is invalid. Line 1, position 1.
323 0
|
C++ 容器
必知的技术知识:emplace
必知的技术知识:emplace
|
Linux
Linux cp命令:复制文件和目录
cp 命令,主要用来复制文件和目录,同时借助某些选项,还可以实现复制整个目录,以及比对两文件的新旧而予以升级等功能。 cp 命令的基本格式如下: [root@localhost ~]# cp [选项] 源文件 目标文件 -a:相当于 -d、-p、-r 选项的集合,这几个选项我们一一介绍; -d:如果源文件为软链接(对硬链接无效),则复制出的目标文件也为软链接; -i:询问,如果目标文件已经存在,则会询问是否覆盖; -l:把目标文件建立为源文件的硬链接文件,而不是复制源文件; -s:把目标文件建立为源文件的软链接文件,而不是复制源文件; -p:复制后目标文件保留源文件的属性(包括
2077 6
|
安全 数据库 C++
Python Web框架比较:Django vs Flask vs Pyramid
【10月更文挑战第6天】本文比较了Python中三个最受欢迎的Web框架:Django、Flask和Pyramid。Django功能全面,适合快速开发;Flask灵活轻量,易于上手;Pyramid介于两者之间,兼顾灵活性和可扩展性。文章分析了各框架的优缺点,帮助开发者根据项目需求和个人偏好做出合适的选择。
331 4
|
搜索推荐 开发者
熊猫比分-专业体育赛事直播app/网页搭建
体育赛事直播APP已成为体育迷观看和讨论赛事的重要渠道。其核心功能包括:1) 实时直播,支持转播、录播、回放,确保低延迟、高流畅度和优质画质;2) 比分数据分析,提供首发阵容、历史对战等信息;3) 用户互动,支持评论、打赏及私聊;4) 主播中心,允许用户申请成为主播并获平台支持。
|
Cloud Native Go 开发者
使用WPS自动化转换办公文档: 将Word, PowerPoint和Excel文件转换为PDF
使用WPS自动化转换办公文档: 将Word, PowerPoint和Excel文件转换为PDF
759 0
|
存储 算法 数据处理
LabVIEW FPGA开发NI sbRIO-9607高精度数字滤波器
LabVIEW FPGA开发NI sbRIO-9607高精度数字滤波器
257 5
|
机器学习/深度学习 人工智能 安全
「随笔」开源大模型与闭源大模型,你更看好哪一方?
开源与闭源AI模型各有利弊。开源促进创新、透明度和学习,但可能有安全风险和质量不一;闭源则保护IP、提供定制服务,但可能限制创新和透明度。混合策略,如基础开源加高级服务闭源,成为平衡点。选择取决于创新、产权、透明度和商业目标。
1104 0
|
人工智能 安全 搜索推荐
【专栏】虚拟现实(VR)如何重塑教育与培训的未来
【4月更文挑战第27天】本文探讨了虚拟现实(VR)如何重塑教育与培训的未来,分为三个部分:VR在教育的应用现状、提升学习体验和培训效果的方式,以及面临的挑战与展望。目前,VR已逐渐融入课堂,提供沉浸式学习体验,如历史和医学培训。通过沉浸感、交互性、安全模拟训练和个性化学习,VR提升了学习效果。然而,高成本、内容不足及真实性的验证仍是挑战。随着技术进步,VR将在教育领域发挥更大作用,与5G、AI结合,创造更高效的学习体验。
611 1
|
安全 Java 数据库
Spring Boot中的Kotlin语言支持
Spring Boot中的Kotlin语言支持