Java中String那些不为人知的事情

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学习笔记将递送更加有灵魂的博文,欢迎关注!一起从小白变大白,哈哈哈~~~~~

                                                                                         谢谢阅读                ----知飞翀

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值