JavaSE---String(含一些源码)

news2024/12/24 17:23:13

(一)字符串构造

我们如何创建一个String类型的对象?有三种:

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

注:String是引用类型,内部存的不是字符串本身,而是一个value[]和hash(value是一个字符数组)

每个对象都会在栈和堆内分配不同的空间

(二)字符串有关常用方法

1.String对象的比较

   我们字符串比较,如果直接用==比较,那么我们比较的时字符串的地址,所以如果我们想比较String里面的值,我们应该要用equals这个方法

这里具体内存分配是什么样为什么不相等,一会我们在字符串常量池中讲

boolean equals(Object anObject)  

这个方法按照字典序进行比较

字典序:字符大小顺序        我们都知道这个equals是父类Object中的方法,我们String类重写了在这个方法,我们看一下他的原代码

我们发现,这里传来一个Object类型的对象,然后我们这个对象先判断地址是否相等,如果相等那就说明指向同一个对象,我们可以直接返回true,然后我们看下面的。检测anObject是否为String类型的对象,如果是的话就继续比较,否则因为是&&就会直接返回false

接下来,我们看下面这两个,coder是匹配hashcode值的,另一个默认为true,所以我们可以理解,这个就是来判断hashcode值是否相等的,如果相等那么我们就继续,不相等就返回false

然后最后一步,我们点进去看一下

我们就从第一个字符到最后一个字符,一个个比较,如果都相等才返回true,否则返回false;

  其实还有很多比较相等的方法,我们就不详细说了,我们一般用到的也就是重写的这个equals方法了

那么我们上面说完了字符串如何比较相等,那我们下面来讲如何比较字符串大小

这里我们使用的是

int compareTo(String s)这个方法 也是按照字典序进行比较

我们来看一下原码,然后来总结一下

那我们看这个源码,我们就知道是从哪里比较的字符串,所以我们直接点到这几个compareTo方法中,我发现差不多都长这个样子

  那好,我们就根据这个来总结一下  :首先他会计算我们两个字符串的长度并把他们变成字符数组,然后用最短的长度进入for循环,我们一旦发现有字符不相等了,就会返回他们的差值,如果一直相等就会返回他们的长度差值

public static void main(String[] args) {
    String s1 = new String("abc");
    String s2 = new String("ac");
    String s3 = new String("abc");
    String s4 = new String("abcdef");
    System.out.println(s1.compareTo(s2));   // 不同输出字符差值-1
    System.out.println(s1.compareTo(s3));   // 相同输出 0
    System.out.println(s1.compareTo(s4));   // 前k个字符完全相同,输出长度差值 -3
}

那这里我们还有一个忽略大小写比较的方法,他给封装了一下

老样子我们再点进去看看

我发现,他就是把他都转成大写然后进行了比较,其实本质上没什么太大区别

2.字符串查找

   我们这里就简单用个表格汇总下字符串查找的方法,因为实在是太多了,如果一个个看源码要好久,而且他们的原码也没有差别很大

3.字符串转化

1) 数值和字符串转化

  我们可以把数组转为字符串,把数字转为字符串以及对象(这个对象要重写toString方法因为我们会调用他重写的toString方法)

2)大小写转换

public static void main(String[] args) {    String s1 = "hello";    String s2 = "HELLO";    // 小写转大写    System.out.println(s1.toUpperCase());    // 大写转小写    System.out.println(s2.toLowerCase()); }

3)字符串转数组

使用toCharArray()

public static void main(String[] args) {   
 String s = "hello";    // 字符串转数组    
char[] ch = s.toCharArray();    
for (int i = 0; i < ch.length; i++) {        
System.out.print(ch[i]);   
}    
System.out.println();    // 数组转字符串    
String s2 = new String(ch);    System.out.println(s2); 
}

我们都知道value是一个字符串数组,那么我们字符串转数组就很简单了

4.字符串替换

使用一个指定新的字符串替换掉已有字符串数据

5.字符串拆分

我们可以使用这两个方法

  第一个就是按照特定的字符串进行拆分,然后返回,第二个就是按照特定字符串拆成多少组,如果拆够了就不拆了

注:这里有一些特殊字符作为分隔符是可能无法正确拆分的,所以我们需要加上转义

就比如我们拆分ip地址

就需要写成这样

那我们来总结下注意事项:

1. 字符"|","*","+"都得加上转义字符,前面加上 "\\" .

2. 而如果是 "\" ,那么就得写成 "\\\\" .

3. 如果一个字符串中有多个分隔符,可以用"|"作为连字符.

6.字符串截取

使用substring方法,可以指定范围

我们来继续看源码,这个check...是用来检查我们传入范围对不对的,我们不用管,然后我们直接进入newString方法

   我们发现这个新new出来的字符串是左闭右开的

那这里还有个很重要的事,我们上面的方法,都不是基于原字符串进行修改的,都是通过新new出来一个String对象,然后修改引用实现的,因为我们的String是不可变的(为什么我们会在下文讲到)

7.字符串的不可变性

  String是一种不可变对象,字符串中的内容不可改变,字符串不可被修改,这也就是为什么我们内部方法也都是创建新对象并且修改引用。那接下来我们看看是为什么?

因为:

String类在设计时就说了,是不可以改变的

图中我们发现都是被final修饰的,即String即不可以被继承,value也被修饰被final修饰,表明value自身的值不能改变,即不能引用其它字符数组,但是其引用空间中 的内容可以修改。

网上有很多人说:String不可变是因为内部保存字符的数组被final修饰了,因此不可以改变(实际上并不是这样的,因为源码中没说)

  我发现,这些final并不能本质上让String不可修改,所以我觉得有一些别的原因,我就去网上找了一些

在许多编程语言中,如Java、Python、C#等, string 类型被设计为不可修改,主要有以下几个原因:
 
内存管理与效率
 
- 字符串常量池:在Java等语言中,不可变的字符串可以方便地实现字符串常量池。相同内容的字符串字面量在内存中只有一份,多个引用可以指向同一个字符串对象,节省了大量的内存空间,提高了内存使用效率和程序性能。
- 避免频繁复制:当字符串作为参数传递或赋值给其他变量时,如果字符串是可变的,可能会导致在传递和赋值过程中频繁地复制整个字符串内容,而不可变字符串只需要传递引用,减少了不必要的内存复制操作,提高了程序的运行效率。
 
线程安全
 
- 不可变对象天生线程安全:在多线程环境下,多个线程可以同时访问不可变的字符串对象而无需担心数据被修改,从而避免了因并发修改导致的数据不一致和同步问题,大大降低了多线程编程的复杂性和风险,提高了程序的并发性能和稳定性。
 
缓存与哈希码
 
- 缓存哈希码:由于字符串不可变,其哈希码在对象创建时就可以计算并缓存起来,每次需要获取哈希码时直接返回缓存的值,提高了获取哈希码的效率,这对于在数据结构中使用字符串作为键(如哈希表)时非常重要,可以快速地进行查找和比较操作。
- 作为键的可靠性:不可变的字符串作为键在哈希表等数据结构中使用时,保证了键的唯一性和稳定性,不会因为键的内容被修改而导致在哈希表中找不到对应的键值对或出现错误的查找结果,确保了数据结构的正确性和一致性。
 
安全与不可篡改
 
- 防止意外修改:不可变的字符串可以防止在程序的其他部分意外地修改字符串内容,从而避免了一些潜在的错误和安全漏洞,使得程序的行为更加可预测和稳定,尤其是在处理一些敏感信息或重要数据时,如密码、配置文件中的关键参数等,不可变字符串可以提供更好的安全性和可靠性。

那这些都仅供参考,但是我们可以指定String设计成不可变的,有很多原因并不是因为String类本身也不是因为内部value被final修饰不可修改

8.字符串修改

那我们上面说String类型不可修改,最好是创建新对象,然后改变引用,那这个的效率是不高的,所以我们可以借助StringBuilder和StringBuffer

(三)StringBuilder和StringBuffer

由于String的不可更改特性,为了方便字符串的修改,Java中又提供StringBuilder和StringBuffer类。这两个类大 部分功能是相同的

还有些方法与String类型是一样的,就不多介绍了

我们这里来讲一下String,StringBuilder和StringBuffer三者的区别

1.String的内容不可修改,StringBuilder和StringBuffer的内容是可以修改的

2.StringBuilder线程不安全,StringBuffer是线程安全的,而String因为不可以修改,也是线程安全的

(四)字符串常量池

首先我们来看一个代码

那为什么会是这个结果?

在Java程序中,我们有道常量经常频繁使用,所以为了让程序运行更快,更节省内存,Java就给我们8种基本数据类型和String类都提供了常量池

其实还有很多池:内存池,线程池,数据库连接池等等。  目的都是为了一定程度上提升效率

1.字符串常量池(StringTable)

字符串常量池实际上就是一个固定大小的HashTable(一种高效查找的数据结构)

2.再谈String对象创建

   我们上面只是简单的画了个内存中的图,并没有涉及到字符串常量池,那这一次我们把字符串常量池加上,来看看字符串在内存中,是怎样分布的

先看这个,我们字符串常量直接赋值的,都会存放到常量中,首先我们会先判断字符串常量池中有没有,如果没有就会放到字符串常量池中,然后在指向引用,如果有了,就直接指向引用

然后有这样一段代码,我们会先去常量池中找有没有这个字符串,如果没有我们就在线程池中创建一个这样的字符串,然后在堆上申请一块内存,指向这个字符串,但是本身他并没有入池,只是在这个池中放了一个这样的字符串。如果有,那就在堆上申请一块内存,直接指向这个字符串,

结论:new出来的对象都是唯一的,但是我们可以使用intern方法,让字符串对象入池

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

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

相关文章

0.96寸OLED显示屏详解

我们之前讲了 LCD1602&#xff0c;今天我们将它的进阶模块——OLED。它接线更少&#xff0c;性能更强&#xff0c;也能显示中文和图像了。 大家在学习单片机的时候是否会遇到调试的问题呢&#xff1f;例如 “这串代码我到底运行成功了没有” &#xff0c;我相信很多刚开始学习…

用un-app写的动漫风格的登录界面

动漫风格的的登录、注册界面模板&#xff0c;使用uni-app编写&#xff0c;直接复制粘贴即可。 废话不多说&#xff0c;代码如下&#xff1a; login.vue文件 <template><view class"content"><view class"tab-box"><text class"c…

Pytorch | 从零构建ParNet/Non-Deep Networks对CIFAR10进行分类

Pytorch | 从零构建ParNet/Non-Deep Networks对CIFAR10进行分类 CIFAR10数据集ParNet架构特点优势应用 ParNet结构代码详解结构代码代码详解SSEParNetBlock 类DownsamplingBlock 类FusionBlock 类ParNet 类 训练过程和测试结果代码汇总parnet.pytrain.pytest.py 前面文章我们构…

【服务器】linux服务器管理员查看用户使用内存情况

【服务器】linux服务器管理员查看用户使用硬盘内存情况 1、查看所有硬盘内存使用情况 df -h2、查看硬盘挂载目录下所有用户内存使用情况 du -sh /public/*3、查看某个用户所有文件夹占用硬盘内存情况 du -sh /public/zhangsan/*

[搜广推]王树森推荐系统——其他召回通道

地理位置召回 GeoHash召回 想法&#xff1a;用户可能对附近发生的事感兴趣 方法&#xff1a;对经纬度的编码&#xff0c;地图上一个长方形区域 索引&#xff1a;GeoHash -> 优质笔记列表(按时间倒排) 这条召回通道没有个性化 同城召回 想法&#xff1a;用户可能对同…

重温设计模式--外观模式

文章目录 外观模式&#xff08;Facade Pattern&#xff09;概述定义 外观模式UML图作用 外观模式的结构C 代码示例1C代码示例2总结 外观模式&#xff08;Facade Pattern&#xff09;概述 定义 外观模式是一种结构型设计模式&#xff0c;它为子系统中的一组接口提供了一个统一…

OpenCV学习——图像融合

import cv2 as cv import cv2 as cvbg cv.imread("test_images/background.jpg", cv.IMREAD_COLOR) fg cv.imread("test_images/forground.png", cv.IMREAD_COLOR)# 打印图片尺寸 print(bg.shape) print(fg.shape)resize_size (1200, 800)bg cv.resize…

ECharts热力图-笛卡尔坐标系上的热力图,附视频讲解与代码下载

引言&#xff1a; 热力图&#xff08;Heatmap&#xff09;是一种数据可视化技术&#xff0c;它通过颜色的深浅变化来表示数据在不同区域的分布密集程度。在二维平面上&#xff0c;热力图将数据值映射为颜色&#xff0c;通常颜色越深表示数据值越大&#xff0c;颜色越浅表示数…

进程间关系与守护进程

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 进程间关系与守护进程 收录于专栏[Linux学习] 本专栏旨在分享学习Linux的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 1. 进程组 什…

LightGBM分类算法在医疗数据挖掘中的深度探索与应用创新(上)

一、引言 1.1 医疗数据挖掘的重要性与挑战 在当今数字化医疗时代,医疗数据呈爆炸式增长,这些数据蕴含着丰富的信息,对医疗决策具有极为重要的意义。通过对医疗数据的深入挖掘,可以发现潜在的疾病模式、治疗效果关联以及患者的健康风险因素,从而为精准医疗、个性化治疗方…

【文档搜索引擎】缓冲区优化和索引模块小结

开机之后&#xff0c;首次制作索引会非常慢&#xff0c;但后面就会快了 重启机器&#xff0c;第一次制作又会非常慢 这是为什么呢&#xff1f; 在 parserContent 里面&#xff0c;我们进行了一个读文件的操作 计算机读取文件&#xff0c;是一个开销比较大的操作&#xff0c; …

html+css网页设计 旅游 移动端 雪花旅行社4个页面

htmlcss网页设计 旅游 移动端 雪花旅行社4个页面 网页作品代码简单&#xff0c;可使用任意HTML辑软件&#xff08;如&#xff1a;Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作&#xff09;。 获取源码 …

3 JDK 常见的包和BIO,NIO,AIO

JDK常见的包 java.lang:系统基础类 java.io:文件操作相关类&#xff0c;比如文件操作 java.nio:为了完善io包中的功能&#xff0c;提高io性能而写的一个新包 java.net:网络相关的包 java.util:java辅助类&#xff0c;特别是集合类 java.sql:数据库操作类 IO流 按照流的流向分…

从零创建一个 Django 项目

1. 准备环境 在开始之前&#xff0c;确保你的开发环境满足以下要求&#xff1a; 安装了 Python (推荐 3.8 或更高版本)。安装 pip 包管理工具。如果要使用 MySQL 或 PostgreSQL&#xff0c;确保对应的数据库已安装。 创建虚拟环境 在项目目录中创建并激活虚拟环境&#xff…

ubuntu20.04安装imwheel实现鼠标滚轮调速

ubuntu20.04安装imwheel实现鼠标滚轮调速 Ubuntu 系统自带的设置中仅具备调节鼠标速度的功能&#xff0c;而无调节鼠标滚轮速度的功能。其默认的鼠标滚轮速度较为缓慢&#xff0c;在查看文档时影响尚可接受&#xff0c;但在快速浏览网页时&#xff0c;滚轮速度过慢会给用户带来…

GitLab的安装与卸载

目录 GitLab安装 GitLab使用 使用前可选操作 修改web端口 修改Prometheus端口 使用方法 GitLab的卸载 环境说明 系统版本 CentOS 7.2 x86_64 软件版本 gitlab-ce-10.8.4 GitLab安装 Gitlab的rpm包集成了它需要的软件&#xff0c;简化了安装步骤&#xff0c;所以直接…

简单工厂模式和策略模式的异同

文章目录 简单工厂模式和策略模式的异同相同点&#xff1a;不同点&#xff1a;目的&#xff1a;结构&#xff1a; C 代码示例简单工厂模式示例&#xff08;以创建图形对象为例&#xff09;策略模式示例&#xff08;以计算价格折扣策略为例&#xff09;UML区别 简单工厂模式和策…

脑肿瘤检测数据集,对9900张原始图片进行YOLO,COCO,VOC格式的标注

脑肿瘤检测数据集&#xff0c;对9900张原始图片进行YOLO&#xff0c;COCO&#xff0c;VOC格式的标注 数据集分割 训练组 70&#xff05; 6930图片 有效集 20&#xff05; 1980图片 测试集 10&#xff05; 990图片 预处理 静态裁剪&#xff1a; 24-82&…

YOLOv8 | 训练自定义数据集

目录 1 处理数据集1.1 数据集格式介绍1.2 划分数据集1.3 在 YOLOv8 中配置数据集 2 训练 YOLOv8 模型2.1 模型训练代码2.2 开启 TensorBoard 若尚未部署 YOLOv8&#xff0c;则可参考这篇博客&#xff1a; YOLOv8 | Windows 系统下从零开始搭建 YOLOv8 项目环境 1 处理…

Java设计模式 —— 【结构型模式】外观模式详解

文章目录 概述结构案例实现优缺点 概述 外观模式又名门面模式&#xff0c;是一种通过为多个复杂的子系统提供一个一致的接口&#xff0c;而使这些子系统更加容易被访问的模式。该模式对外有一个统一接口&#xff0c;外部应用程序不用关心内部子系统的具体的细节&#xff0c;这…