java的String类详解

目录

  • 不可变字符串
    • 字符串常量池
  • String类的继承关系
  • String类的底层实现
  • 创建String对象
  • 字符串拼接
    • 常见面试题
  • String的常用方法
    • 字符串是否相等
    • 获取子串
    • 返回字符串的长度
    • 字符串的比较
    • 返回给定值的索引
    • 转换大小写
    • 返回给定索引的字符
    • 字符串替换
    • 把字符串转换为字符数组
    • 去字符串空白
    • 字符串连接
    • 格式化字符串输出



String类表示字符串类型,String是java标准类库的预定义类,它是java的引用类型。 在java.lang包下,可以直接使用。
String类有final修饰,是最终类,不能被继承。



不可变字符串

String类是不可变类,这表明String对象包含的字符序列一旦创建就无法更改(没有setter方法)。不可变指的是对象不可变,但是String类型的引用变量可以指向不同的字符串对象

字符串常量池

一旦使用带双引号的字符串,就会在字符串常量池存储该字符串。这就相当于创建了一个字符串对象。比如:String s1 = “abc”,字符串"abc"就会被存储到字符串常量池中。
如果再次需要使用已经创建过的字符串,就直接让字符串的引用变量指向常量池中的字符串
比如:String s2 = “abc”; 因为前面已经在字符串常量池中创建了字符串"abc",所以系统会让s2直接指向该字符串,也就是s1和s2指向同一个字符串对象"abc"。

如果是用构造方法创建字符串对象,比如:String s3 = new String(“abc”); 此时会在堆内存新开辟一个空间存储这个String对象,对象内部的成员变量会记录常量池中"abc"字符串的地址。但是对象本身的地址是堆内存中新开辟的新地址

如果是通过构造器创建的String对象,想获取存储的字符串的常量池地址,可以使用intern实例方法:
public String intern(); 该方法可以获取字符串对象存储的字符序列的常量池地址。如果常量池没有改字符串对象存储的字符序列,就在常量池中创建该字符序列。

字符串常量池的位置在java7及其之后都是在堆内存中,java6及其以前字符串常量池在方法区



String类的继承关系

String类实现了三个接口:Serializable、Comparable、CharSequence接口



String类的底层实现

子以前String类的底层是char数组,每个字符占2个字节。
从java9开始,String、StringBuffer和StringBuilder都是采用byte[]数组再加一个byte类型的code实例变量(用于标识编码类型)实现。因此每个字符只占1个字节。



创建String对象

String类是唯一一个有单独创建方式的类,它可以直接用双引号括起来的字符串来创建对象实例。比如"abc",这就相当于创建了一个String类的对象。
除此之外,String类也可以像普通类一样,用构造器创建对象。

介绍几个常见的构造器:

  1. String():构造一个空字符串的String对象。
  2. String(String original):创建一个和参数的字符串值相同的副本。
  3. String(char[] value):通过复制字符数组里的字符序列,创建一个字符串。
  4. public String(char[] value, int offset, int count):通过复制字符数组里的子字符序列,创建一个新的字符串。
  5. public String(byte[] bytes): 通过平台默认字符集,将bytes数组的元素序列转换为字符串。
  6. String(byte[] bytes, int offset, int length): 通过平台默认字符集,将bytes数组的子元素序列转换为对应的字符串。


字符串拼接

java的"+"运算符还可以做字符串的拼接
比如:String s1 = “abc” + “edf”; 这样s1的值为"abcdef"。
再比如:String s2 = “007” + 123; 这样s2的值为007123。注意,如果其中一个操作数是字符串,另一个操作数是任何类型都会被转换为字符串类型,比如这里123是int类型,会转换为字符串类型"123",再做拼接。

常见面试题

String s1 = "abc";
String s2 = "a" + "b" + "c";
System.out.println(s1 == s2);	// 结果为trueString s3 = "bc";
String s4 = "a" + s3;
System.out.println(s1 == s4);  // 结果为false

这是因为java有常量优化机制:如果等号右边的表达式全是常量,那么编译阶段右边的结果就会被计算出来。如果右边的结果在左边变量数据类型的范围内,就直接为其赋值,否则赋值失败。
所以,s2的值在编译阶段就已经确定了,为"abc",第二行代码相当于String s2 = “abc”,所以s2会和s1一起指向字符串常量池中的"abc",所以结果为true。
注意:String s2 = “a” + “b” + “c”; 实际上是创建了1个字符串对象"abc",在编译阶段时,三个单独的字符串就已经被合并为"abc"了,只有"abc"会被存储到常量池中。

当右边表达式存在变量时,编译期间不会存在常量优化机制。
对于String s4 = “a” + s3; 因为s3是一个变量。所以连接等号右边需要利用StringBuilder类,之后再调用它的toString方法返回一个String对象,这个对象有单独的地址,所以结果不等于"abc"。



String的常用方法

字符串是否相等

1.public boolean equals(Object anObject); 将该字符串与指定对象比较,如果二者包含的字符序列相等,则返回true;否则返回
false。
String类重写了Object类的equals方法,只看两个String对象存储的字符系列的值是否相等。

推荐写法:String s1 = “hello”; “hello”.equals(s1);
不推荐写法:String s1 = “hello”; s1.equals(“hello”);
这是因为s1的值如果是null,会产生异常,用字符串字面量做主调,可以避免这种异常。

要避免用==运算符比较两个字符串对象是否相等,等号运算符只是比较2个字符串引用变量指向的地址,而不是比较字符序列的值

2.public boolean equalsIgnoreCase(String anotherString); 如果希望比较字符序列时不考虑大小写,就用这个方法。

获取子串

public String substring(int beginIndex); 获取从beginIndex位置开始到整个字符串结束的子字符串(包括beginIndex)。
public String substring(int beginIndex, int endIndex); 获取从beginIndex位置开始到endIndex位置的子字符串(包括beginIndex,不包括endIndex)。

返回字符串的长度

public int length(); 返回该字符串对象的字符序列长度,准确说是Unicode代码单元的长度。

字符串的比较

public int compareTo(String anotherString); 按字典顺序比较两个字符串,返回正值、零、负值。

返回给定值的索引

public int indexOf(int ch); 返回给定值在字符串中第一次出现的索引
public int indexOf(int ch, int fromIndex); 返回给定值在字符串中第一次出现的索引,但是搜索的位置从索引fromIndex(包含fromIndex)开始
public int indexOf(String str); 返回给定子串在字符串中第一次出现的索引
public int indexOf(String str, int fromIndex); 返回给定子串在字符串中第一次出现的索引,但是搜索的位置从索引fromIndex(包含fromIndex)开始

public int lastIndexOf(int ch); 返回给定值在字符串中最后一次出现的索引
public int lastIndexOf(int ch, int fromIndex); 返回给定值在字符串中最后一次出现的索引,但是搜索的位置从索引fromIndex开始,往左边搜索
public int lastIndexOf(String str); 返回给定子串在字符串中最后一次出现的索引
public int lastIndexOf(String str, int fromIndex); 返回给定子串在字符串中最后一次出现的索引,但是搜索的位置从索引fromIndex开始,往左边搜索

如果没找到指定值,这些方法都会返回-1

转换大小写

public String toUpperCase(); 生成一个新的字符串,新字符串把字符串的所有字母转换为大写格式
public String toUpperCase(); 生成一个新的字符串,新字符串把字符串的所有字母转换为小写格式

返回给定索引的字符

public char charAt(int index); 返回字符串里,参数指定索引对应的字符

字符串替换

replace(CharSequence target, CharSequence replacement); 将字符串中包含的target子串全部替换为replacement字符串,替换是从左往右依次替换。

把字符串转换为字符数组

public char[] toCharArray(); 把字符串转换为新生成的对应字符数组。

去字符串空白

public String trim(); 返回一个新的字符串,去掉原字符串开头和结尾的空白

字符串连接

public String concat(String str); 将指定字符串链接到字符串的结尾,并返回连接后的字符串

格式化字符串输出

public static String format(String format, Object… args); 使用指定的字符串和参数返回一个格式化后的新字符串。
它和C语言的printf是一样的用法。

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

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

相关文章

ant.design 组件库中的 Tree 组件实现可搜索的树: React+and+ts

ant.design 组件库中的 Tree 组件实现可搜索的树,在这里我会详细介绍每个方法,以及容易踩坑的点。 效果图: 首先是要导入的文件 // React 自带的属性 import React, { useMemo, useState } from react; // antd 组件库中的,输入…

如何使用 reqwest 包

GET 请求 向连接发起一个 GET 请求:https://hacker-news.firebaseio.com/v0/topstories.json,并解析返回的内容。 尝试发起请求 因为是 GET 请求,可以先在浏览器中进行查看,浏览器可以正常显示一个 id 列表,如下所示…

Anaconda安装

目录 1.Anaconda 安装前是否需要安装Python 2.Anaconda 都包含了什么 3.Anaconda官网下载地址

《Linux从练气到飞升》No.08 Linux的版本管理工具 git

🕺作者: 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux菜鸟刷题集 😘欢迎关注:👍点赞🙌收藏✍️留言 🏇码字不易,你的👍点赞🙌收藏❤️关注对我真的…

复现沙箱逃逸漏洞

什么是沙箱(sandbox) 在计算机安全性方面,沙箱(沙盒、sanbox)是分离运行程序的安全机制,提供一个隔离环境以运行程序。通常情况下,在沙箱环境下运行的程序访问计算机资源会受到限制或者禁止,资源包括内存、…

【大模型】大模型在软件特性设计中的应用

创建业务对象 1、已有的业务对象可以放入向量数据库 2、如果没有新的业务对象需要创建,直接跳过 3、新的业务对象由用户手动创建 提示词 假设你是一名 Java 软件技术专家,根据如下 yaml 格式生成对应的实体对象,其中 1、最顶层为对象名 2、…

Visual ChatGPT:Microsoft ChatGPT 和 VFM 相结合

推荐:使用 NSDT场景编辑器助你快速搭建可二次编辑的3D应用场景 什么是Visual ChatGPT? Visual ChatGPT 是一个包含 Visual Foundation 模型 (VFM) 的系统,可帮助 ChatGPT 更好地理解、生成和编辑视觉信息。VFM 能够指…

前端如何设置表格边框样式和单元格间距?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 实现思路⭐ 代码演示⭐ 注意事项⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅!这个专栏是为那些对Web开发感兴…

C++ 派生类成员的标识与访问——作用域分辨符

在派生类中,成员可以按访问属性分为以下四种: (1)不可访问成员。这是从基类私有成员继承下来的,派生类或是建立派生类对象的模块都无法访问到它们,如果从派生类继续派生新类,也是无法访问的。 &…

Python魔法解析:探索变量类型的丰富多彩世界!

在Python这个魔法般的编程语言中,变量是连接你与计算机世界的神奇桥梁。然而,这些变量并不是单一的,它们有着丰富多彩的类型。无论你是刚刚踏入编程的大门,还是想要深入了解Python的高级特性,本篇博客将带你探索变量的…

Next.js使用装饰器decorator 解决[作为表达式调用时,无法解析类修饰器的签名。]

Next.js 会自动检测 jsconfig.json 或 tsconfig.json 中的experimentalDecorators。 tsconfig.json {"compilerOptions": {//..."experimentalDecorators": true} }然后重启服务 否则装饰器无法识别 不声明的话vscode 执行 ts检测 也会报错作为表达式调用…

pycharm打开terminal报错

Pycharm打开终端报错如何解决?估计是终端启动conda不顺利,需要重新设置路径。参考以下文章的做法即可。 Windows下Pycharm中Terminal无法进入conda环境和Python Console 不能使用 给pycharm中Terminal 添加新的shell,才可以使用conda环境 W…

黑马大数据学习笔记4-Hive部署和基本操作

目录 思考规划安装MySQL数据库修改root用户密码配置Hadoop下载解压Hive提供MySQL Driver包配置Hive初始化元数据库启动Hive(使用Hadoop用户)Hive体验HiveServer2HiveServer2服务启动 Beeline p48、51、52 https://www.bilibili.com/video/BV1WY4y197g7/?…

Uni-Dock:GPU 分子对接使用教程

github文件下载: git clone https://github.com/dptech-corp/Uni-Dock.git cd Uni-Dock/example/screening_test wget https://github.com/dptech-corp/Uni-Dock/releases/download/1.0.0/unidock 将此文件加入到全局变量中 chmod x unidock sudo mv unidock /…

物联网潜在的巨大价值在于大数据分析

物联网潜在的巨大价值在于大数据分析 从数据里去挖掘市场或者用户的精准需求。 往小的说,后台可以统计用户家里各各插座一年甚至更久的用电情况,这些数据也可以通过app或者小程序展现给用户。 用户可以很直观看到自己一年的用电情况,哪个家…

Blazor前后端框架Known-V1.2.10

V1.2.10 Known是基于C#和Blazor开发的前后端分离快速开发框架,开箱即用,跨平台,一处代码,多处运行。 Gitee: https://gitee.com/known/KnownGithub:https://github.com/known/Known 概述 基于C#和Blazo…

任务15、MidJourney视频(Video)参数动态上线,制作惊艳动画短片

15.1 任务概述 本次任务将帮助你掌握Midjourney中的Video参数,并利用这些参数创作出令人惊艳的绘画作品。通过学习Video参数的基本概念和功能,以及案例的实际应用,你将学会如何正确设置和调整这些参数,从而达到你所期望的绘画效果。最终,你将运用所学知识,生成香奈儿模特…

【C++】C++11 新特性总结 | C++ 常见设计模式总结(秋招篇)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言介绍几种C11新特性介绍一下自动类型推导auto和decltype关键字的用法举例讲一下范围基于的for循环介绍一下列表初始化讲一下右值引用,和左值引用的区…

ubuntu服务器配置ftp服务

需求:配置ftp服务用于在windows电脑上直接浏览、下载、上传ubuntu服务器上的文件,用于文件共享,方便实用 效果:用户打开windows资源管理器后输入ftp://xxx.xxx.xxx.xxx (公网IP地址)后,即可浏览…

map和set的使用总结

目录 一、关联式容器二、键值对三、树形结构的关联式容器3.1 set3.1.1 set介绍3.1.2 set的模板参数列表3.1.3 set的使用实例 3.2 map3.2.1 map的介绍3.2.2 map的参数列表说明3.2.3 map的operator[](very very very好用,map的精华)3.2.4 map的…