Code Ease Code Ease
  • 个人博客网站 (opens new window)
  • 好用的工具网站 (opens new window)
  • Java核心基础
  • 框架的艺术
  • 分布式与微服务
  • 开发经验大全
  • 设计模式
  • 版本新特性
数据库系列
大数据+AI
  • xxl-job
运维与Linux
  • 基于SpringBoot和BootStrap的论坛网址
  • 基于VuePress的个人博客网站
  • 基于SpringBoot开发的小功能
  • 做一个自己的IDEA插件
程序人生
关于我
  • 分类
  • 标签
  • 归档

神秘的鱼仔

你会累是因为你在走上坡路
  • 个人博客网站 (opens new window)
  • 好用的工具网站 (opens new window)
  • Java核心基础
  • 框架的艺术
  • 分布式与微服务
  • 开发经验大全
  • 设计模式
  • 版本新特性
数据库系列
大数据+AI
  • xxl-job
运维与Linux
  • 基于SpringBoot和BootStrap的论坛网址
  • 基于VuePress的个人博客网站
  • 基于SpringBoot开发的小功能
  • 做一个自己的IDEA插件
程序人生
关于我
  • 分类
  • 标签
  • 归档
服务器
  • Java核心基础

    • 基础篇

      • Java常用关键字
      • 写了那么久的String字符串,你可能根本不懂它!
        • (一)引言
        • (二)关于String字符串
        • (三)关于字符串常量池
        • (四)String str和new String()有什么区别
        • (五)new String()方法创建了几个对象
        • (六)总结
      • 详解Java中的BIO、NIO、AIO
      • 一篇文章带你了解cloneable接口、浅拷贝、深拷贝
      • 谈一谈session和cookie的区别,以及session的实现机制
      • 什么是接口的幂等性,如何实现接口幂等性?一文搞定
      • Java16都快上线了,你该不会连Java8的特性都不会用吧?
      • Java中的拦截器和过滤器有什么区别
      • 你能保证你的代码没有异常吗?
      • 时间类有多复杂,JDK竟设计了三版
      • JavaIO的整体结构以及File类的使用
      • javaIO之字节流与字符流
    • 集合类

    • JVM虚拟机

    • Java并发

  • 框架的艺术

  • 分布式与微服务

  • 开发经验大全

  • 版本新特性

  • Java
  • Java核心基础
  • 基础篇
CodeEase
2023-09-11
目录

写了那么久的String字符串,你可能根本不懂它!

作者:鱼仔
博客首页: codeease.top (opens new window)
公众号:Java鱼仔

# (一)引言

String str和new String()有什么区别?这个问题之前在面试中有被问到过一次,当时面试结束后也写了自己关于这个题目的理解,不过最近在看Effect Java的时候发现书中也提到了关于String的用法,刚好就放到一起聊一下。

# (二)关于String字符串

String应该是Java中最常用的一个对象,他不是八种基本数据类型的其中之一,但是我随便翻了一下项目代码,用String定义的变量超过百分之八十。

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

    /** Cache the hash code for the string */
    private int hash; // Default to 0
}
1
2
3
4
5
6
7
8

关于String的几个基本知识点在String类的源码定义中就能看到:

1、在JDK8中,String实例的值是通过char数据存储的。(JDK9时,String实例的存储由char变成了byte数组,原因是使用byte数组可以减少一半的内存)

2、String类被final修饰,因此String不能被继承,value变量被final修饰,因此String实例不能被修改

3、String类实现了Serializable, Comparable, CharSequence接口。

# (三)关于字符串常量池

字符串常量池是虚拟机中的内容,但是接下来的几个问题需要用到,就简单了解下。为了让String字符串可以复用,Java虚拟机中设置了一种叫做字符串常量池的东西。

Java为了避免产生大量的String对象,设计了一个字符串常量池。工作原理是这样的,创建一个字符串时,JVM首先为检查字符串常量池中是否有值相等的字符串,如果有,则不再创建,直接返回该字符串的引用地址,若没有,则创建,然后放到字符串常量池中,并返回新创建的字符串的引用地址。因此看下面这段代码:

String s1="abc";
String s2="abc";
System.out.println(s1==s2);  //返回true
1
2
3

返回的结果就是true,因为指向了同一个对象。

关于字符串常量池的位置,在不同版本的JDK中有所不同:

JDK1.7之前字符串常量池属于运行时常量池的一部分,存放在方法区

JDK1.7之后字符串常量池被从方法区拿到了堆中

# (四)String str和new String()有什么区别

回到开始的问题,String str和new String()有什么区别?区别在于,String str创建的字符串保存在字符串常量池中,并且可复用。new String()创建的字符串按照最标准的对象创建方式,生成在堆中,并且一个new String会在堆中创建一个对象。下面这张图应该可以把这个流程讲清楚。

1.jpeg

s1==s2返回true,s1==s3返回false。

# (五)new String()方法创建了几个对象

又是个好问题,这道题的答案是一个或者两个。

写一段代码:

public class test {
    public static void main(String[] args) {
        String s1=new String("ab");
    }
}
1
2
3
4
5

编译后通过javap -v test.class查看字节码:

2.png

1、在常量池中创建了ab对象,位置在##3

3.png

2、在堆中创建了ab对象

这样的情况下创建了两个对象,一个在常量池中,一个在堆中。

再写一段代码:

public class test {
    public static void main(String[] args) {
        String s1="ab";
        String s2=new String("ab");
    }
}
1
2
3
4
5
6

同样的方式查看字节码:

4.png

首先s1="ab"在常量池中创建了ab对象,存放在常量池的##2位置里,这个时候new String就只在堆中创建了一个String对象,常量池中因为已经有了,就不会再创建了。

这样的情况下,只创建了一个对象。

# (六)总结

虽说怎么写代码都能实现一定的功能,但是有时候换种写法可以省下很多资源。比如将:

String str=new String("abc")
1

写成:

String str="abc"
1

虽然只是小小的改动,但是在频繁调用的方法中,就有可能避免创建了百万个String实例。

对于有一定开发经验的程序员,建议可以读一下《Effect-Java》,里面有许多写代码的更优方式。

我是鱼仔,我们下期再见!

上次更新: 2025/04/29, 17:22:06
Java常用关键字
详解Java中的BIO、NIO、AIO

← Java常用关键字 详解Java中的BIO、NIO、AIO→

最近更新
01
AI大模型部署指南
02-18
02
半个月了,DeepSeek为什么还是服务不可用
02-13
03
Python3.9及3.10安装文档
01-23
更多文章>
Theme by Vdoing | Copyright © 2023-2025 备案图标 浙公网安备33021202002405 | 浙ICP备2023040452号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式