当前位置: 首页 > article >正文

[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());//0

sb.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());//0

sb.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());//0

sb.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.kler.cn/a/516560.html

相关文章:

  • 人脸识别打卡系统--基于QT(附源码)
  • Java导出通过Word模板导出docx文件并通过QQ邮箱发送
  • Linux网络之TCP
  • C语言-----扫雷游戏
  • 2024年度总结
  • linux-ubuntu学习笔记碎记
  • PyTorch入门 - 为什么选择PyTorch?
  • arcgis for js只显示范围内的天地图,其余部分透明
  • Vue基础(2)
  • 前k个高频元素力扣--347
  • 详解C#中的特性(Attribute)
  • 小游戏源码开发搭建技术栈和服务器配置流程
  • 独立开发者产品日刊:将 Figma 设计转化为全栈应用、对话 PDF生成思维导图、视频转 AI 笔记、AI问答引擎、Mac 应用启动器切换器
  • Python散点统计栅格化
  • 动态规划(路径问题)
  • 安宝特方案 | AR在供应链管理中的应用:提升效率与透明度
  • HTML常用标签
  • Docker基础安装与使用
  • LatentSync数字人,一键批量,口型同步,MPS加速(WIN/MAC)
  • 设计模式Python版 单例模式
  • c#的tabControl控件实现自定义标签颜色
  • 【SpringBoot实现xss防御】
  • 期权帮|在股指期货中超过持仓限额怎么办?
  • 【Redis】持久化机制
  • 【JVM】垃圾收集器详解
  • 解决CentOS9系统下Zabbix 7.2图形中文字符乱码问题