Java中String的理解
Java中String的理解
最近在读String的源码,看了些String的⽂章,⾃⼰对String作了下总结记录下来。
1.String为什么是不可变的?
String是final类,不可继承,其⽅法也不可被覆盖,避免从⼦类操纵⽗类属性;String的值保存在private final char[]数组中,本质是⼀个字符数组,私有则外部不可访问和修
改,final引⽤则引⽤(或说引⽤的值)不变。引⽤可以简单地认为是堆上对象的⾸地址。String内部的private int hash,缓存hash值,hashCode和equals⽤来⽐较对象相等,缓
存hash可以减少运算时间提⾼效率。但是,String的值char[]可以通过反射改变。String不可变是出于安全和使⽤效率考虑的。
2.String的split,substring,replace,replaceAll等⽅法有哪些注意点?
java中split的用法charAt,toLowerCase,toUpperCase,trim,toCharArray等常⽤⽅法并没有太多注意点。
split(String regex,int limit):regex,切⽚的正则;limit,切⽚数。
split(String regex):regex,切⽚的正则。从这⾥可以看出切⽚是使⽤正则来切⽚的,⽽且要注意的是,尾部切⽚得到的空字符串""(注意没有空格)是不会出现的结果的字符串数组
中的。
思考:
String s=“,1,2,,3,,,”;
String[] arr=s.split(",");
arr的值是什么?
结果是{"",“1”,“2”,“”,“3”}。如果制定切⽚数limit则会按切⽚数切⽚。
substring(int beginIndex,int endInx):beginIndex是包含的,end不包含。
replace():有两个⽅法,接收char替换,接收字符序列(字符串)替换。
replaceAll(String regex,String replacement):⽤replacement替换所有的符合regex正则的⼦串。
3.String,StringBuilder,StringBuffer
对String的修改总是返回新的String,原String不变。
StringBuiler⾮线程安全,StringBuffer线程安全。StringBuffer认为线程安全是其⽅法使⽤synchronized同步,同时也会承担其带来的开销。
对⼤量修改字符串的操作推荐使⽤StringBuilder。
所有类都间接继承来⾃Object,所有对象实例都是Objcet的实例,如果不重写,则继承其toString(),hashCode(),equals()⽅法。打印⽇志,系统输出等带有“显⽰”含义的对实例
的表⽰都是调⽤其toString()⽅法。默认的toString⽅法时Class Name+"@"+⼗六进制的hashCode值。String的“+”可以看做所谓的运算符重载,但是Java没有运算符重载。String
的“+”,和数值的“+”有所不同,⼀般情况String的“+"就是join操作把字符或字符串拼接。
看下⾯例⼦:
System.out.println(s+5+6);
System.out.println(5+6+s);
System.out.println(5+s+6);
System.out.println(s+(5+6));```
思考输出结果。
<br>结果是:
<br>hello56
<br>11hello
<br>5hello6
<br>hello11
<br>应避免此类写法或者加上括号指定运算顺序。
##5.String在JVM的存储
<br>JVM在创建我们常见的字符串常量,⽐如String s=“abcd”,和字符串对象,⽐如String s=new String("abcd")时⾏为有所区别。
<br>字符串常量:⽐如String s="abcd",创建字符串常量时,JVM会⾸先检查字符串常量池,如果该字符串已经存在常量池中,那么就直接返回常量池中的实例引⽤。如果字符串不存在常量池中,就会实例化该字符串并且将其放到常量池中。常量池中<br>字符串对象:String s=new String(“abcd”);注意这⾥没有上⾯String s="abcd"的先决条件。在类加载时,常量池会创建“abcd”对象,指向代码时在堆上创建⼀个String对象,该String对象保存到常量池“abcd”对象的引⽤,s保存到堆上该String 创建字符串总是先去常量池是否已有当前字符串对象,没有才去堆上分配,在堆上新分配的也不会加到常量池
<br>思考:
```String s1="ABC";
String s2="ABC";
String s3=new String("ABC");
System.out.println(s1==s2);
System.out.println(s1==s3);```
<br>输出结果是什么?
<br>结果是:true
<br>false
<br>new String()总是会在堆上开辟新的内存,但该块内存存储的字符串信息会先去常量池查查,如果常量池有,则直接存下常量池的字符串的引⽤;如果没有则在堆上保存字符串信息。
如下图:
![](img2018blogs/blog/1476330/201903/1476330-20190313114258718-1875513481.jpg)
这⾥具体可以参考这篇⽂章:
[深⼊理解Java中的String](wwwblogs/xiaoxi/p/6036701.html)
##6.String,对象,集合的判空和判null
<br>对于某个对象判null,直接s==null即可。在⽇常学习⼯作中,很多情况都是对空字符串,空集合的判断。
<br>集合的判空不能⽤==null,应该⽤⼯具类,其内部实现⼀般是判null或元素数为0则为空集合。
<br>对于⼀个指定为String类型的引⽤s,如果判断空字符串?
<br>思考:
<br>String s=null;
<br>System.out.println(s);
<br>输出:null
<br>思考:
<br>System.out.println("".equals." ");
<br>输出:false
<br>对于字符串的判空还是要借助⼯具类才能保证全⾯性。思路是:判null,trim去除头尾空格再判空,⽽且对于“null”本⾝这个字符串应该视为<br>是空字符串,在某些序列化结果和数据库返回结果,null会被直接传送返回,应该剔除这种情况。在⽇
<br><br>对String的⼀些思考和理解暂时先写到这⾥,以后如果有新思考会更新到这篇。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论