IT技术基础篇聊聊Java的String,还有那么几个面试弯
前言
有人说看了你的基本类型篇,那我期望有Java语言表达一句话还不成了是吧,我是不是得一字一顿呢?当然不是啦,Java中存在着String,只要使用双引号概括起来的那么就是一个String(字符串)。设计
字符串操作那可是计算机程序设计中最常见的行为了,使用频率高的因素决定了其定位与设计,设计者将其定位为不可变,不可变的表现如下:在设计上String类通过final修饰了类,同时将存放内容的char数组也使用final修饰。final关键字修饰的属性为不可修改的,修饰的类是不可继承的,如此就限制了使用者对其修改。publicfinalclassStringimplementsjava。io。Serializable,ComparableString,CharSequence,Constable,ConstantDesc{Stableprivatefinalbyte〔〕value;。。。}我们可以通过String类的源码先从表象看一看,每一个看起来会修改其值的方法最终都是创建了一个新的String对象。如下图字符串的截取方法,指定起止下标,但返回时如果截取长度与字符串长度一致返回当前对象,否则就创建一个新的对象返回。publicStringsubstring(intbeginIndex,intendIndex){intlengthlength();checkBoundsBeginEnd(beginIndex,endIndex,length);intsubLenendIndexbeginIndex;if(beginIndex0endIndexlength){returnthis;}returnisLatin1()?StringLatin1。newString(value,beginIndex,subLen):StringUTF16。newString(value,beginIndex,subLen);}位置使用常量方式创建的字符串存放在常量池里使用new方式创建的字符串存放在堆里
说到这里就顺便了一下String提供的方法intern(),这个方法就有点意思了,根据下图源码表示,这个方法是返回一个标准化的表示方式,通过字符串的常量池进行返回,也就是说针对字符串调用此方法就会统一表示,主要是针对通过new创建在堆上的字符串,调用此方法,它会先去常量池里发现,如果存在返回它,如果不存在就会放入常量池并返回,简单理解就是将存在于堆的字符串放入常量池。Returnsacanonicalrepresentationforthestringobject。pApoolofstrings,initiallyempty,ismaintainedprivatelybytheclass{codeString}。pWhentheinternmethodisinvoked,ifthepoolalreadycontainsastringequaltothis{codeString}objectasdeterminedbythe{linkequals(Object)}method,thenthestringfromthepoolisreturned。Otherwise,this{codeString}objectisaddedtothepoolandareferencetothis{codeString}objectisreturned。pItfollowsthatforanytwostrings{codes}and{codet},{codes。intern()t。intern()}is{codetrue}ifandonlyif{codes。equals(t)}is{codetrue}。pAllliteralstringsandstringvaluedconstantexpressionsareinterned。Stringliteralsaredefinedinsection3。10。5oftheciteTheJavaLanguageSpecificationcite。returnastringthathasthesamecontentsasthisstring,butisguaranteedtobefromapoolofuniquestrings。jls3。10。5StringLiteralspublicnativeStringintern();重载
重载就是操作符在应用于对应类时具有特殊意义,这里对于String而言即为连接的作用,以下通过javap命令对于源码进行反编译,进行更直观的确认:java反编译流程(参数很多,请根据需要进行添加)1、javacXXX。java2、javapvXXXpublicclassTest{publicstaticvoidmain(String〔〕args){Stringaa;Stringsbcda;System。out。println(s);}}0:ldc2Stringa2:astore13:new3classjavalangStringBuilder6:dup7:invokespecial4MethodjavalangStringBuilder。init:()V10:ldc5Stringbcd12:invokevirtual6MethodjavalangStringBuilder。append:(LjavalangString;)LjavalangStringBuilder;15:aload116:invokevirtual6MethodjavalangStringBuilder。append:(LjavalangString;)LjavalangStringBuilder;19:invokevirtual7MethodjavalangStringBuilder。toString:()LjavalangString;22:astore223:getstatic8FieldjavalangSystem。out:LjavaioPrintStream;26:aload227:invokevirtual9MethodjavaioPrintStream。println:(LjavalangString;)V30:return
通过将源代码javap反译后可以看到指令码中,Java在处理拼接的字符串时借助了StringBuilder类,append方法即追加内容,调用toString方法new出来最终结果。
有人会问拼接时有四个元素进行拼接,为什么只调用了2次append方法呢,因为前3个元素均在常量池优化合并。
为了直观地看出,下面的例子,请参照如下,共计调用5次append方法:publicclassTest{publicstaticvoidmain(String〔〕args){Stringaa;Stringsbacad;System。out。println(s);}}0:ldc2Stringa2:astore13:new3classjavalangStringBuilder6:dup7:invokespecial4MethodjavalangStringBuilder。init:()V10:ldc5Stringb12:invokevirtual6MethodjavalangStringBuilder。append:(LjavalangString;)LjavalangStringBuilder;15:aload116:invokevirtual6MethodjavalangStringBuilder。append:(LjavalangString;)LjavalangStringBuilder;19:ldc7Stringc21:invokevirtual6MethodjavalangStringBuilder。append:(LjavalangString;)LjavalangStringBuilder;24:aload125:invokevirtual6MethodjavalangStringBuilder。append:(LjavalangString;)LjavalangStringBuilder;28:ldc8Stringd30:invokevirtual6MethodjavalangStringBuilder。append:(LjavalangString;)LjavalangStringBuilder;33:invokevirtual9MethodjavalangStringBuilder。toString:()LjavalangString;36:astore237:getstatic10FieldjavalangSystem。out:LjavaioPrintStream;40:aload241:invokevirtual11MethodjavaioPrintStream。println:(LjavalangString;)V44:return弯弯绕绕面试
一、请写出以下程序的输出结果publicclassTest{publicstaticvoidmain(String〔〕args){Stringaa;Stringbb;Stringabab;Stringsumab;Stringsumaab;Stringsumabab;System。out。println(absum);trueSystem。out。println(absuma);falseSystem。out。println(absumab);falseSystem。out。println(sumsuma);falseSystem。out。println(sumsumab);falseSystem。out。println(sumasumab);false}}根据前面我们通过反编译得出来的结论:1、常量拼接仍在常量池;2、有变量参与拼接,JDK就会估化操作:Stringaa;Stringsumaab;StringBuildertempnewStringBuilder();temp。append(a);temp。append(b);temp。toString();StringBuilder的toString()方法为newString()
二、问以下语句共创建了几个对象StringsnewString(abc);以上语句等价于:Stringtemp123;01常量池存在,则将堆内对象引用赋值,否则在堆内创建对象,并加入常量池StringsnewString(temp);1所以上述语句共创建12个对象
三、请问以下代码是否存在问题StringlockThread。currentThread()。getName();synchronized(lock){DOSOMETHING}Lock取值为当前线程的名称,但线程名称非常量,存在于堆内,因此在这种情况下会导致锁失效。需使用intern()方法将lock加入常量池。
林勇为报南海撞机之仇,率8万名红客攻陷白宫网站,插五星红旗自从世界和互联网经济飞速发展起来以后,越来越多的人都投身于互联网建设当中。但是中国从前早互联网方面并不占据优势,因此信息化和数据化时代发展的也比较缓慢。但是在这些人当中,有一群侠义
用chatGPT写了一个php无限栏目分类的实例今天测试一个用chatGPT写一个php的无限栏目分类的程序,写得好快,还有测试的结果全部的都写出来了,虽然不能满足某些需求,但可以提供一定的思路,真的很厉害,不得不说人类的人工智
国补一取消后,新势力们就集体下跌,新能源繁荣都是假象?近几年来,中国品牌可以说是强势崛起了,凭借着实用性性价比等因素,在市场各系品牌中市占率中连续第一。而随着新能源汽车市场的爆红,造车新势力们也混得顺风顺水,2022年销量超10万辆的
性能远超chan的无锁队列作者leonzgshao,腾讯CSIG后台开发工程师导语结合Java语言的高可用无锁队列框架Disruptor实现的高性能无锁队列,可实现远高于chan的高性能数据传递,解决高并发
ChatGPT,机器意识觉醒最近大火的ChatGPT,宣传得会替代人类似的,其实不用太焦虑,无生命的AI,极限发展也就是低级的意识觉醒,这是物理结构决定的。而高级意识,除了智慧,还需要有生命。从网络上的报道,
深圳福田红树林入选国际重要湿地名录南方财经全媒体记者魏彤实习生周可莹傅杨清广州报道近日,中国18处湿地列入国际重要湿地名录。其中,广东省广州海珠国家湿地公园和深圳福田红树林湿地成功入选。据了解,广东省入选国际重要湿
乡土散文故乡的路其实世上本没有路,走的人多了,也便成了路!这是鲁迅先生对路最好的诠释。的确,故乡的路就是靠故乡人民用双脚走出来的。故乡的路以前叫乡间小路,山坡上稻田间菜畦边果树旁,到处密布着它的影
散文二月,人随春好,万事可期作者子墨春风十里,又是一年春来到,动静之间,春意轻染岁月的斑斓,一切便有了生机和力量。春天的阳光,丝丝缕缕,仿佛一些曼妙的音韵,跳跃之间,就唤醒了人间万物,又将人们的期待,洒满通往
5G是否必要,4G是否够用,简单分析一下1简单来说我们购买手机时选择5G款还是4G款这个很简单,买5G手机,但是,华为的绝大部分手机都是4G的,为什么还有那么多人选择,其实很好理解现在很多人买手机5G开关都不开,或者流量
测量长度的工具有哪些?这一个工具足以测量长度在日常生活中我们随时会需要测量物体长度,可能会是一些小物体,比如杯子的杯盖。又或者是一些大物体,比如一张桌子的高度,一台电视机的长度等等。当我们需要进行长度测量,身边却没有测量工具
鲸目VR赋能餐企,拉近餐厅与食客之间的距离随着社会的发展,人们生活水平显著提高,普通的温饱早已不能满足广大消费者的要求,外出就餐已成为人们必不可少的一项消遣,也是重要的社交活动。在这个越来越注重吃的年代,高档餐饮像雨后春笋