[java] java基础-字符串篇

目录

API

String

创建字符串对象的两种方式:

Java的内存模型

字符串常量池(串池)存放地址

两种构造方法的内存分析

String的常用方法

==号比较的是什么

字符串比较(比较字符串的数据值)

遍历字符串

StringBuilder

使用场景

 构造方法

常用方法

StringJoiner

构造方法

成员方法

字符串相关的底层原理

原理1:字符串存储的内存原理

原理2:==号比较的到底是什么

原理3:字符串拼接的底层原理

拼接时没有变量

拼接时有变量

原理4:StringBuilder提高效率原理

原理5:StringBuilder源码分析

常见面试题

下列代码的运行结果(有变量)

下列代码的运行结果是(无变量)


API

API:应用程序编程接口
java API:指JDK中提供的各种功能的Java类,这些类将底层的实现封装起来,我们不需要关心这些类是如何实现的,只需要学习这些类是如何使用即可。

(API就是别人已经写好的东西,我们不用自己编写,直接使用即可)

API 例如:

  • Scanner 键盘录入
  • Random 随机数

API帮助文档:帮助开发人员更好的使用API和查询API的一个工具

API帮助文档
下载链接:https://pan.quark.cn/s/f3fd6e8bd977
提取码:meJU

用手机复制链接到夸克即可打开

找到需要的方法

String

String 是Java定义好的一个类,定义在java.lang包中,所以使用的时候不用导包

Java程序中的所有字符串文字("abc")都被称为java.lang.String类的对象

只要有字符串参加的+操作,都是字符串的拼接,字符串拼接会产生一个新的字符串

"abc"+true="abctrue";
//将abc和true进行拼接,形成新的字符串

 字符串的内容是不会发生改变的,它的对象在创建之后不能被更改

String name="123";
String address="456";
System.out.println(name+address);
//产生了3个字符串
String name="123";
name="456";
//产生了两个字符串,在常量池中创建新的字符串"456"后,
再赋值给name

创建字符串对象的两种方式:

1、直接赋值(常用)

String name="abc";

2、new 构造方法

(1)创建空白字符串,不含任何内容

空参构造,获取一个空白的字符串对象

public String () 
//""没有任何内容的字符串对象

(2)根据传入的字符串,创建字符串对象

public String (String str)

(3)根据字符数组,创建字符串对象(常用)

适用场景要求:要修改字符串的内容,可以直接修改字符数组

public String (char[] chs)例:
char[] chs ={'a','b','c'};
String str =new String(chs);//abc

 (4)根据字节数组,创建字符串对象(常用)

适用场景要求:把字节信息转成字符串,先根据字ascii码表查询,换成对应的字符,再创建成字符串对象

在网络中传输的数据是字节

public String (byte[] chs)例:
byte[] chs ={97,98,99};
String str =new String (chs);//abc

Java的内存模型

栈内存:方法运行的时候进栈,执行完毕出栈
堆内存:new的对象都在这里
方法区:字节码文件、临时存储

字符串常量池(串池)存放地址

JDK7以前字符串常量池在方法区,JDK7开始存放在堆内存

两种构造方法的内存分析

直接赋值:(存放在串池中,简单,节约内存)

系统会先检查该字符串在字符串常量池中是否存在,存在则复用,不存在则创建新的

new新建:

new的字符数组在堆内存中,new字符串在堆内存中开辟空间,相同字符串也会开辟空间,容易浪费内存,建议使用直接赋值

从键盘输入的数据属于new String

String s1=new String("abc");//记录堆里面的地址值
String s2="abc";//记录串池中的地址值
System.out.println(s1==s2);//false

String的常用方法

==号比较的是什么

基本数据类型:数据值

引用数据类型:地址值(String属于引用数据类型)

字符串比较(比较字符串的数据值)

boolean equals方法(要比较的字特串)  完全一样true  否则 false
boolean equalsIgnoreCase(要比较的字符串)忽略大小写的比较(英文状态的大小写 a A)

String s1=new String("abc");//记录堆里面的地址值
String s2="abc";//记录串池中的地址值
System.out.println(s1==s2);//false
//比较字符串对象中的内容是否相等
boolean result=s1.equals(s2);//true
//示例:已知正确的用户名和密码,请用程序实现模拟用户登录
//总共三次机会,登录之后,给出相应提示public static void main(String[] args){//1.定义两个变量记录正确的用户名和密码
String rightUsername = "zhangsan";
String rightPassword = "123456";Scanner sc = new Scanner(System.in);
//2.键盘录入用户名和密码
for (int i = 0;i < 3; i++) {
// 0 1 2
System.out.println("请输入用户名");
String username = sc.next();
System.out.println("请输入密码");
String password = sc.next();//3.比较
if (username.equals(rightUsername) && password.equals(rightPassword)) {
System.out.println("用户登录成功");
break;
} else {
if(i == 2){
//最后一次机会也输入错误,此时要提示账号被锁定
System.out.println("账号"+ username+"被锁定,请联系:XXX-XXXXX");
}else{
Svstem.out.println("用户登录失败,用户名或密码有误,您还剩下"+(2-i)+"次机会");//2 1 0}}
}

遍历字符串

public char charAt (int index):根据索引返回字符
public int length():返回此字符串的长度

数组长度:数组名.length--属性,不加括号

字符串长度:字符串对象.length()--方法,加括号

//示例:遍历字符串
public class StringDemo5 {
public static void main(String[] args) {//1.键盘录入一个字符串
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串");
String str = sc.next();//2.进行遍历
for (int i = 0;i < str.length(); i++) {
//i 依次表示字符串的每一个索引
char c = str.charAt(i);
System.out.println(c);
}}

String substring(int beginIndex, int endIndex):截取
包头不向尾,包左不同右,只有返回值才是截取的小串
String substring( int beginIndex):截取到末尾

//示例:手机号屏蔽:
String phoneNumber=“12345671234”;
String start =phoneNumber. substring(0,3);//"123"String end = phoneNumben.substring (7);//"1234"
String result = start+"****"+end;//123****1234

String replace(旧值,新值)替换

只有返回值才是替换后的结果

//示例:敏感词替换
String talk="你玩得真好,TMD, CNM";
String[] arr={"TMD","CNM”,“SB” "MLGB"};
for(int i=0;i<arr.length; i++)
{
talk= talk.replace(arr[i],"***");
};
//talk="你玩得真好,***,***"

StringBuilder

可以看作是一个容器,创建之后里面的内容是可变的

作用:提高字符串的操作效率

使用String进行字符串拼接时,每拼接一次就会产生一个新的字符串,浪费内存且浪费时间

而StringBuilder则是看作容器,在进行字符串拼接时不用每次都产生新的字符串,而是在原基础上进行拼接

使用场景

字符串拼接

字符串反转

 构造方法

public StringBuilder():创建一个空白可变的字符串对象,不含有任何内容

public StringBuilder(String str):根据字符串的内容,来创建可变字符串对象

常用方法

public StringBuilder append(任意类型):添加数据,并返回对象本身

public StringBuilder reverse():反转容器中的内容

public int length():返回长度(字符出现的个数)

public String toString():实现将StringBuilder转换为String

(StringBuilder对象转为字符串)

/*
示例:对称字符串
需求:键盘接受一个字符串,程序判断出该字符串是否是对称字符串,并在控制台打印是或不是
对称字符串:123321、111
非对称字符串:123123
*/public static void main(String[] args) {//1.键盘录入一个字符串
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串");
String str = sc.next();//2.反转键盘录入的字符串
String result = new StringBuilder().append(str).reverse().toString();//3.比较
if(str.equals(result)){
System.out.println("当前字符串是对称字符串");
}else{
System.out.println("当前字符串不是对称字符串");
}
}
/*
示例:拼接字符串
需求:定义一个方法,把 int数组中的数据按照指定的格式拼接成一个字符串返回。
调用该方法,并在控制台输出结果。
例如:数组为int[] arr={1,2,3};
执行方法后的输出结果为:[1,2,3]
*/public static void main(String[] args) {//1.定义数组
int[] arr = {1, 2, 3};//2.调用方法把数组变成字符串
String str = arrToString(arr);
System.out.println(str);
}public static String arrToString(int[] arr){
StringBuilder sb = new StringBuilder();
sb.append("[");for (int i = 0; i < arr.length; i++) {
if(i == arr.length - 1){
sb.append(arr[i]);
}else{
sb.append(arr[i]).append(", ");
}
}sb.append("]");
return sb.tostring();
}

StringJoiner

像上面拼接字符串的例子,使用StringBuilder,代码复杂,所以出现了StringJoiner,拼接速度快,且代码简单的方式

/*
示例:拼接字符串
需求:定义一个方法,把 int数组中的数据按照指定的格式拼接成一个字符串返回。
调用该方法,并在控制台输出结果。
例如:数组为int[] arr={1,2,3};
执行方法后的输出结果为:[1,2,3]
*/public static void main(String[] args) {
int[] arr = {1, 2, 3};
StringJoiner sj = new StringJoiner(", ", "[", "]");for (int i = 0; i < arr.length; i++){
sj.add(arr[i] + "");
System.out.println(sj);
}
}

StringJoiner跟StringBuilder一样,也可以看成是一种容器,创建之后里面的内容是可以改变的

作用:提高字符串的操作效率,而且代码编写特别简洁,但是目前市场上很少有人用

jdk8出现的

构造方法

public StringJoiner(间隔符号):创建一个StringJoiner对象,指定拼接时的间隔符号

public StringJoiner(间隔符号,开始符号,结束符号):创建一个StringJoiner对象,指定拼接时的间隔符号,开始符号,结束符号

没有无参构造

成员方法

public StringJoiner add(添加的内容):添加数据,并返回对象本身

public int length():返回长度(字符出现的个数)

public String to String():返回一个字符串(该字符串就是拼接之后的结果)

public static void main(String[] args) {//1.创建对象
StringJoiner sj = new StringJoiner( delimiter: ",", prefix: "[", suffix: "]");//2.添加元素
sj.add("aaa").add("bbb").add("ccc");
int len = sj.length();
System.out.println(len);//13//3.打印
System.out.println(sj);//[aaa,bbb,ccc]String str = sj.toString();
System.out.println(str);//[aaa,bbb,ccc]
}

字符串相关的底层原理

原理1:字符串存储的内存原理

直接赋值会复用字符串常量池中的
new出来不会复用,而是开辟一个新的空间

原理2:==号比较的到底是什么

基本数据类型:数据值

引用数据类型:地址值

原理3:字符串拼接的底层原理

拼接时没有变量

public class Test {
public static void main(String[] args) {
String s= "a" +"b"+"c";
System.out.println(s);
}
}

拼接的时候没有变量,都是字符串。

触发字符串的优化机制。
在编译的时候就已经是最终的结果了。

//java文件
public class Test {
public static void main(String[] args) {
String s = "a"+"b"+"c";
System.out.println(s);
}
}
//编译后的class文件
public class Test {
public static void main(String[] args) {
String s ="abc";
System.out.println(s);
}
}

拼接时有变量

JDK8以前

public class Test {
public static void main(String[] args) {
String s1 = "a";
String s2= s1+"b";
//实际执行为new StringBuilder().append(s1).append("b").toString();
//toString 方法实际为new String,即上面的语句实际创建了两个对象,一个+,堆内存中两个对象
//new StringBuilder和new String
String s3= s2+"c";
//创建新的StringBuilder和String对象
//实际执行为new StringBuilder().append(s2).append("c").toString();
//toString 方法实际为new String,即上面的语句实际创建了两个对象,一个+,堆内存中两个对象
//new StringBuilder和new String
System.out.println(s3);
}
}

有变量参与,在内存中创建了很多对象,浪费空间,也非常慢

在JDK8中,会先预估拼接之后的字符串需要的空间大小,创建数组,把要拼接的内容放在数组中

如果很多字符串变量拼接,不要直接+,在底层会创建多个对象,浪费时间,浪费性能

建议使用StringBuilder或者StringJoiner

有变量参与,都是字符串直接相加,编译之后就是拼接之后的结果,会复用串池中的字符串

如果有变量参与,每一行拼接的代码,都会在内存中创建新的字符串,浪费内存。

原理4:StringBuilder提高效率原理

public class Test {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
sb.append("a");
sb.append("b");
sb.append("c");
System.out.printIn(sb);
}
}

 所有要拼接的内容都会往StringBuilder中放,不会创建很多无用的空间,节约内存

原理5:StringBuilder源码分析

默认创建一个长度为16的字节数组
添加的内容长度小于16,直接存
添加的内容大于16会扩容(原来的容量*2+2)
如果扩容之后还不够,以实际长度为准

public class Test4 {
public static void main(Stringl] args) {
StringBuilder sb = new StringBuilder();
//容量:最多装多少
//长度:已经装了多少
System.out.printIn(sb.capacity());//16
system.out.printin(sb.length());//0sb.append("abc");
System.out.printin(sb.capacity());//16
System.out.printIn(sb.length());//3
}
}
public class Test4 {
public static void main(Stringl] args) {
StringBuilder sb = new StringBuilder();
//容量:最多装多少
//长度:已经装了多少
System.out.printIn(sb.capacity());//16
system.out.printin(sb.length());//0sb.append("abcdefghijklmnopqrstuvwxyz");
System.out.printin(sb.capacity());//34
System.out.printIn(sb.length());//26
}
}
public class Test4 {
public static void main(Stringl] args) {
StringBuilder sb = new StringBuilder();
//容量:最多装多少
//长度:已经装了多少
System.out.printIn(sb.capacity());//16
system.out.printin(sb.length());//0sb.append("abcdefghijklmnopqrstuvwxyz0123456789");
System.out.printin(sb.capacity());//36
System.out.printIn(sb.length());//36
}
}

常见面试题

下列代码的运行结果(有变量)

public class Test3 {
public static void main(String[] args) {
String s1 ="abc";//记录串池中的地址值
String s2="ab";
String s3 = s2 +"c";//新new出来的对象,堆地址
System.out.println(s1 == S3);//false
}
}

字符串拼接的时候,如果有变量
JDK8以前:系统底层会自动创建一个StringBuilder对象,然后再调用其append方法完成拼接。拼接后,再调用其toString方法转换为String类型,而toString方法的底层是直接new了一个字符串对象。
JDK8版本:系统会预估要字符串拼接之后的总大小,把要拼接的内容都放在数组中,此时也是产生一个新的字符串。

所以无论是高版本或者低版本的JDK,有变量的字符串进行拼接,都会创建新的对象,存放在堆地址中

下列代码的运行结果是(无变量)

public class Test4 {
public static void main(String[] args){
String s1 ="abc"; //记录串池中的地址值
String s2="a" +"b"+"c"; //复用串池中的字符串
Svstem.out.println(s1 == s2);  //true
}
}

在编译的时候,就会将"a"+"b"+"c"拼接为"abc",所以s1和s2指向串池中的同一个字符串,地址值相同

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

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

相关文章

Unity中关于实现 管道水流+瀑布流动+大肠蠕动效果笔记

Unity中关于实现 管道水流瀑布流动大肠蠕动效果笔记 效果展示&#xff1a; 参考资料及链接&#xff1a; 1、如何在 Unity 中创建水效果 - 水弯曲教程 https://www.youtube.com/watch?v3CcWus6d_B8 关于补充个人技能中&#xff1a;顶点噪波影响网格着色器配合粒子实现水特效 …

Couchbase UI: Indexes

在Couchbase中&#xff0c;索引的这些指标可以帮助你评估索引的性能和状态。下面是每个指标的详细解释&#xff0c;以及如何判断索引的有效性&#xff1a; 1. Index Name&#xff08;索引名称&#xff09; 描述&#xff1a;每个索引都有一个唯一的名称。这个名称通常会包括表…

redis的分片集群模式

redis的分片集群模式 1 主从哨兵集群的问题和分片集群特点 主从哨兵集群可应对高并发写和高可用性&#xff0c;但是还有2个问题没有解决&#xff1a; &#xff08;1&#xff09;海量数据存储 &#xff08;2&#xff09;高并发写的问题 使用分片集群可解决&#xff0c;分片集群…

第一届“启航杯”网络安全挑战赛WP

misc PvzHE 去这个文件夹 有一张图片 QHCTF{300cef31-68d9-4b72-b49d-a7802da481a5} QHCTF For Year 2025 攻防世界有一样的 080714212829302316092230 对应Q 以此类推 QHCTF{FUN} 请找出拍摄地所在位置 柳城 顺丰 forensics win01 这个软件 云沙盒分析一下 md5 ad4…

ThreadLocal概述、解决SimpleDateFormat出现的异常、内存泄漏、弱引用、remove方法

①. ThreadLocal简介 ①. ThreadLocal是什么 ①. ThreadLocal本地线程变量,线程自带的变量副本(实现了每一个线程副本都有一个专属的本地变量,主要解决的就是让每一个线程绑定自己的值,自己用自己的,不跟别人争抢。通过使用get()和set()方法,获取默认值或将其值更改为当前线程…

蓝桥杯模拟算法:多项式输出

P1067 [NOIP2009 普及组] 多项式输出 - 洛谷 | 计算机科学教育新生态 这道题是一道模拟题&#xff0c;我们需要分情况讨论&#xff0c;我们需要做一下分类讨论 #include <iostream> #include <cstdlib> using namespace std;int main() {int n;cin >> n;for…

LLM - 大模型 ScallingLaws 的设计 100B 预训练方案(PLM) 教程(5)

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/145356022 免责声明&#xff1a;本文来源于个人知识与公开资料&#xff0c;仅用于学术交流&#xff0c;欢迎讨论&#xff0c;不支持转载。 Scalin…

深度解析:基于Vue 3的教育管理系统架构设计与优化实践

一、项目架构分析 1. 技术栈全景 项目采用 Vue 3 TypeScript Tailwind CSS 技术组合&#xff0c;体现了现代前端开发的三大趋势&#xff1a; 响应式编程&#xff1a;通过Vue 3的Composition API实现细粒度响应 类型安全&#xff1a;约60%的组件采用TypeScript编写 原子化…

计算机组成原理(2)王道学习笔记

数据的表示和运算 提问&#xff1a;1.数据如何在计算机中表示&#xff1f; 2.运算器如何实现数据的算术、逻辑运算&#xff1f; 十进制计数法 古印度人发明了阿拉伯数字&#xff1a;0&#xff0c;1&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;5&#xff0c;6&#…

(详细)Springboot 整合动态多数据源 这里有mysql(分为master 和 slave) 和oracle,根据不同路径适配不同数据源

文章目录 Springboot 整合多动态数据源 这里有mysql&#xff08;分为master 和 slave&#xff09; 和oracle1. 引入相关的依赖2. 创建相关配置文件3. 在相关目录下进行编码&#xff0c;不同路径会使用不同数据源 Springboot 整合多动态数据源 这里有mysql&#xff08;分为maste…

AI如何帮助解决生活中的琐碎难题?

引言&#xff1a;AI已经融入我们的日常生活 你有没有遇到过这样的情况——早上匆忙出门却忘了带钥匙&#xff0c;到了公司才想起昨天的会议资料没有打印&#xff0c;或者下班回家还在纠结晚饭吃什么&#xff1f;这些看似微不足道的小事&#xff0c;往往让人疲惫不堪。而如今&a…

一分钟搭建promehteus+grafana+alertmanager监控平台

为什么要自己搭建一个监控平台 平时进行后端开发&#xff0c;特别是微服务的后端可开发&#xff0c;一定少不了对接监控平台&#xff0c;但是平时进行一些小功能的测试又没有必要每次都手动安装那么多软件进行一个小功能的测试&#xff0c;这里我使用docker-compose搭建了一个…

深入MapReduce——计算模型设计

引入 通过引入篇&#xff0c;我们可以总结&#xff0c;MapReduce针对海量数据计算核心痛点的解法如下&#xff1a; 统一编程模型&#xff0c;降低用户使用门槛分而治之&#xff0c;利用了并行处理提高计算效率移动计算&#xff0c;减少硬件瓶颈的限制 优秀的设计&#xff0c…

前端【10】jQuery DOM 操作

目录 jquery捕获查取 获得内容 - text()、html() 以及 val() 获取属性 - attr() ​编辑 jQuery 修改/设置内容和属性 设置内容 - text()、html() 以及 val() 设置属性 - attr() jQuery添加元素 jQuery - 删除元素 前端【9】初识jQuery&#xff1a;让JavaScript变得更简…

进程控制的学习

目录 1.进程创建 1.1 fork函数 1.2 fork函数返回值 1.3 写时拷贝 1.4 fork 常规用法 1.5 fork 调用失败的原因 2. 进程终止 2.1 进程退出场景 2.2 进程常见退出方法 2.2.1 从main 返回 2.2.2 echo $&#xff1f; 查看进程退出码 2.2.2.1 我们如何得到退出码代表的含…

数据结构与算法分析:专题内容——人工智能中的寻路7之AlphaBeta(代码详解)

一、算法描述 在考虑到对手的可能走法之后&#xff0c;Minimax算法能够较为恰当地找出玩家的最优走法。但是&#xff0c;在生成博弈树时&#xff0c;这个信息却没有使用&#xff01;我们看看早先介绍的BoardEvaluation评分函数。回忆一下下图Minimax的探测&#xff1a; 这是从…

12、本地缓存分布式缓存(未完待续)

1、哪些数据适合放入缓存&#xff1f; 即时性、数据一致性要求不高的访问量大且更新频率不高的数据&#xff08;读多&#xff0c;写少&#xff09; 2、本地缓存 1、本地缓存&#xff0c;如果是单体项目&#xff0c;部署到一台服务器上&#xff0c;就不存在什么问题&#xff…

Linux——网络基础(1)

文章目录 目录 文章目录 前言 一、文件传输协议 应用层 传输层 网络层 数据链路层 数据接收与解封装 主机与网卡 数据传输过程示意 二、IP和MAC地址 定义与性质 地址格式 分配方式 作用范围 可见性与可获取性 生活例子 定义 用途 特点 联系 四、TCP和UDP协…

免费GPU算力,不花钱部署DeepSeek-R1

在人工智能和大模型技术飞速发展的今天&#xff0c;越来越多的开发者和研究者希望能够亲自体验和微调大模型&#xff0c;以便更好地理解和应用这些先进的技术。然而&#xff0c;高昂的GPU算力成本往往成为了阻碍大家探索的瓶颈。幸运的是&#xff0c;腾讯云Cloud Studio提供了免…

阿里前端开发规范

文章目录 1. 为什么前端写代码要规范&#xff1f;一、代码规范的必要性二、 规范带来的好处 2. 资源一、推荐 1. 为什么前端写代码要规范&#xff1f; 一、代码规范的必要性 可维护性 统一的代码风格便于理解和修改减少代码维护成本降低项目交接难度 团队协作 提高团队开发效…