做者:泥沙砖瓦浆木匠 网站:http://blog.csdn.net/jeffli1993 我的签名:打算起手不凡写出鸿篇巨做的人,每每坚持不了完成第一章节。 |
提及String,你们最熟悉不过了。我也是那么说过,可是仿佛这熟悉的里面也有不少细节,或者是咱们没掌握的东西。每每有不少旧东西里面爆出不少光点。好比,做者泥瓦匠近期在冬天的牛仔裤里面搜出了一张100现金(不宜乐乎)。回到正题,咱们下面如下几点讲下String。分两个部分:
基础部分:(JDK源码 文档) 算法
扩展部分: api
楼主不是大牛级别的人物,泥瓦匠一直认为的是“打算起手不凡写出鸿篇巨做的人,每每坚持不了完成第一章节。”因此,操着键盘,听着喜欢的音乐。幽默的对你说个人理解体会。
(但愿大牛指出错误,万分感谢!) 数组
怀着初次见你的心情,泥瓦匠和你一块儿打开JDK1.7文档。我最近想写一些关于JDK1.7的理解,都知道JDK8出来了,新特性我准备下阶段有空学习。
泥瓦匠想说,阅读E文文档有利于体会原汁原味。但毕竟国内大牛翻译的很不错了,我们不加评判,喜欢哪一种本身挑。能抓老鼠,能解决实际项目,适应业务环境的就是你学到了。请看下面的小例子: 网络
清单1.1 app
String abc = "abc"; char data[] = {'a','b','c'}; String abcStr = new String(data); System.out.println("abc"); String cde = "cde"; System.out.println("abc" + cde); String c = "abc".substring(2,3); String d = cde.substring(1, 2); System.out.println(c); System.out.println(d);
泥瓦匠,你不是在忽悠我吗?这么简单的程序,你想说什么。说实在确实是基础,但基础扎实才能有更高的突破。就想泥瓦匠默默为本身,为家人为将来打基础。 框架
能够见,String是不须要用new来建立一个新对象的类。它是不可变的(Constant),其值(像"abc"建立后,不可改变)。天然,String其实实现了基本类型char的序列的功能,所以中文名“字符串”。这里你们有可能疑惑,泥瓦匠就找到JDK源码证据给大家看: ide
这段代码是来自JDK1.7源码里面的,char型value数组的形式组成了String类的内容。其操做就是针对value数组操做。这样想是否豁然开朗,而后内心自喜“so easy”。其实难点下面,你们慢慢看下去。 函数
依旧看代码清单1.1,Java提供了一个特殊的链接操做符(concatenation operator)+ 用于直接来拼接字符串。其中操做经常使用的方法罗列以下: 学习
方法 做用
s.length() 返回s字符串长度 s.charAt(1) 返回s字符串中下标为1的字符 s.substring(0, 2) 返回s字符串中下标0到2的子字符串 s.indexOf("nsg") 返回子字符串"nsg"的下标 s.startsWith(" ") 判断s是否以空格开始 s.endsWith("end") 判断s是否以"end"结束
跟着泥瓦匠运行下清单1.1,你能够看到打印出来: 优化
abc abccde c d
有人看到这个会大吃一惊,而后质问说“老师说,String 和 == 不要紧,你是否是瞎扯淡”。哈哈,我只能说,只不过修行在实际。举个小栗子吧。
看下面清单1.2
static String b = "ab"; private static void test(){ String a = "a" + "b"; System.out.println(a == b); }
看到这里,你是否以为这么简单,内心想着确定是“false,泥瓦匠真逗。”运行下,结果倒是
true
泥瓦匠的记忆宫殿:就是至关于 泥瓦匠和个人亲姐姐比较咱们两个的爸爸,毕竟的爸爸都是那一个,固然是true。
"a" + "b"的生命是怎么样的呢?网络牛人有些反编译会发现实际上是相似下面的过程:
StringBuilder temp = new StringBuilder(); temp.append("a").append("b"); return temp.toString();
究竟JVM是怎么把"a" + "b"和"ab"知道他们是同样的呢。咱们回顾下,由于String是不可变类,也就是静态Java语言的特色。这涉及到JVM的优化方案。但JVM很死板,它不会很人工智能的像人脑,它会的只是它能处理的,因此好好了解JVM有助于开发更好的额程序。好比定义一个ab字符串常量够了,它不会在再 子串 a b。这就是它的优化方案。
泥瓦匠的记忆宫殿:这就是偷懒思想,今天我要见我爸爸,明天姐姐要见爸爸。合并下呗,后天一块儿去见爸爸。
就此咱们能够得出结论:编译器给我带来它对程序的优化,为了提高程序的效率和内存资源等,因此咱们能够明白,如何掌握其特性写出更好的代码。
补充个例子,看看大家真的掌握没?
private static String getA(){ return "a";} private static void test2(){ String a = "a"; String b = a + "b"; String e = getA() + "b"; System.out.println(b == "ab"); System.out.println(e == "ab"); }
false false
若是猜到了,证实你真懂了。泥瓦匠仍是耐心的讲解下:
第一个false:b是包括了一个常量和一个引用的值,因此。
第二个false: 你也能够猜到外部方法的常量在本方法只是一个引用。因此。
结论以下:咱们如今若是不知道JVM怎么在编译时期优化,咱们就慢慢了解它们。
这个例子很差写,泥瓦匠就带大家看看源码等。equals并不陌生,相信你们的系统里面有不少设计到这个方法。
其实equals是实现了Object的equals方法,而在Object的equals:
它其实就是实现了 == 比较内存的内容。
Q:泥瓦匠,为何String要重写Object,这不致使意义不一致了吗?
A:非也非也,String是String,String用来处理的事物逻辑和业务和Object彻底不一样。equals顾名思义等于,等于不表示彻底相等。而是同样或者类似。正所谓业务看状况,好比泥瓦匠处理得金融数据通常小数点10几位,那请问你还会在意小数点10位后的的值吗,当它们比较的时候,你不会在意,因此这就是类似。
简单描述下,就是遍历两个数组最好的条件下,就是要么长度不一样,要么前面几个不一样。直接返回false。
Q:若是碰到大字符串这就悲剧了。因此一些大字符串怎么处理呢。
A:其实实际中,大字符串也难见。但说处理的话,大字符串匹配能够考虑分割匹配或是啥的这里就不展开了。
Q:equals重写 和 hashCode 有关系吗?
A:这里咱们要先说明hashCode方法提供对象的hashCode值,返回与默认的System.identityHashCode()一致。其普遍用于集合框架。到后面我也会讲到。hashCode的源于计算机的比较源于数字,而不是对象。因此一个hashCode值标识一个对象,产生了对象相关的不少算法。可是默认的hashCode犯法会发起对本地的调用开销很大。
intern你们就有点陌生了。我们首先得普及下常量池的概念,常量池(constant pool)指的是在编译期被肯定,并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量。而后看看下面的例子:
private static void test5(){ String a = "a"; String b = a + "b"; String c = "ab"; String d = new String("ab"); System.out.println(c == d.intern()); System.out.println(b.intern() == d.intern()); }
当调用 intern()方法时,JVM 会在这个常量池中经过 equals()方法查找是否存在等值的 String,若是存在,则直接返回常量池中这个 String 对象的地址;没有找到,则会建立等值的字符串,返回其地址。
思考提高:这有什么用呢?
答曰:能够用于一些常量的存储比较,枚举(枚举底层就是字符串,哈哈)。当想常量比常量,多数的状况下,考虑效率则选择 intern()而不是equals。
String是Java基础组件重要的一部分。我慢慢的总结的J2EE Java的组件体系,而后增长内容进去。仍是那句话,泥瓦匠想说:
如以上文章或连接对你有帮助的话,别忘了在文章按钮或到页面右下角点击 “赞一个” 按钮哦。你也能够点击页面右边“分享”悬浮按钮哦,让更多的人阅读这篇文章