当前位置:首页 » 编程语言 » 字符串操作java

字符串操作java

发布时间: 2024-11-11 22:02:09

⑴ 浅谈java中字符串的初始化(详细图解)

前言

在深入学习字符串类之前,我们先搞懂JVM是怎样处理新生字符串的。当你知道字符串的初始化细节后,再去写Strings="hello"或Strings=newString("hello")等代码时,就能做到心中有数。

首先得搞懂字符串常量池的概念,下面进入正文吧。

常量池

把经常用到的数据存放在某块内存中,避免频繁的数据创建与销毁,实现数据共享,提高系统性能。

八种基础数据类型除了float和double都实现了常量池技术。在近代的JDK版本中(1.7后),字符串常量池被实现在Java堆内存中。

下面通过三行代码让大家对字符串常量池建立初步认识:

publicstaticvoidmain(String[]args){Strings1="hello";Strings2=newString("hello");System.out.println(s1==s2);//false}

先来看看第一行代码Strings1="hello";

直接通过双引号(Strings1="hello")声明字符串的方式,虚拟机首先会到字符串常量池中查找该字符串是否已经存在。如果存在会直接返回该引用,如果不存在则会在堆内存中创建该字符串对象,然后到字符串常量池中注册该字符串。

上面的代码中(Strings1="hello")虚拟机首先会到字符串常量池中查找是否有存在hello字符串对应的引用。发现没有后会在堆内存创建hello字符串对象(内存地址0x0001),然后到字符串常量池中注册地址为0x0001的hello对象,也就是添加指向0x0001的引用。最后把字符串对象返回给s1。

下面看Strings2=newString("hello");

当我们使用new关键字创建字符串对象的时候,JVM将不会查询字符串常量池,它将会直接在堆内存中创建一个字符串对象,并返回给所属变量。

所以s1和s2指向的是两个完全不同的对象,判断s1==s2的时候会返回false。

再来看下面的示例:

publicstaticvoidmain(String[]args){Strings1=newString("hello")+newString("world");s1.intern();Strings2="helloworld";System.out.println(s1==s2);//true}

第一行代码Strings1=newString("hello")+newString("world");的执行过程是这样子的:

依次在堆内存中创建hello和world两个字符串对象;

然后把它们拼接起来(底层使用StringBuilder实现);

在拼接完成后会产生新的helloworld对象,这时变量s1指向新对象helloworld。

执行完第一行代码后,内存是这样子的:

第二行代码s1.intern();

当调用intern()方法时,首先会去常量池中查找是否有该字符串对应的引用,如果有就直接返回该字符串;

如果没有,就会在常量池中注册该字符串的引用,然后返回该字符串。

由于第一行代码采用的是new的方式创建字符串,所以在字符串常量池中没有保存helloworld对应的引用,虚拟机会在常量池中进行注册,注册完后的内存示意图如下:

第三行代码Strings2="helloworld";

首先虚拟机会去检查字符串常量池,发现有指向helloworld的引用。然后把该引用所指向的字符串直接返回给所属变量。

执行完第三行代码后,内存示意图如下:

如图所示,s1和s2指向的是相同的对象,所以当判断s1==s2时返回true。

总结:

当用new关键字创建字符串对象时,不会查询字符串常量池;

当用双引号直接声明字符串对象时,虚拟机将会查询字符串常量池。

说白了就是:字符串常量池提供了字符串的复用功能,除非我们要显式创建新的字符串对象,否则对同一个字符串虚拟机只会维护一份拷贝。

编译代码验证字符串初始化操作

下面我们再来看一个示例:

publicclassMain{publicstaticvoidmain(String[]args){Strings1="hello";Strings2="world";Strings3=s1+s2;Strings4="helloworld";System.out.println(s3==s4);}}

首先第一行和第二行是常规的字符串对象声明,它们分别会在堆内存创建字符串对象,并会在字符串常量池中进行注册。

影响我们做出判断的是第三行代码Strings3=s1+s2;,我们不知道s1+s2在创建完新字符串helloworld后是否会在字符串常量池进行注册。

简单点说:我们不知道这行代码是以双引号形式声明字符串,还是用new关键字创建字符串。

那么我们看下这端代码的反编译后的代码:

PSD:codejavaSE argetclassesdemo>javap-c.Main.classCompiledfrom"Main.java"publicclassdemo.Main{publicdemo.Main();Code:0:aload_01:invokespecial#1//Methodjava/lang/Object."<init>":()V4:returnpublicstaticvoidmain(java.lang.String[]);Code:0:ldc#2//Stringhello2:astore_13:ldc#3//Stringworld5:astore_26:new#4//classjava/lang/StringBuilder9:p10:invokespecial#5//Methodjava/lang/StringBuilder."<init>":()V13:aload_114:invokevirtual#6//Methodjava/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;17:aload_218:invokevirtual#6//Methodjava/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;21:invokevirtual#7//Methodjava/lang/StringBuilder.toString:()Ljava/lang/String;24:astore_325:ldc#8//Stringhelloworld27:astore429:getstatic#9//Fieldjava/lang/System.out:Ljava/io/PrintStream;32:aload_333:aload435:if_acmpne4238:iconst_139:goto4342:iconst_043:invokevirtual#10//Methodjava/io/PrintStream.println:(Z)V46:return}

直接看重点:

21:invokevirtual#7//Methodjava/lang/StringBuilder.toString:()Ljava/lang/String;

24:astore_3

虚拟机调用StringBuilder的toString()方法获得字符串helloworld,并存放至s3。

下面是我们追踪StringBuilder的toString()方法源码

@OverridepublicStringtoString(){//Createa,don'tsharethearrayreturnnewString(value,0,count);}

通过以上源码可以看出:s3是通过new关键字获得字符串对象的。

回到题目,也就是说字符串常量表中没有存储helloworld的引用,当s4以引号的形式声明字符串时,由于在字符串常量池中查不到相应的引用,所以会在堆内存中新创建一个字符串对象。所以s3和s4指向的不是同一个字符串对象,结果为false。

总结

阅读完本文,相信你对于字符串的初始化的了解又更上一层了。关注我,一个专注分享Java知识的新时代农民工。

作者:初念初恋

⑵ Java工具类(一)Guava操作字符串

在Java编程中,处理字符串是一个常见任务,从简单的空值判断到复杂的拆分和连接操作,都需要高效、简便的解决方案。为简化这类任务,Google开发了Guava库,提供丰富的集合工具和高效字符串处理功能。本文将深入探讨Guava库的字符串操作能力,重点关注连接器、拆分器、字符匹配器、字符集和大小写格式工具。

Guava连接器(Joiner)是一个强大的字符串连接工具,能够优雅地处理空值问题。其使用方式分为三步:使用`on`方法设置连接符,调用`useForNull`方法为`null`值设定默认处理,最后使用`join`方法处理集合。例如:

java
Joiner joiner = Joiner.on(", ");
String result = joiner.join(Arrays.asList("apple", null, "banana"));

Guava拆分器(Splitter)允许以模式、字符、字符串或字符匹配器进行复杂拆分,返回`Iterable`对象。其创建和配置过程同样遵循不可变设计原则,确保线程安全。

字符匹配器(CharMatcher)则提供了一种简单而强大的方式来处理特定类型的字符,如数字或空白字符。它实现了一个布尔判断接口,并提供了多种方法来操作匹配字符,如修剪、折叠、移除、保留等。

Charsets为Java平台提供的六种标准字符集提供了常量引用,确保了跨平台兼容性。使用这些常量而非名称获取实例能避免潜在的不兼容性问题。

大小写格式(CaseFormat)工具用于方便地在不同ASCII大小写规范间转换字符串,支持多种格式。例如,转换字符串以适应编程语言的命名规范。

总结而言,Guava的字符串处理工具集不仅简化了常见字符串操作,还提供了高性能、灵活的解决方案,适用于大规模数据处理。在使用时,需根据具体需求和场景合理选择工具和参数,以实现性能优化。Guava库的高效设计和丰富功能,为Java开发者提供了强大的支持,有助于提高开发效率和代码质量。

⑶ Java字符串格式化和工具类使用

前言

我们在做项目时候经常需要对字符串进行处理,判断,操作,所以我就总结了一下java字符串一些常用操作,和推荐比较好用我在自用的工具类,毕竟有轮子我们自己就不用重复去写了,提供开发效率,剩下的时间就去约女朋友吧哈哈哈!!!!

java内置操作format

我们知道平时我们都会做字符串拼接打印操作,单还是在用?号嘛,那样就很low为力显示逼格,使用format操作很有必要?

String类的format()方法用于创建格式化的字符串以及连接多个字符串对象,制定字符串格式和参数生成格式化的字符串。显示不同转换符实现不同数据类型到字符串的转换

测试用例:

@Testpublicvoida(){Stringstr="";str=String.format("Hi,%s","王力");System.out.println(str);str=String.format("Hi,%s:%s.%s","王南","王力","王张");System.out.println(str);System.out.printf("字母a的大写是:%c%n",'A');System.out.printf("3>7的结果是:%b%n",3>7);System.out.printf("100的一半是:%d%n",100/2);System.out.printf("100的16进制数是:%x%n",100);System.out.printf("100的8进制数是:%o%n",100);System.out.printf("50元的书打8.5折扣是:%f元%n",50*0.85);System.out.printf("上面价格的16进制数是:%a%n",50*0.85);System.out.printf("上面价格的指数表示:%e%n",50*0.85);System.out.printf("上面价格的指数和浮点数结果的长度较短的是:%g%n",50*0.85);System.out.printf("上面的折扣是%d%%%n",85);System.out.printf("字母A的散列码是:%h%n",'A');}

打印结果

._________/\/___'_____(_)______\\(()\___|'_|'_||'_/_`|\\\/___)||_)|||||||(_||))))'|____|.__|_||_|_||_\__,|////=========|_|==============|___/=/_/_/_/::SpringBoot::(v2.4.7)2021-09-1010:42:07INFObackground-preinitorg.hibernate.validator.internal.util.VersionHV000001:HibernateValidator6.1.7.Final2021-09-1010:42:.8.0_202onxiangyongdeMacBook-Pro.localwithPID46281(startedbyxiangyongin/Users/xiangyong/selfProject/project/kmall/kmall-api)2021-09-1010:42::test,mptest__|___|_.____|_|||/|_)(_|||_|_)||_|_/|3.4.12021-09-1010:42:.755seconds(JVMrunningfor8.519)Hi,王力Hi,王南:王力.王张字母a的大写是:A3>7的结果是:false100的一半是:50100的16进制数是:64100的8进制数是:14450元的书打8.5折扣是:42.500000元上面价格的16进制数是:0x1.54p5上面价格的指数表示:4.250000e+01上面价格的指数和浮点数结果的长度较短的是:42.5000上面的折扣是85%字母A的散列码是:41

更多格式进入参考这里

equals

两个字符串做比较,当然这里比较的话就不得不提老生常谈的问题,==和equals区别

首先的区别是,equals是方法,而==是操作符;

equals比较的是两个字符串内容而不是引用

==在比较对象时比较的是引用地址是否相同,在比较基本类型时比较的是其内容

@Testpublicvoida(){//s1与s2不是同一个对象Strings1=newString("aaa");Strings2=newString("aaa");System.out.println(s1==s2);//falseSystem.out.println(s1.equals(s2));//true//s5与s6是基本数据类型Strings5="aaa";Strings6="aaa";System.out.println(s5==s6);//trueSystem.out.println(s5.equals(s6));//true//s3和s4是同一个地址的引用Strings3=newString("aaa");Strings4=s3;System.out.println(s3==s4);//trueSystem.out.println(s3.equals(s4));//true}

注意我们看到s5==s6是true而s1==s2是false,因为s5和s6是基本数据类型此时比较的是值,s1和s2是对象比较的是引用所以是不同两个String对象比较引用

这里涉及到基本数据类型:

Java中有8种基本数据类型(字母开头小写),即boolean、byte、short、char、int、float、long、double,基本数据类型不是对象,放在堆栈中,用完就销毁,访问速度快。而对象放在堆中。如果必须用到对象Java针对每种基本数据类型提供了包装类,即Boolean、Byte、Short、Character、Integer、Float、Long、Double(开头大写)等。

详细深入参考点击进入

toString

返回当前String对象的字符串表示形式,一般用于打印对象信息方便快捷,所有类都继承object,任何类,都可以重写toString方法

工具类hutool

借用官方引用:

Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的

点击进入官网导航强烈推荐

已发布maven中央仓库,多么模块可以单独引用某一个模块,也可以引用全部,

包含组件如下:

ApacheCommons

分的比较·散乱单,应为不是专门的工具库,但是用起来还是挺不错的使用频率最高的框架。有很多实用的工具类并没有全部列出来,只列出了最基础的一部分,感兴趣的小伙伴,可以看官方的api进行更深入的学习

ApacheCommons有很多子项目,常用的项目如下

详细使用参考这里点击进入

作者:kenx

⑷ java中字符串如何去除最后一个字符

在Java中,处理字符串并移除最后一个字符的操作相当直接,主要借助于String类的两个方法:substring()和length()。以下是详细的步骤:

1.使用substring()方法:这个方法有两个参数,第一个参数是开始截取的索引(包括该位置的字符),第二个参数是截止但不包括的索引。当你想要移除最后一个字符时,可以设置开始索引为字符串长度减一,然后截取到原长度。例如:

java

Stringoriginal="example";

intlastCharIndex=original.length()-1;

Stringresult=original.substring(0,lastCharIndex);

2.利用length()方法获取字符串长度:这个方法返回字符串中的字符数,包括空格和特殊字符。通过减一,我们可以得到最后一个字符的位置。

3.如果你希望移除字符串尾部的特定字符,而非仅最后一个字符,可以考虑使用trim()方法。RTrim()和TrimEnd()是trim()方法的变体:

-RTrim()会移除字符串末尾的空格或特定字符数组中的字符。

-TrimEnd()接受一个字符数组作为参数,移除数组中每个字符的尾部出现。

以下是使用这些方法的实例:

java

Stringstr="example@trimme";

Stringtrimmed=str.trim();

Stringrtrimmed=str.RTrim('@');//或者str.TrimEnd('@');

通过上述方法,你可以有效地在Java中移除字符串的最后一个字符或尾部特定字符。

热点内容
怎么改邮政网银密码 发布:2024-11-22 18:06:24 浏览:353
压缩机不制冷 发布:2024-11-22 17:57:45 浏览:428
linux面试题及答案100 发布:2024-11-22 17:56:06 浏览:16
密码门卡如何用nfc 发布:2024-11-22 17:45:11 浏览:137
linux开启snmp 发布:2024-11-22 17:40:51 浏览:938
js检测手机访问 发布:2024-11-22 17:25:08 浏览:798
ftp服务器上传不了文件怎么办 发布:2024-11-22 17:24:19 浏览:259
数据库改售价 发布:2024-11-22 17:19:54 浏览:997
安卓rom资源哪个好 发布:2024-11-22 17:18:18 浏览:447
keil编译路径不对 发布:2024-11-22 17:08:20 浏览:487