Java中String你都晓得?
前言
有回到了最初的起点,呆呆的站在镜子前。。。。自知飞翀博客创建至今似乎写的第一篇就是跟String有关的知识,经过半年多的深入,我发现String也不平凡。今天God翀带你重拾最初的,那个被忽视的String。
String介绍
String的特点:String在java官方设计之初就是想让使用者如同使用int、float、double等基本数据类型一样非常轻松的上手,但是String又不平凡,从我个人的理解上认为String相当于一个对象,String之所以会被使用者用起来如同基本数据类型一样so cool,正是因为final的存在。?(如下图:选自java源码)从图中可以看出final修饰使String只能被赋值一次而无法更改。
问:你说错了吧!我们在实际使用中经常可以String s="abc"; s="12sc";
答:这是因为在String底层保证我们一旦要对String s进行修改就会新创建一个String并将值赋给内存然后由s引用,而原来的空间被废弃。
聪明的你一定发现了问题,正是因为我们不了解String的本质所以在实际的使用中可能会经常对String进行修改会产生大量的内存空间垃圾,所以记住哟!如果我们实际情况避免不了频繁的对String进行更改,这时我们会使用StringBuffer或StringBuilder来代替String。(StringBuffer与StringBuilder将在后续博文中介绍)
拓展知识(以下3点摘选自:CSDN博客:几钱清风)
直接使用 ” ” 声明的String对象会直接存储在常量池中,(可以实现共享)
1.String str1=”first”;
jvm在运行时先查找常量池中是否有该字符串,如果有则直接返回该字符串的引用给first(实现了字符串 的共享) ;否则先在常量
池中创建该字符串并返回引用,此时只会在常量池中创建String对象,不会在堆中创建。
2.String str2=new String(“second”);
该代码生成了两个String对象。因为使用了“”会现在常量池中查找是否存在second对象,没有则创建否则不创建;在常量池创建完成后,由于使用了new,jvm会在堆中创建内容相同的String对象,并将引用返回给str2.
3.String str3=”what”; String str4=str3+”a nice day”;
运行时,+ 相当于new,所以堆中会有“what a nice day”对象;常量池中会有”what” “a nice day”两个对象,而不会有”what a nice day”对象。
String面试家常
由于String类型的特殊性,在面试场合自然也就少不了。下面我将通过几道题目带领大家一起深入String。
问题一:判断定义为String类型的s1和s2是否相等
String s1 = "abc";
String s2 = "abc";
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
答案:true true (s1==s2比较的是被应用对象的地址是否相同;s1.equals(s2)比较的是实际s1与s2的值是否相同)
分析:当String以直接赋常量的形式创建的时候,会在JVM方法区中的常量池中寻找此常量("abc")是否存在,如果存在直接将"abc"的地址赋给String变量。详情见下图:当main主方法进入栈中后首先读到String s1,然后进入常量池中寻找是否已经存在"abc"即进行下图文字内容;之后String s2被读取后首先在常量池中寻找"abc"的踪影,发现存在即将地址赋给s2;最终s1与s2指向同一个地址。
问题二: 下面这句话在内存中创建了几个对象?
String s1 = new String("abc");
答案:2个
分析:当String以创建地址的方式赋值(new String() )时,也是先在常量池中查找是否存在此字符串("abc"),如果不存在创建之;然后再将此字符串对象拷贝到堆中形成一个值为abc的对象,将此对象的地址赋给String变量。图示如下:可见共创建2个对象。
依据:new String("abc");创建两个对象的依据如下图(摘选自Java SE8官方帮助文档):大致意思是以public String(String original)创建String的时候会生成参数original的副本。
问题三:判断定义为String类型的s1和s2是否相等
String s1 = new String("abc");
String s2 = "abc";
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
答案:false true
分析:结合前面题目一与题目二的知识,较容易判断出s1与s2的地址不同,值相同。
问题四:判断定义为String类型的s1和s2是否相等
String s1 = "a" + "b" + "c";
String s2 = "abc";
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
答案:true true
分析:这里存在常量优化机制,即在编译阶段会将常量"a"+"b"+"c"连接起来,实际上就是String s1="abc"; String s2="abc";所以s1与s2的地址相同,值也相同。
问题五:判断定义为String类型的s1和s2是否相等
String s1 = "ab";
String s2 = "abc";
String s3 = s1 + "c";
System.out.println(s3 == s2);
System.out.println(s3.equals(s2));
答案:false true
分析:这里与第四题不同的是+连接时出现变量s1,也就不能使用常量优化机制。就会将s1转为StringBuffer或StringBuilder,然后通过append方法将"c"加入进来,之后调用toString转换成String,最后将这个String的地址赋给变量s3.图示如下:
依据:如下图(摘自Java SE8帮助文档):文档介绍java中采用+操作符将字符串与对象连接时,通过StringBuilder或StringBuffer实现的。
JavaSE学习笔记将递送更加有灵魂的博文,欢迎关注!一起从小白变大白,哈哈哈~~~~~
谢谢阅读 ----知飞翀