【我与Java的成长记】之String类详解

在这里插入图片描述

系列文章目录

能看懂文字就能明白系列
C语言笔记传送门
Java笔记传送门
🌟 个人主页:古德猫宁-

🌈 信念如阳光,照亮前行的每一步


文章目录

  • 系列文章目录
    • 🌈 *信念如阳光,照亮前行的每一步*
  • 前言
  • 一、字符串构造
  • 二、String类的特性
  • 三、StringBuilder和StringBuffer
    • 总结
  • 三、StringBuilder一些常见的方法


前言

String 类是 Java 中用于表示字符串的核心类之一。它提供了丰富的方法来操作字符串,包括连接、拆分、替换、查找、截取等,使得字符串处理变得简单和高效。

本节重点:

  • 理解String为什么具有不可变性
  • StringBuffer、StringBuilder和String的区别
  • 为什么StringBuilder比StringBuffer总是快了一毫秒
  • 模拟简单String类方法的实现

一、字符串构造

常用的字符串构造有以下三种:

public static void main(String[] args) {//new一个String对象String s1 = new String("hello");//使用常量串进行构造String s2 = "hello";//使用字符数组进行构造char[] arr = {'h','e','l','l','o'};String s3 = new String(arr);}

在这里特别注意的是:

  1. s1,s2,s3存储的是一个地址,由地址指向所引用的对象,可是当我们打印s1,s2,s3的时候,却发现输出的结果是“hello”
    在这里插入图片描述
    原因是String调用了toString的构造方法,我们打开String的源码看看
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    最后是print输出“hello”。

  2. String类是引用类型,内部并不存储字符串本身,在String类的实现源码中,String类实例变量如下:
    在这里插入图片描述
    我们可以看到,String类中有两个成员,一个是数组value[],一个是整型hash(默认为0),当我们调试的时候,我们可以看到是value[]存储的“hello”
    在这里插入图片描述
    如下图所示,我们可以这样理解:
    在这里插入图片描述

  3. 字符串常量后面没有以\0标记结尾,我们可以调用length看下字符串的长度。
    在这里插入图片描述
    在这里插入图片描述

二、String类的特性

String 对象具有不可变性的,即一旦创建就不能被修改。这种不可变性使得字符串在多线程环境下更安全,也可以被用作常量,有助于提高代码的可读性和可维护性。
我们先来看以下代码:

public static void main(String[] args) {String s = "hello";s = s.concat(" java");System.out.println(s);}

输出结果:
在这里插入图片描述
这里很多人可能就有疑问了,不是说String对象具有不可变性吗,为什么这里还可以被改变呢?
虽然字符串的内容看起来变了,从“hello”变成了“hello java”,但实际上,原来的字符串还是没有改变,而是得到了一个新的字符串了,它的内容是“hello java”。

具体如图所示:
在这里插入图片描述

为什么字符串具有不可变性呢?
一方面,String类中的字符实际保存在内部维护的value字符数组中,另一方面,String类被final修饰,表明该类不能被继承,而且value也被final修饰,表明value自身的值不能改变,既不能引用其他字符数组,但是其引用空间中的内容可以修改。

特别注意的是:字符串不可变是因为其内部保存字符的数组被final修饰了,因此不能改变,这句话是错误的,不是因为String类自身,或者其内部value被final修饰而不能被修改。

而是因为value[]被private修饰,我们无法拿到value,自然不能通过value去修改值。
在这里插入图片描述

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

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

三、StringBuilder和StringBuffer

注意:尽量避免直接对String类型对象进行修改,因为String类是不能修改的,所有的修改都会创建新对象,效率非常低。
所以为了方便字符串的修改,java中又提供了StringBuilder和StringBuffer类。

StringBuffer和StringBuilder虽然也封装了一个字符数组,但与String不同,其定义如下:

char[] value;

与String不同的是,它并不是被final所修饰,所以是可以修改的。

我们可以做个简单的测试:

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("String:"+(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("StringBuffer:"+(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("StringBuilder:"+(end - start));}

在这里插入图片描述
从结果可以看出,在对String类进行修改时,效率是非常慢的,因此:尽量避免对String的直接修改,如果要修改尽量使用StringBuffer或者StringBuilder。

注意:String和StringBuilder类不能直接转换。如果要想互相转换,可以采用如下原则:

  • String变为StringBuilder:利用StringBuilder的构造方法或者append()方法。
  • StringBuilder变为String:利用toString()方法。

总结

为什么StringBuilder和StringBuffer比String快那么多呢?

简单来说String 是不可变的,每次对 String 进行操作(如连接、拼接、替换等),都会生成一个新的 String 对象,原始的 String 对象不变。这样会频繁地创建新的对象,产生大量的临时对象,导致内存开销和垃圾回收压力增大。
StringBuffer 和 StringBuilder 是可变的,它们提供了修改字符串内容的方法,而不是创建新的对象。这样可以减少对象的创建和销毁,提高了性能。
StringBuffer 和 StringBuilder 内部都是使用可变长度的字符数组(char[])来存储字符串内容。它们的方法都是基于字符数组的操作,如扩容、复制、移动等。这种直接操作字符数组的方式可以提高性能,避免了额外的对象创建和拷贝操作。

为什么StringBuilder比StringBuffer总是快了一毫秒呢?

原因是StringBuilder 是非线程安全的,而StringBuffer 是线程安全的,StringBuffer 中的方法是同步的,即它们被设计为可以安全地在多线程环境中使用。这是通过在每个方法上使用 synchronized 关键字来实现的,以确保同一时刻只有一个线程可以访问 StringBuffer 的方法。
在这里插入图片描述
当方法被 synchronized 修饰时,就意味着该方法在同一时间只能被一个线程执行,其他线程需要等待。

三、StringBuilder一些常见的方法

由于StringBuilder和StringBuffer两大类大部分功能是相同的,这里简单介绍StringBuilder一些常用的方法,其他方法可自行浏览:StringBuilder在线文档

方法说明
StringBuilder append(String str)在尾部追加,相当于String的+=,可以追加:boolean,char,char[],double,float,int,long,Object,String,StringBuilder的变量
char charAt(int index)获取index位置的字符
int length()获取字符串的长度
int capacity()获取底层保存字符串空间总的大小
void ensureCapacity(int mininmunCapacity)扩容
void setChar(int index,char ch)将index位置的字符设置为ch
int indexOf(String str)返回str第一次出现的位置
int indexOf(String str,int fromIndex)从fromIndex位置开始查找str第一次出现的位置
StringBuffer deleteCharAt(int index)删除index位置的字符
StringBuffer delete(int start,int end)删除[start,end)区间内的字符
StringBuffer replace(int start,int end,String str)将[start,end)位置的字符替换为str
String substring(int start)从star开始一直到末尾的字符以String的形式返回
StringBuffer reverse()反转字符串

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2774252.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

深入浅出:Golang的Crypto/SHA256库实战指南

深入浅出&#xff1a;Golang的Crypto/SHA256库实战指南 介绍crypto/sha256库概览主要功能应用场景库结构和接口实例 基础使用教程字符串哈希化文件哈希化处理大型数据 进阶使用方法增量哈希计算使用Salt增强安全性多线程哈希计算 实际案例分析案例一&#xff1a;安全用户认证系…

【芯片设计- RTL 数字逻辑设计入门 13 -- generate_for 和 for】

文章目录 generate_forverilog codetestbench code仿真波形 for 循环verilog code仿真波形错误小结 generate_for 在某个module中包含了很多相似的连续赋值语句&#xff0c;请使用generata…for语句编写代码&#xff0c;替代该语句&#xff0c;要求不能改变原module的功能。 …

假设检验的过程

假设检验的核心思想是小概率事件在一次实验中不可能发生&#xff0c;假设检验就是利用小概率事件的发生进行反正。学习假设检验&#xff0c;有几个概念不能跳过&#xff0c;原假设、p值 1.原假设 假设检验的基本过程如下&#xff1a; 1&#xff09;做出一个假设H0&#xff0c…

IEC 104电力规约详细解读(三) - 遥信

1.功能简述 遥信&#xff0c;、即状态量&#xff0c;是为了将断路器、隔离开关、中央信号等位置信号上送到监控后台的信息。遥信信息包括&#xff1a;反应电网运行拓扑方式的位置信息。如断路器状态、隔离开关状态&#xff1b;反应一次二次设备工作状况的运行信息&#xff0c;如…

豪掷770亿!华为员工集体“分红大狂欢”:至少14万人受益

豪掷770亿&#xff01;华为员工集体“分红大狂欢”&#xff1a;至少14万人受益 近日&#xff0c;华为宣布了其2023年度分红计划&#xff0c;总金额高达770.85亿元&#xff0c;预计至少将惠及14万员工。这一消息引发了广泛关注和热议&#xff0c;成为业界的一大亮点。作为中国领…

如何构建一个高效的微服务治理闭环管理体系

随着企业业务的快速发展和数字化转型的推进&#xff0c;微服务架构因其高度的灵活性、可扩展性和可维护性而逐渐成为主流。然而&#xff0c;微服务架构的复杂性也带来了诸多治理挑战。为了有效应对这些挑战&#xff0c;构建一个微服务治理闭环至关重要。 1、微服务治理概述 微…

vue的8大生命周期

第072个 查看专栏目录: VUE ------ element UI 专栏目标 在vue和element UI联合技术栈的操控下&#xff0c;本专栏提供行之有效的源代码示例和信息点介绍&#xff0c;做到灵活运用。 提供vue2的一些基本操作&#xff1a;安装、引用&#xff0c;模板使用&#xff0c;computed&a…

L3HCTF 2024

Check in 输入一个1就获得flag

幻兽帕鲁服务器搭建最简单新手教程,10秒钟自动部署,一键开服(腾讯云)

以下教程是基于腾讯云轻量应用服务器搭建的&#xff0c;非常简单&#xff0c;无论搭建幻兽帕鲁还是其他的游戏或者应用&#xff0c;都能以非常快的速度部署好。而且稳定流畅&#xff0c;功能丰富。 下面就来一起看看如何搭建吧。 幻兽帕鲁腾讯云服务器购买与一键部署教程&…

【Git版本控制 03】远程操作

目录 一、克隆远程仓库 二、推送远程仓库 三、拉取远程仓库 四、忽略特殊文件 五、命令配置别名 一、克隆远程仓库 Git是分布式版本控制系统&#xff0c;同⼀个Git仓库&#xff0c;可以分布到不同的机器上。怎么分布呢&#xff1f; 找⼀台电脑充当服务器的⻆⾊&#xff…

Java ieda 抽风报错导致无法正常启动项目

Java ieda 抽风报错导致无法正常启动项目 问题描述&#xff1a;新建模块运行时出现下面报错&#xff0c;不能正常启动程序。 Error:Module 你的项目名 production: java.lang.ClassCastException: class org.jetbrains.jps.builders.java.dependencyView.TypeRepr$PrimitiveT…

031-安全开发-JS应用WebPack打包器第三方库JQuery安装使用安全检测

031-安全开发-JS应用&WebPack打包器&第三方库JQuery&安装使用&安全检测 #知识点&#xff1a; 1、三方库-JQuery-使用&安全 2、打包器-WebPack-使用&安全 演示案例&#xff1a; ➢打包器-WebPack-使用&安全 ➢第三方库-JQuery-使用&安全 #为什么…

神经网络基本原理

神经网络是一门重要的机器学习技术。它是目前最为火热的研究方向–深度学习的基础。 神经网络是一种模拟人脑的神经网络以期能够实现类人工智能的机器学习技术。人脑中的神经网络是一个非常复杂的组织。成人的大脑中估计有1000亿个神经元之多。 1 介绍 下面是一个包含三个层…

大华智慧园区综合管理平台/emap/devicePoint RCE漏洞

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

解决Windows程序与Mysql连接报错 [WinError 10048] 通常每个套接字地址(协议/网络地址/端口)只允许使用一次

问题解析 这是因为mysql与程序之间已经耗尽了动态范围内的端口&#xff0c;链接的开关过于频繁 解决方法 打开注册表编辑器&#xff0c;进入目录计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters点击顶部菜单编辑->新建&#xff0c;或是右…

用于电机控制应用的动态制动电阻器了解下

大型直流和交流电机驱动器通常提供用于安装制动电阻器的端子。这些电阻器是什么&#xff0c;它们如何减慢机器的速度&#xff1f;必须考虑哪些危险和注意事项&#xff1f; 机械能 任何运动中的机器都具有动能。这种能量是一些储存的势能被“倾倒”到电机或执行器中的结果&…

在线音乐服务器测试报告

一、项目背景 在线音乐服务器采用前后端分离的方法来实现&#xff0c;同时使用了数据库来存储相关的数据&#xff0c;同时将其部署到云服务器上。前端主要有个页面构成&#xff1a;登录页、音乐列表页、收藏音乐页等&#xff0c;以上模拟实现了最简单的在线音乐服务器。其结合后…

13. UE5 RPG限制Attribute的值的范围以及生成结构体

前面几章&#xff0c;我们实现了通过GameplayEffect对Attribute值的修改&#xff0c;比如血量和蓝量&#xff0c;我们都是有一个最大血量和最大蓝量去限制它的最大值&#xff0c;而且血量和蓝量最小值不会小于零。之前我们是没有实现相关限制的&#xff0c;接下来&#xff0c;我…

【排序】希尔排序

算法图解 算法基本步骤 首先&#xff0c;希尔排序是基于插入排序的一个时间复杂度为O(N*logN)的一个很牛的排序。 大家应该能注意到&#xff0c;图解中每一趟排序的时候有的数背景颜色是一样的&#xff0c;像这样背景颜色相同的数为一组&#xff0c;我们一共可以分gap组。 那…

代码献瑞,算力有礼!低代码开发工具PaddleX特色产线新春福利来啦

回望2023年&#xff0c;飞桨在开发套件能力基础上&#xff0c;充分结合大模型能力&#xff0c;正式在飞桨星河社区上线发布了低代码开发工具PaddleX&#xff0c;实现AI应用开发效果和效率的大幅提升。产品通过提供图形界面开发模式&#xff0c;将复杂的编程任务简化为简单易用的…