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

news2024/9/23 13:22:39

在这里插入图片描述

系列文章目录

能看懂文字就能明白系列
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://www.coloradmin.cn/o/1440579.html

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

相关文章

Mongodb启动为Windows服务开机自启动

注意&#xff1a;mongodb的安装目录不应有中文&#xff0c;如果有&#xff0c;服务启动的路径会出现乱码&#xff0c;导致找不到对应的文件 1.安装好mongoDB 2.创建data目录&#xff0c;并在其中创建db目录和log目录 3.在log目录中创建mongodb.log文件 4.打开cmd&#xff08;用…

【网络攻防实验】【北京航空航天大学】【实验一、入侵检测系统(Intrusion Detection System, IDS)实验】

实验一、入侵检测系统实验 1、 虚拟机准备 本次实验使用1台 Kali Linux 虚拟机和1台 Windows XP 虚拟机,虚拟化平台选择 Oracle VM VirtualBox,如下图所示。 2、 Snort环境搭建 实验前,先确保Kali Linux虚拟机能够访问外网,将网络模式设置为“网络地址转换”: 2.1 安装…

计算两个数相除后的余数返回值为浮点型math.fmod(x, y)

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 计算两个数相除后的余数 返回值为浮点型 math.fmod(x, y) [太阳]选择题 请问以下代码执行math.fmod()后输出的结果是&#xff1f; import math print("【执行】math.fmod(10, 4)"…

redis特点

一、redis线程模型有哪些&#xff0c;单线程为什么快&#xff1f; 1、IO模型维度的特征 IO模型使用了多路复用器&#xff0c;在linux系统中使用的是EPOLL 类似netty的BOSS,WORKER使用一个EventLoopGroup(threads1) 单线程的Reactor模型&#xff0c;每次循环取socket中的命令…

【数据结构】一篇文章带你学会八大排序

一、排序的概念1. 排序的使用&#xff1a;2. 稳定性&#xff1a;3. 内部排序&#xff1a;4. 外部排序︰5. 排序的用途&#xff1a; 二、排序的原理及实现1. 插入排序1.1 直接插入排序1.1.1 直接插入排序在现实中的应用1.1.2 直接插入排序的思想及个人理解1.1.3 直接插入排序的排…

嵌入式系统中的故障容错和恢复机制有哪些常用的方法和技术?

嵌入式系统是一种在特定应用领域内运行的计算机系统&#xff0c;其对系统可靠性和稳定性有着较高的要求。在嵌入式系统中&#xff0c;故障容错和恢复机制是至关重要的&#xff0c;因为它们能够确保系统在面临故障和异常情况时能够继续正常工作或者快速恢复正常状态。本文将介绍…

MPLS VPN功能组件(4)

数据转发过程 VPN数据的转发 顶层公网标签 由LDP分配,指示LSR如何将标签报文从始发的源PE通过LSP标签交换到达目的PE 内层私网标签(VPN标签) 由MP-BGP分配,在将每一条客户路由变为VPNv4路由前缀时会自动为每一条VPNv4前缀关联一个标签 内层私网标签用于指示目的PE将该标签报…

“手把手教你玩转函数递归,建议收藏!“

目录 1. 什么是递归 2. 递归的限制条件 3. 递归的举例 4. 递归与迭代 正⽂开始 1. 递归是什么&#xff1f; 递归是学习C语⾔函数绕不开的⼀个话题&#xff0c;那什么是递归呢&#xff1f; 递归其实是⼀种解决问题的⽅法&#xff0c;在C语⾔中&#xff0c;递归就是函数⾃…

Pandas数据预处理之数据标准化-提升机器学习模型性能的关键步骤【第64篇—python:数据预处理】

文章目录 Pandas数据预处理之数据标准化&#xff1a;提升机器学习模型性能的关键步骤1. 数据标准化的重要性2. 使用Pandas进行数据标准化2.1 导入必要的库2.2 读取数据2.3 数据标准化 3. 代码解析4. 进一步优化4.1 最小-最大缩放4.2 自定义标准化方法 5. 处理缺失值和异常值5.1…

MCS-51系列单片机简介

MCS-51系列单片机简介 MCS-51系列单片机是因特尔(Intel)公司生产的一个系列单片机的名称。比如&#xff1a;8051/8751/8031、8052/8752/8032、80C51/87C51/80C31、80C52/87C52/80C32等&#xff0c;都属于这一系列的单片机。 MCS-51系列单片机从功能上&#xff0c;可分为51和52…

深度学习入门笔记(九)自编码器

自编码器是一个无监督的应用&#xff0c;它使用反向传播来更新参数&#xff0c;它最终的目标是让输出等于输入。数学上的表达为&#xff0c;f(x) x&#xff0c;f 为自编码器&#xff0c;x 为输入数据。 自编码器会先将输入数据压缩到一个较低维度的特征&#xff0c;然后利用这…

Java图形化界面编程—— LayoutManager布局管理器笔记

2.4 LayoutManager布局管理器 之前&#xff0c;我们介绍了Component中有一个方法 setBounds() 可以设置当前容器的位置和大小&#xff0c;但是我们需要明确一件事&#xff0c;如果我们手动的为组件设置位置和大小的话&#xff0c;就会造成程序的不通用性&#xff0c;例如&…

数字图像处理实验记录七(彩色图像处理实验)

一、基础知识 经过前面的实验可以得知&#xff0c;彩色图像中的RGB图像就是一个三维矩阵&#xff0c;有3个维度&#xff0c;它们分别存储着R元素&#xff0c;G元素&#xff0c;B元素的灰度信息&#xff0c;最后将它们合起来&#xff0c;便是彩色图像。 这一次实验涉及CMYK和HS…

Java 获取、创建 stream 流操作对象的几种方法

Java 获取、创建 stream 流操作对象的几种方法 package com.zhong.streamdemo.createstreamdemo;import java.util.*; import java.util.stream.Stream;/*** ClassName : CreateStream* Description : 创建 stream 操作对象* Author : zhx* Date: 2024-02-08 13:10*/ public c…

查看网络配置的ipconfig命令

ipconfig是调试计算机网络的常用命令&#xff0c;通常大家使用它显示计算机中网络适配器的IP地址、子网掩码及默认网关。其实这只是ipconfig的不带参数用法&#xff0c;而它的带参数用法&#xff0c;在网络中应用也是相当不错的。 1.语法 ipconfig [/all] [/renew[Adapter]] [/…

分布式springboot 3项目集成mybatis官方生成器开发记录

文章目录 说明实现思路实现步骤第一步&#xff1a;创建generator子模块第二步&#xff1a;引入相关maven插件和依赖第三步&#xff1a;编写生成器配置文件第四步&#xff1a;运行查看结果 说明 该文章为作者开发学习记录&#xff0c;方便以后复习和交流主要内容为&#xff1a;…

《游戏引擎架构》 -- 学习2

声明&#xff0c;定义&#xff0c;以及链接规范 翻译单元 声明与定义 链接规范 C/C 内存布局 可执行映像 程序堆栈 动态分配的堆 对象的内存布局 kilobyte 和 kibibyte 流水线缓存以及优化 未完待续。。。

AOP相关

AOP相关 什么是AOP&#xff1f; 常见的场景 记录操作日志 缓存处理 spring内置事务处理 AOP记录操作日志 定义切点表达式&#xff0c;确定要记录的方法 找到方法中有log注解的方法 获得方法 获得方法的参数 spring中的事务实现 spring中的事务分声明式事务和编程式事务…

[word] word表格表头怎么取消重复出现? #媒体#笔记#职场发展

word表格表头怎么取消重复出现&#xff1f; word表格表头怎么取消重复出现&#xff1f;在Word中的表格如果过长的话&#xff0c;会跨行显示在另一页&#xff0c;如果想要在其它页面上也显示表头&#xff0c;更直观的查看数据。难道要一个个复制表头吗&#xff1f;当然不是&…

使用GDI画图片生成合成图片并调用打印机进行图片打印

使用GDI画图片生成合成图片并调用打印机进行图片打印 新建窗体应用程序PrinterDemo&#xff0c;将默认的Form1重命名为FormPrinter&#xff0c;添加对 Newtonsoft.Json.dll用于读写Json字符串 zxing.dll&#xff0c;zxing.presentation.dll用于生成条形码&#xff0c;二维码…