当前位置: 首页 > news >正文

Java字符串知多少:String、StringBuffer、StringBuilder

一、String

1、简介

  • String 是 Java 中使用得最频繁的一个类了,不管是作为开发者的业务使用,还是一些系统级别的字符使用, String 都发挥着重要的作用。
  • String 是不可变的、final的,不能被继承,且 Java 在运行时也保存了一个字符串池(String pool) ,就使得 String 变得很特殊。
  • 实现三个接口:java.io.Serializable, Comparable, CharSequence

2、String对象两种创建方法

// 1:编译时就确定了字符串的内容
String strComplier = "A";
// 2:new,只有运行时才能确定字符串的内容
String strNew = new String("A");
  • String strComplier = “A”;

Java 程序在运行的时候会维护着一个常量池,编译期生成的各种字面量和符号引用会在类加载后进入方法区的运行时常量池。对于上述这种实现字符串的方式就可以在编译的时候确定字符串的内容,因此这一行生成的内存结构就如下图。

在这里插入图片描述

不严谨的讲:虚拟机栈中的 strComplier 存储的就是 A 在常量池中的地址

  • String strNew = new String(“A”);

因为使用的 new 的方式,所以这句代码只有运行的时候才能确定字符串的内容。而对于 new 关键字,java 是将对象的实例数据存放上的,但是又因 String 常量池的存在,因此实际上在堆上的 String 对象的数据又指向了字符串常量池。

在这里插入图片描述

不严谨的讲:虚拟机栈中的 strNew 存储的就是 strNew 这个对象在堆内存的地址,而 strNew 中的字符串数据又指向了常量池中的 A

3、比较: == 和 equals()

  • ==

    比较两个对象的引用是否相等,也就是说比较两个地址是否相等

//true : 地址相同
String a = "A";
String a1 = "A";
System.out.println(a1 == a); //指向的都是 A 的地址,地址相同,返回的是 true
//false : 地址不同,在堆中是两个不同的对象,虽然指向常量池中的同一个值 A
String b = new String("A");
String b1 = new String("A");
System.out.println(b==b1);//分别指向的是在堆内存上的不同对象的地址,地址不同,返回的是 false
//false : 地址不同
String c = "A";
String c1 = new String("A");
System.out.println(c == c1);//一个指向常量池,一个指向堆,返回 false
//true : 地址相同
String d = "A";
String d1 = d; 
System.out.println(d == d1);//把d中的 常量池地址 赋给d1,返回 true
//true : 地址相同
String a = "A1";
String a1 = "A" + 1;//编译时已确定
System.out.println(a == a1);//true//false : 地址不同
String b = "A1";
String b1 = "A";
String b2 = b1 + 1;//编译时不确定
System.out.println(b == b2);//false

在这里插入图片描述

  • equals

    比较的两个对象是否相等,也就是说是同一个对象,在jvm堆内是惟一的

    String类对equals()方法进行了重写,只有值相等,才为true

//equals方法源码
public boolean equals(Object anObject) {//判断是否是相同对象if (this == anObject) {return true;}//判断anObject是否是String类型if (anObject instanceof String) {//        String aString = (String)anObject;//判断编码是否相同if (coder() == aString.coder()) {////比较两个字符串是否完全相等return isLatin1() ? StringLatin1.equals(value, aString.value)                : StringUTF16.equals(value, aString.value);}} return false;
}

在这里插入图片描述

String stringCompiler = "A";
String stringNew = new String("A");
StringBuilder stringBuilder = new StringBuilder("A");
StringBuffer stringBuffer = new StringBuffer("A");
//不是相同对象
System.out.println(stringCompiler == stringNew);  // false
//不是相同对象,但都是String类型,编码、字符值都相同
System.out.println(stringCompiler.equals(stringNew));  // true
//stringBuilder不是String类型
System.out.println(stringCompiler.equals(stringBuilder));  // false
//stringBuffer不是String类型
System.out.println(stringNew.equals(stringBuffer));   // false
比较==equals()
String s1 = new String(“java”);
String s2 = new String(“java”);
false
s1、s2在堆中是不同的对象,地址不同
虽然都指向了常量池中的’'java"
true
String类对equals()进行了重写
只要值相同,就返回true
String s1 = new String(“java”);
String s2 = s1;
true
同一对象,地址相同,值相同
true
同一对象,地址相同,值相同
String s1 = “java”;
String s2 = “java”;
true
编译时值已确定
指向常量池中同一地址
true
值相同

4、final

  • String 是 final ,也就是String 是不可变的。即一个 String 对象创建之后所有对它修改后的字符串,都是新生成的 String 对象。
  • String 设计成 final 主要有如下原因:
    • 实现字符串常量池,只有当字符串是不可变时字符串池才有可能实现,字符串池的实现可以在运行时节约很多 heap 空间,因为不同的字符串变量都指向池中的同一个字符串,即可以实现多个变量引用 JVM 内存中的同一个字符串实例,如果字符串不是不变的,String interning 将不能实现(String interning 是指对不同的字符串仅仅只保存一个,即不会保存多个相同的字符串),因为这样的话,如果变量改变了它的值,那么其它指向这个值的变量的值也会一起改变。
    • 安全问题,在系统中有很多地方都是以字符串的形式存在的,比如数据库的用户名,Socket 的主机和端口,当你在调用其他方法,比如调用一些系统级操作之前,可能会有一系列校验,如果是可变类的话,可能在你校验过后,其内部的值被改变了,可能引起严重的系统崩溃问题。
    • 缓存提升性能,String 大量运用在哈希的处理中,由于 String 的不可变性,可以只计算一次哈希值,然后缓存在内部,后续直接取就好了,字符串的处理速度要快过其它的键对象,这就是 HashMap 中的键往往都使用字符串的原因。
    • 线程安全,因为字符串是不可变的,所以是多线程安全的,同一个字符串实例可以被多个线程共享。这样便不用因为线程安全问题而使用同步。

5、编码与解码

//编码
String.getBytes()//方法是得到一个操作系统默认的编码格式的字节数组。
String.getBytes(String decode)//方法会根据指定的decode编码返回某字符串在该编码下的byte数组表示//解码    
new String(byte[] b,String decode)//按照指定的方法编码
  • 示例
//编码解码一致,正确输出
byte[] b_gbk = "中".getBytes("GBK"); 
String s_gbk = new String(b_gbk,"GBK"); 
System.out.println(s_gbk);//中
//编码解码不一致,输出乱码
byte[] b_gbk = "中".getBytes("GBK"); 
String s_utf8 = new String(b_gbk,"UTF-8"); 
System.out.println(s_utf8);//��

二、StringBuffer

  • final,不能被继承,不能有子类
  • 线程安全
  • 通过append、insert进行字符串的操作
  • 实现接口:java.io.Serializable, CharSequence

三、StringBuilder

  • final,不能被继承,不能有子类
  • 线程不安全
  • 通过append、insert进行字符串的操作
  • 实现接口:java.io.Serializable, CharSequence

四、三者比较

比较StringStringBufferStringBuilder
继承性finalfinalfinal
实现接口Serializable
Comparable
CarSequence
Serializable
CarSequence
Serializable
CarSequence
速度
线程安全性线程安全线程安全线程不安全
常用方法equals()append()
insert()
append()
insert()
适用场景少量的字符串操作多线程下的大量操作单线程下的大量操作

相关文章:

Java字符串知多少:String、StringBuffer、StringBuilder

一、String 1、简介 String 是 Java 中使用得最频繁的一个类了,不管是作为开发者的业务使用,还是一些系统级别的字符使用, String 都发挥着重要的作用。String 是不可变的、final的,不能被继承,且 Java 在运行时也保…...

中国20强(上市)游戏公司2022年财报分析:营收结构优化,市场竞争进入白热化

易观:受全球经济增速下行的消极影响,2022年国内外游戏市场规模普遍下滑。但中国游戏公司凭借处于全球领先水平的研发、发行和运营的能力与经验,继续加大海外市场布局,推动高质量发展迈上新台阶。 风险提示:本文内容仅代…...

如何自学C++编程语言,聊聊C++的特点,别轻易踩坑

为什么现在有那么多C培训班呢?因为这些培训班可以为学生安排工作,而外包公司因为缺人,需要做很多项目,可能需要在全国各地分配不同的程序员去干不同的项目,因此需要大量的程序员入职。这样,外包公司就会找培…...

算法Day07 | 454.四数相加II,383. 赎金信,15. 三数之和, 18. 四数之和

Day07 454.四数相加II383. 赎金信15. 三数之和18. 四数之和 454.四数相加II 题目链接:454.四数相加II 寻找两个数组之和,是否与另外两个数组之和有特定的关系。 因为数值可能跨度太大,选择使用下标表示为对应的数值大小,会很浪费…...

ps抠图、抠头发去背景等

方法一:背景橡皮擦 一、很早之前我们使用的是魔术棒工具,但现在我们可以使用Photoshop 有内置的“背景橡皮擦” 步骤: 第1步:在Photoshop中打开需要修的图。 第2步:单击并按住工具栏…...

计算机组成原理基础练习题第一章

有些计算机将一部分软件永恒地存于只读存储器中,称之为() A.硬件    B.软件C.固件    D.辅助存储器输入、输出装置以及外界的辅助存储器称为() A.操作系统    B.存储器 C.主机      D.外围设备完整的计算机系…...

[PyTorch][chapter 34][池化层与采样]

前言: 这里主要讲解一下卷积神经网络中的池化层与采样 目录 DownSampleMax poolingavg poolingupsampleReLu 1: DownSample 下采样,间隔一定行或者列进行采样,达到降维效果 早期LeNet-5 就采样该采样方式。 LeNet-5 2 Max pooling 最大值采样…...

Java进阶-字符串的使用

1.API 1.1API概述 什么是API ​ API (Application Programming Interface) :应用程序编程接口 java中的API ​ 指的就是 JDK 中提供的各种功能的 Java类,这些类将底层的实现封装了起来,我们不需要关心这些类是如何实现的,只需要…...

接口自动化框架对比 | 质量工程

一、前言 自动化测试是把将手工驱动的测试行为转化为机器自动执行,通常操作是在某一框架下进行代码编写,实现用例自动发现与执行,托管在CI/CD平台上,通过条件触发或手工触发,进行回归测试&线上监控,代替…...

谷歌浏览器network error解决方法

很多用户在使用谷歌浏览器时候会出现network error网页提示,很多用户不知道该如何处理这一问题,其实解决方法不止一种,小编整理了两种谷歌浏览器network error解决方法,一起来看看吧~ 谷歌浏览器network error解决方法&#xff1…...

自动化测试如何做?接口自动化测试框架必备的9个功能,测试老鸟总结...

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 当你准备使用一个…...

ANR原理篇 - ANR原理总览

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 例如:第一章 Python 机器学习入门之pandas的使用 文章目录 系列文章目录前言ANR流程概览ANR触发机制一、service超时机制二、broadcast超时机制三、provider超…...

新版Mamba体验超快的软件安装

在一文掌握Conda软件安装:虚拟环境、软件通道、加速solving、跨服务器迁移中详细介绍的conda的基本使用和遇到问题的解决方式,也提到了mamba作为一个替代工具,可以很好的加速conda的solving environemnt过程。但有时也会遇到一个很尴尬的问题…...

LDAP配置与安装

LDAP配置与安装 一、安装LDAP1、安装OpenLDAP及相关依赖包2、查看OpenLDAP版本3、配置OpenLDAP数据库4、设置OpenLDAP的管理员密码5、修改配置文件5.1. 修改{2}hdb.ldif文件5.2. 修改{1}monitor.ldif文件5.3. 修改{-1}frontend.ldif文件 6、验证LDAP的基本配置7、修改LDAP文件权…...

1-Linux环境安装JDK

Linux环境安装JDK 准备: ① Linux 环境 本文中Linux环境为 CentOS Linux 7 可使用以下命令查询 linux 系统版本: hostnamectl② 准备JDK包 进入官网 https://www.oracle.com/java/technologies/downloads/#java17下载对应jdk包 此处使用以前下载的旧…...

通胀数据回落助金价小幅回升

现货黄金窄幅震荡,目前交投于2032.92美元/盎司附近。隔夜美国通胀数据弱于市场预期,市场对美联储6月份加息预期降温,美元指数走弱,金价一度冲高至2050关口附近,不过,随后金价回吐全部涨幅,并一度…...

正则表达式的基本语法以及技巧和示例

正则表达式(Regular Expression)是一种强大的文本模式匹配工具,它使用特定的语法规则来描述和匹配字符串。在实际应用中,正则表达式可以用于搜索、替换、验证和分割文本数据。本文将详细解释正则表达式的语法和常用的使用示例。 …...

蓝牙耳机怎么挑选?小编分享2023畅销蓝牙耳机排行榜

蓝牙耳机怎么挑选?蓝牙、音质、续航、佩戴是蓝牙耳机选购时最重要的四大维度,这几年随着技术的成熟体验有了很大改善,但挑选的时候仍然要仔细对比,不然容易踩雷。小编根据销量整理了蓝牙耳机排行榜,一起看看最受消费者…...

Linux快照太有趣了!

1.首先介绍一下什么是Linux快照 VMware 的菜单栏中有虚拟机快照这个选项,形象来说快照就相当于一个备份文件,记录的是虚拟机运行到某一节点时的状态,在虚拟机的使用过程中如果发生了意外,比如系统崩溃或系统异常,此时…...

【改进粒子群优化算法】自适应惯性权重粒子群算法(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage)&#xff1a…...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...

微信小程序之bind和catch

这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

在rocky linux 9.5上在线安装 docker

前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制

在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...

AI,如何重构理解、匹配与决策?

AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...

Go 并发编程基础:通道(Channel)的使用

在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...

GraphQL 实战篇:Apollo Client 配置与缓存

GraphQL 实战篇:Apollo Client 配置与缓存 上一篇:GraphQL 入门篇:基础查询语法 依旧和上一篇的笔记一样,主实操,没啥过多的细节讲解,代码具体在: https://github.com/GoldenaArcher/graphql…...