String类型
String类
在Java中,String 类是一个非常核心且常用的类,它用于表示文本值,即字符序列或者说字符串。
1.1 类的声明
public final class Stringimplements java.io.Serializable, Comparable<String>, CharSequence
解释:
-
final:
String类前面的final关键字表明这个类不能被继承。这意味着任何试图扩展String类的行为都是非法的。这主要是因为字符串在 Java 中是不可变的(immutable),如果允许继承,则子类可能会破坏这种不变性。 -
Serializable:
String类实现了Serializable接口,这表示String对象可以被序列化。序列化是指将对象的状态保存到一个字节流中,以便可以在网络上传输或者以后使用(例如存储到磁盘上)。任何实现了Serializable接口的对象都可以被 Java 的内置序列化机制处理。 -
Comparable:
String类实现了Comparable接口,这意味着String对象可以相互比较它们的大小。具体来说,可以通过compareTo()方法来比较两个字符串的字典顺序(即按照字母表顺序),从而确定它们之间的关系(相等、小于或大于)。 -
CharSequence:
String类也实现了CharSequence接口,这是一个定义了字符序列的基本操作的接口。CharSequence接口中定义的方法包括获取某个位置的字符、获取序列长度等基本功能。String类自然地支持这些方法,因为字符串本身就是一种字符序列。
1.2 内部属性
- 在 JDK 8 中,
String类内部使用char数组来存储字符串数据。 - 从 JDK 9 开始,
String类内部使用byte数组来存储数据,并引入coder字段来指示编码方式。
// JDK 8 及以前
private final char value[];// JDK 9 及以后
private final byte value[];
private final int coder; // 编码信息
1.3 String实例化的两种方式
第1种方式:String s1 = "hello";
第2种方式:String s2 = new String("hello");
第二种方式: 被IntrinsicCandidate 注解标注了。 这个注解是Java16引入的。
@IntrinsicCandidatepublic String(String original) {this.value = original.value;this.coder = original.coder;this.hash = original.hash;this.hashIsZero = original.hashIsZero;}
String s2 = new String("hello");
底层会有两个对象,一个是"hello"在字符串常量池中。一个是在堆内存中。浪费内存。
1.5 字符串的拼接
当在Java中使用+运算符连接字符串,尤其是在有变量参与的情况下,Java会在后台创建一个StringBuilder对象来进行字符串的拼接,并在最后通过调用toString()方法将StringBuilder转换为String对象。这样做可以提高字符串拼接的效率。
一::字符串常量池的特性
字符串常量池用于存放字符串常量,这些常量在编译期就可以确定。它的主要目的是避免重复创建相同的字符串对象,以节省内存空间。
例如,当你直接定义String s = "abc"时,"abc" 这个字符串常量会被放入字符串常量池,如果后续又有一个String s2 = "abc",那么s2会直接指向常量池中已有的 "abc" 对象,而不会再创建一个新的对象。
二、s1 + s2的拼接过程
- 当执行
String s1 = "abc"和String s2 = "def"时,"abc" 和 "def" 这两个字符串常量被放入字符串常量池,s1和s2分别指向常量池中的这两个对象。 - 对于
s3 = s1 + s2,由于涉及到对字符串变量的操作,Java 会在后台创建一个StringBuilder对象来进行拼接。它会先将s1指向的 "abc" 添加到StringBuilder中,然后再将s2指向的 "def" 添加进去。 - 最后,通过调用
StringBuilder的toString()方法创建一个新的String对象,这个新对象并不是在字符串常量池中创建的,而是在堆内存中。
三. intern() 方法:
如果将 s3 指向的字符串放入字符串常量池,可以显式地调用 intern() 方法:
String s3 = (s1 + s2).intern();
String m = "m";
String f = m + "e";
String str = f.intern(); // 将"me"放入字符串常量池中,并且将"me"对象的地址返回。
1.6 关于String类的构造方法
1.6.1 String(char[] value) String(char[] value, int index, int count)
若:有一个byte[]数组,可以将byte[]数组或者其中一部分转换成字符串,这是一个解码的过程。(采用的是平台默认的字符编码方式进行的解码。)
// 有一个char[]数组,可以将char[]数组转换成字符串
char[] chars = new char[]{'你','好','优','秀'};
// 转换成字符串
String s1 = new String(chars);
System.out.println(s1);
// 将char[]数组的一部分转换成字符串
String s2 = new String(chars, 0, 2);
System.out.println(s2);
1.6.2 编码与解码
使用指定字符集
// 将字符串转换成byte[]数组(这个过程是一个编码的过程)
byte[] bs = "你好".getBytes(StandardCharsets.UTF_8);
// 将以上的byte[]数组转换成字符串(这个过程是一个解码的过程)
//String s5 = new String(bs, "UTF-8");
String s5 = new String(bs, StandardCharsets.UTF_8);
System.out.println(s5);String s6 = new String( bs, Charset.defaultCharset() ); 在不知道字符编码方式的时候,可以
动态获取平台的编码方式。
(使用平台默认的字符集进行编码)
1.4 字符串常量的存储位置
> 字符串常量 都 存储 在字符串常量池(StringTable)中
> 字符串常量池不允许存放两个相同的字符串常量。
> 字符串常量池,在不同的jdk版本中,存放位置不同。
jdk8及之后:字符串常量池存放在堆空间。
Jdk8 之前 永久代
字符串常量池的工作原理可以总结如下:
- 编译阶段确定:在编译Java源代码时,所有的字符串字面量都会被确定下来。
- JVM启动时初始化:当JVM启动时,会初始化字符串常量池,将所有字符串字面量放入其中。
- 运行时直接使用:在程序运行时,如果需要使用某个字符串字面量,可以直接从字符串常量池中获取,而不需要每次都创建新的字符串对象。
- 提高效率:由于避免了重复创建相同的字符串对象,字符串常量池可以节省内存空间并提高程序的执行效率。
- 缓存技术:字符串常量池本质上是一种缓存技术,它预先创建了字符串对象,以便在需要时快速访问。
/*** 在java程序当中,凡是带有双引号的字符串,在编译阶段就已经完全确定了:这些字符串字面量将来会放在字符串常量池中。* 在JVM启动的时候,会进行一系列的初始化,其中就包括字符串常量池的初始化,在初始化字符串常量池的时候,会将所有的* 字符串字面量全部提前创建好,放到字符串常量池中。在执行java程序的过程中,如果需要这个字符串字面量对象,直接从* 字符串常量池中获取。提高执行效率。** Java8之后:字符串常量池在堆内存当中。** 字符串常量池是一种缓存技术。提前创建好对象放进去,用的时候直接拿。(字符串字面量在JVM启动的时候就会创建好。)*/
1.7 String 类常用方法
length
equals 与 equalsIgnoreCase
String s3 = "Java";String s4 = "java";System.out.println(s3.equals(s4)); // falseSystem.out.println(s3.equalsIgnoreCase(s4)); // true
startswith 与 endswith
@Testpublic void testStartsWithAndEndsWith() {System.out.println("http://www.baidu.com".startsWith("http://")); // trueSystem.out.println("http://www.baidu.com".endsWith(".com")); // trueSystem.out.println("http://www.baidu.com".startsWith("https://")); //falseSystem.out.println("http://www.baidu.com".endsWith(".cn")); // false}
`regionMatches` 是 Java 中 `String` 类的一个方法,它用于比较两个字符串在指定区域内的子串是否相等。这个方法有两个重载版本:
1. `public boolean regionMatches(int toffset, String other, int ooffset, int len)`
这个版本的 `regionMatches` 方法会区分大小写。参数解释如下:
- `toffset`:当前字符串中开始比较的位置。
- `other`:另一个要进行比较的字符串。
- `ooffset`:`other` 字符串中开始比较的位置。
- `len`:要比较的字符数。
2.
`public boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len)`
这个版本允许你指定是否忽略大小写来进行比较。额外的参数是:
- `ignoreCase`:如果为 `true`,则比较时忽略大小写;如果为 `false`,则区分大小写。
当你调用 `regionMatches` 时,它会返回一个布尔值,表示两个指定区域的子串是否相等。例如,如果你想要比较 `"HelloWorld"` 从索引 0 开始的 5 个字符与 `"helloJava"` 从索引 0 开始的 5 个字符,并且不区分大小写,你可以这样写代码:
```java
String s1 = "HelloWorld";
String s2 = "helloJava";
boolean result = s1.regionMatches(true, 0, s2, 0, 5);
// 结果应该是 true,因为 "Hello" 和 "hello" 在忽略大小写的情况下是相同的。
```
compareTo
用于按字典顺序比较两个字符串。这个方法是基于 Unicode 值来比较字符串中的字符的。
- 返回值:一个整数,表示调用该方法的字符串(即当前字符串)与参数字符串之间的相对顺序。
- 如果返回值为负数,说明当前字符串在字典顺序上位于参数字符串之前。
- 如果返回值为正数,说明当前字符串在字典顺序上位于参数字符串之后。
- 如果返回值为 0,说明两个字符串相等。
@Testpublic void testCompareTo() {System.out.println("a".compareTo("b")); // -1System.out.println("a".compareTo("c")); // -2System.out.println("b".compareTo("a")); // 1System.out.println("a".compareTo("a")); // 0System.out.println("A".compareTo("a")); // -32System.out.println("A".compareToIgnoreCase("a")); // 0}
- 注意事项:
- `compareTo` 是区分大小写的,这意味着大写字母和小写字母会被视为不同的字符。
- 如果你需要进行忽略大小写的比较,可以使用 `compareToIgnoreCase` 方法。
contains
@Testpublic void testContains() {System.out.println("HelloWorld.java".contains(".java")); // trueSystem.out.println("HelloWorld.java".contains(".txt")); // false}
substring
// 截取子字符串
截取字符串中介于两个指定下标之间的字符
str.substring(beginIndex, endIndex)
注意:不包括endIndex
拼接字符串
concat 与 "+"
String s = "ab";
System.out.println(s + 1);
// concat方法
System.out.println(s.concat(String.valueOf(2)));
+ 运算符可以连接任意数量的字符串,
而 concat 方法只能连接两个字符串
使用 + 运算符时,非字符串类型的操作数会被自动转换为字符串;
而使用 concat 方法时,如果传入非字符串类型的参数,会抛出异常。
即:
- 不能连接
null,会抛出NullPointerException。 - 不能连接多个字符串,必须链式调用
String s1 = "test"; String s2 = null; String s3 = s1 + s2; System.out.println(s3); // "testnull"/*String s1 = "test"; String s2 = null; String s3 = s1.concat(s2); // 空指针异常*/
String.join() 方法(Java 8+)
String.join() 方法
用于连接多个字符串,并在每个字符串之间插入指定的分隔符。
有两个重载版本
String.join(CharSequence delimiter, CharSequence... elements)
这个方法接受两个参数:delimiter:这是一个CharSequence类型的参数,它表示用作分隔符的字符序列。这个分隔符会被插入到连接的字符串元素之间。
elements:这是一个变长参数,接受CharSequence类型的数组。这些是将要被连接的字符串元素。
String.join(CharSequence delimiter, Iterable<? extends CharSequence> elements)
这个方法接受两个参数:delimiter:与第一个版本相同,这是一个CharSequence类型的参数,表示分隔符。
elements:这是一个Iterable类型的参数,其元素必须是CharSequence的子类型。这个方法会遍历这个可迭代对象中的所有元素,并将它们连接起来。
eg:
// 创建一个集合对象List list = new ArrayList();list.add("abc");list.add("def");list.add("xyz");System.out.println(String.join("-", list)); abc-def-xyz
去除空格
trim()
trim() 方法是最常用的方法之一,它用于删除字符串两端的空白字符。这里的空白字符包括空格、制表符、换行符等
ASCII码的空白 , (无法去除全角空白)
strip()
从 Java 11 开始,引入了 strip() 方法,它与 trim() 功能相似,但 strip() 去除的是根据 Unicode 标准来标识的所有空格字符,而不仅仅局限于 ASCII 中的空格字符
stripLeading() 和 stripTrailing()
从 Java 11 引入的,分别用于只删除字符串开头或结尾的空白字符
非字符串 ->字符串
String.valueOf()
Object obj = 42;
String str = String.valueOf(obj); "42"
+ 号 拼接
String的正则表达式相关的方法:
①String replace(CharSequence target, CharSequence replacement);
将当前字符串中所有的target替换成replacement,返回一个新的字符串。
②String replaceAll(String regex, String replacement);
将当前字符串中所有符合正则表达式的regex替换成replacement。
public void testReplace(){// 这个也是替换所有,只不过没有使用正则表达式String str1 = "oraclejavac++mysqlphppythonjavamysql".replace("java", "golang");System.out.println(str1);// 替换所有数字,使用正则表达式String str2 = "a1b2c3d54e43f".replaceAll("\\d", "");System.out.println(str2);}
③String[] split(String regex);
将当前字符串以某个正则表达式表示的子字符串进行分割,返回一个字符串数组。
④boolean matches(String regex);
判断当前字符串是否符合正则表达式regex。
相关文章:
String类型
String类 在Java中,String 类是一个非常核心且常用的类,它用于表示文本值,即字符序列或者说字符串。 1.1 类的声明 public final class Stringimplements java.io.Serializable, Comparable<String>, CharSequence 解释:…...
Ubuntu24.04安装和配置Redis7.4
Ubuntu24.04安装和配置Redis7.4 #切换到root用户 sudo su -#更新源 apt update apt upgrade#安装 lsb-release、curl 和 gpg ,以便能够添加 Redis 仓库 apt install lsb-release curl gpg#导入 Redis 的 GPG 密钥 curl -fsSL https://packages.redis.io/gpg | gpg …...
权限相关知识
1.Linux权限的概念 在说Linux权限的概念之前我来问大家一个问题,你们觉得什么是权限? 权限平时的体现呢,就比如不是校长的亲戚就不能逛办公室,没充会员的爱奇艺看不了VIP影视剧,没成会员的的蛋糕店拿不到会员价等等等…...
【时间之外】IT人求职和创业应知【37】-AIGC私有化
目录 新闻一:2024智媒体50人成都会议暨每经20周年财经媒体峰会召开 新闻二:全球机器学习技术大会在北京召开 新闻三:区块链技术在金融领域的应用取得新突破 不知不觉的坚持了1个月,按照心理学概念,还要坚持2个月&am…...
深入理解 source 和 sh、bash 的区别
1 引言 在日常使用 Linux 的过程中,脚本的执行是不可避免的需求之一,而 source、sh、bash 等命令则是执行脚本的常用方式。尽管这些命令都能运行脚本,但它们之间的执行方式和效果却有着显著的区别。这些区别可能会影响到脚本的环境变量、工作…...
k8clone二进制工具迁移k8s中的无状态应用
1 概述 k8clone是一个简便的Kubernetes元数据克隆工具,它可以将Kubernetes元数据(对象)保存为本地压缩包,在恢复时可将这些元数据恢复到目标集群中(已存在的资源不会被覆盖)。它不依赖远程存储,…...
VPI photonics的一些使用经验(测相位 快速搜索)持续更新
1.使用FuncSinEl模块的注意事项: 2.在VPI player(示波器)测电信号相位时候,可以使用正则表达式,快速搜索。 比如我要搜索以30开头的数据,输入: ^30 其他的正则表达式不适用,比如以…...
DBeaver 连接 OceanBase Oracle 租户
DBeaver 是一款通用的数据库工具软件,支持任何具有JDBC驱动程序的数据库。DBeaver 需要 Java 运行环境的支持。截稿时 DBeaver 24.0.0 版本默认提供的 OceanBase 驱动是连接 MySQL 的,想连接 Oracle 租户需要新建一个驱动器使用。 下载数据库驱动包 1、…...
QT_CONFIG宏使用
时常在Qt代码中看到QT_CONFIG宏,之前以为和#define、DEFINES 差不多,看了定义才发现不是那么回事,定义如下: 看注释就知道了QT_CONFIG宏,其实是:实现了一个在编译时期安全检查,检查指定的Qt特性…...
力扣(leetcode)题目总结——辅助栈篇
leetcode 经典题分类 链表数组字符串哈希表二分法双指针滑动窗口递归/回溯动态规划二叉树辅助栈 本系列专栏:点击进入 leetcode题目分类 关注走一波 前言:本系列文章初衷是为了按类别整理出力扣(leetcode)最经典题目,…...
如何处理 iOS 客户端内 Webview H5 中后台播放的音视频问题
目录 问题描述Page Visibility API 的应用什么是 Page Visibility API?使用 Page Visibility API 暂停音视频完整解决方案1. 监听媒体的播放和暂停事件2. 防止自动播放3. 结合 Intersection Observer 进行媒体控制4. 手动处理应用生命周期中的事件 问题描述 在 iOS…...
C++的一些模版
1、不限制次数的输入数据 vector<int> nums;int num;while (cin >> num) {nums.push_back(num);if (cin.get() \n) break;}2、取模模版 template<int kcz> struct ModInt { #define T (*this)int x;ModInt() : x(0) {}ModInt(int y) : x(y > 0 ? y : y…...
spring boot整合https协议
整体目录 1. 生成SSL证书 首先,使用keytool生成一个自签名证书。打开命令行工具并运行以下命令: keytool -genkeypair -alias myserver -keyalg RSA -keysize 2048 -keystore keystore.jks -validity 365 这将创建一个名为keystore.jks的文件…...
服务器开机即占用大量内存,解决
1.服务器开机两分钟不到,内存使用飙升 [rootlocalhost ~]# top #查看是否有了明显的内存占用程序 2.上述未果,查看是否有违规的开机自启项 [rootlocalhost ~]# chkconfig --list 3.上述无果,查看开启启动加载项内容 上网搜后ÿ…...
Keil uvision的edition
0 Preface/Foreword 0.1 参考网址 https://zhuanlan.zhihu.com/p/456069876 1 Keil版本介绍 版本介绍: Keil Lite(免费版):最多32KB代码,无法使用中间件Keil Essential(基础版):没…...
[每周一更]-(第123期):模拟面试|消息队列面试思路解析
文章目录 22|消息队列:消息队列可以用来解决什么问题?1. 你用过消息队列吗?主要用来解决什么问题?异步、削峰和解耦你能各举一个例子吗?2. 你用的是哪个消息队列?为什么使用它而不用别的消息队列?3. 为什么你一定要用消息队列?不用行不行?不用有什么缺点?4. 在对接多…...
游戏引擎学习第12天
视频参考:https://www.bilibili.com/video/BV1yom9YnEWY 这节没讲什么东西,主要是改了一下音频的代码 后面有介绍一些alloc 和malloc,VirtualAlloc 的东西 _alloca 函数(或 alloca)分配的是栈内存,它的特点是: 生命周…...
深入理解Flutter生命周期函数之StatefulWidget(一)
目录 前言 1.为什么需要生命周期函数 2.开发过程中常用的生命周期函数 1.initState() 2.didChangeDependencies() 3.build() 4.didUpdateWidget() 5.setState() 6.deactivate() 7.dispose() 3.Flutter生命周期总结 1.调用顺序 2.函数调用时机以及主要作用 4.生…...
413: Quick Sort
解法: #include <bits/stdc.h> using namespace std; const int N1e55; int a[N]; int n;int main(int argc, char** argv) {cin>>n;for (int i0;i<n;i) cin>>a[i];sort(a,an);for (int i0;i<n;i) cout<<a[i]<<" "…...
vue之axios根据某个接口创建实例,并设置headers和超时时间,捕捉异常
import axiosNew from axios;//给axios起个别名//创建常量实例 const instanceNew axiosNew.create({//axios中请求配置有baseURL选项,表示请求URL的公共部分,url baseUrl requestUrlbaseURL: baseURL,//设置超时时间为20秒timeout: 20000,headers: {…...
从羊肠小道到智能高速:HTTP1到HTTP3的演进之路
引言 计算机网络就像一张遍布全球的道路系统,服务器是一座座城市、村庄,客户端是穿梭其中的车辆,而HTTP协议,就是规范车辆通行、货物传递的交通规则。从HTTP1到HTTP3的演进,本质上就是这条“网络道路”的升级史——从泥…...
如何永久保存微信聊天记录:免费工具实现数据可视化与年度报告生成
如何永久保存微信聊天记录:免费工具实现数据可视化与年度报告生成 【免费下载链接】WeChatMsg 提取微信聊天记录,将其导出成HTML、Word、CSV文档永久保存,对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trendi…...
解决Android 12 NFC功能失效:PendingIntent.FLAG_MUTABLE的正确用法
Android 12 NFC开发实战:PendingIntent可变性标志的深度解析 在移动支付和门禁系统逐渐普及的今天,NFC技术已经成为现代智能手机不可或缺的功能之一。然而,随着Android系统的版本迭代,开发者们不得不面对各种兼容性挑战。特别是在…...
嵌入式开发代码版本比较工具与技巧
1. 嵌入式开发中的代码版本差异查看方法在嵌入式开发过程中,代码版本管理是每个工程师必须掌握的核心技能。随着项目迭代和功能更新,我们经常需要比较不同版本代码之间的差异,无论是为了代码审查、问题排查还是版本合并。作为一名嵌入式开发者…...
收藏!程序员转型AI大模型应用开发,必学四大核心技能(小白友好版)
当下AI大模型风口持续爆发,越来越多程序员想抓住机遇转型入局,但大多陷入“盲目跟风、无从下手、学了没用”的困境——其实,转型AI大模型应用开发无需急于求成,不用追求“面面俱到”,先吃透核心技能,搭建完…...
LFM2.5-1.2B-Thinking-GGUF部署教程:解决‘返回为空’问题的max_tokens调优策略
LFM2.5-1.2B-Thinking-GGUF部署教程:解决返回为空问题的max_tokens调优策略 1. 模型简介与部署准备 LFM2.5-1.2B-Thinking-GGUF是Liquid AI推出的轻量级文本生成模型,特别适合在资源有限的环境中快速部署使用。这个模型采用GGUF格式和llama.cpp运行时&…...
百川2-13B-4bits模型调优:OpenClaw任务响应速度提升50%的3个技巧
百川2-13B-4bits模型调优:OpenClaw任务响应速度提升50%的3个技巧 1. 问题背景与优化动机 去年冬天,当我第一次将百川2-13B-4bits模型接入OpenClaw时,发现一个奇怪现象:同样的自动化任务,在本地测试时响应飞快&#x…...
逆向实战:用Smali语法修改APK逻辑,实现一个简单的功能破解(附工具与源码)
逆向工程实战:用Smali语法解锁APK功能的全流程指南 在Android逆向工程领域,掌握Smali语法就像获得了一把打开APK内部逻辑的万能钥匙。不同于那些停留在理论层面的教程,本文将带你深入一个真实的逆向场景——如何通过修改Smali代码来解锁某个演…...
基于LangChain的RAG与Agent智能体开发 - 向量存储与向量检索,以及RAG增强检索实现
大家好,我是小锋老师,最近更新《2027版 基于LangChain的RAG与Agent智能体 开发视频教程》专辑,感谢大家支持。本课程主要介绍和讲解RAG,LangChain简介,接入通义千万大模型 ,Ollama简介以及安装和使…...
I2C协议详解:从基础原理到工程实践
1. I2C协议基础与核心设计思想I2C(Inter-Integrated Circuit)总线是Philips公司(现NXP)在1980年代开发的一种同步、半双工串行通信协议。作为嵌入式系统中最常用的总线之一,I2C以其简洁的两线制(SDA数据线S…...
