java 基于JDK中的源码总结下String二
申明:转载请注明出处,如有商用目的请务必知会本人,感谢。
上一篇文章:http://blog.csdn.net/ts1122/article/details/8738336,介绍了String一些易错内容。这里接着大体介绍下String类提供的API。大体就是不对API做一一介绍,只是根据类型说个大概,再选择一些经典的方法详细说明下。说明下,这两篇文章都是基于JDK1.7.0_17版本进行说明的,本文章后面的内容会说到JDK1.7版本String类的实现和JDK1.6版本还是很大不同的。
先说构造方法,String类里面构造方法很多。由于方法签名只与方法名称以及参数类型有关系,这么多构造方法的差异就只能是传递的参数类型和数目。不过有的构造方法基本不会被用到,比如下面两个:
- public String() {
- this.value = new char[0];
- }
- public String(String original) {
- this.value = original.value;
- this.hash = original.hash;
- }
第一个构造方法之所以不用,说明文档里面写的很清楚:由于String是不可变的,当前方法的基本没用。这个方法给出了一个指向空字符串的引用,之后指向的内容又不能改变,所以没有什么用处。Java里面有些类叫做不可变类,其定义为:类中的每个方法都不能改变其对象。一般这种类中的数据域都有加final修饰,String类就是一个不可变类,其数据域就加了final字符修饰。上面的第二个方法之所以不用是因为会多分配一块内存,JVM会在当前线程的stringpool中分配一块内存,之后在堆中再分配一块内存。构造一个String,我们一般只要用String = “abc”这种方式就足够了,而且简单高效,这种用法也是java推荐的。:-D
下面是一组和String类数据域有关的方法:
- public int length()
- public boolean isEmpty()
- public char charAt(int index)
- public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin)
这三个方法都是基于String的数据域char value[]实现的,比如返回value.length。这些方法经常有用到,得记住。最后一个方法是将String中数据域内容拷贝到char数组方法,用System.arraycopy的本地方法实现,效率应该很高。
接下来是一组String内容比较方法:
- public boolean equals(Object anObject)
- public boolean equalsIgnoreCase(String anotherString)
- public boolean contentEquals(CharSequence cs)
- public int compareTo(String anotherString)
第一个方法比较两个字符串对象内容是否完全相等,如果是就返回true。第二个方法从方法名称就可以理解,不考虑大小写进行比较。看了下第二个方法的内部实现,先把字符统一转成大写进行比较,如果不行再转成小写进行比较,看说明文档对于Georgian alphabet就有这种大写不成要用小写的特殊情况。:-( 第三个方法和前面两个方法基本一样,只不过参数类型不同。最后一个方法和C语言中的一样:取两个字符串较短的长度,从第一个字符开始对两个字符串进行比较,如果出现第一个不同的字符则返回两个字符之间的差值。结果返回是0的话就说明两个字符串内容相等。但是这个方法在java中很少用到。
一组新的字符串内容比较方法:
- public int indexOf(int ch)
- public int indexOf(int ch, int fromIndex)
- public int lastIndexOf(int ch)
- public boolean startsWith(String prefix)
- public boolean startsWith(String prefix, int toffset)
- public boolean endsWith(String suffix)
- public int indexOf(String str)
- public int indexOf(String str, int fromIndex)
- public int lastIndexOf(String str)
前面三个方法都是返回一个字符在当前字符串中的位置。后面一组方法是寻找一组字符串在当前字符串中的位置,和前面一组方法很相似。
一组易被忽视会产生新的字符串对象的方法:
- public String substring(int beginIndex)
- public String substring(int beginIndex, int endIndex)
- public String replace(char oldChar, char newChar)
- public String toLowerCase()
- public String toUpperCase()
- public String trim()
这些都是对当前字符串内容进行截取,替换,大小写变更等操作的方法。由于String类是不可变类,这些方法不能改变对象内容,只能新分配内存保存操作结果,如果滥用这些方法会造成内存泄露的。
这里根据public String substring(int beginIndex)说一下JDK1.6和JDK1.7String类的一些不同。JDK1.6上String类的数据域如下:
- /** The value is used for character storage. */
- private final char value[];
- /** The offset is the first index of the storage that is used. */
- private final int offset;
- /** The count is the number of characters in the String. */
- private final int count;
即其包含一个类似高中几何上向量的东西,给出内容同时还给出了一个起始点和长度的游标。JDK1.6中在实现substring最终会用到下面的方法:
- // Package private constructor which shares value array for speed.
- String(int offset, int count, char value[]) {
- this.value = value;
- this.offset = offset;
- this.count = count;
- }
这就是说截取一段某一个字符串中的一段,实际上并没有分配新的内存,只是提供了一个新的向量,返回的引用仍然指向原来的字符串。如果原来的字符串不再使用,仅使用新的截取的字符串,个人认为就造成内存浪费。如果每次都是从一个很长很长字符串中截取一小段内容,就造成了内存的极大浪费,这也是JDK1.6使用过程中,关于字符串的一个优化点。再看JDK1.7中String类就只有char value[]一个数据域,方法substring就采取了新的做法,如下:
- this.value = Arrays.copyOfRange(value, offset, offset+count);
这句代码完成这个方法实现主体,分配了新的内存,将需要的内容拷贝到新的内存中。看JDK文档中说明,1.6的这种做法是为了速度。:-D
接下来就是valueOf方法,都是像 public static String valueOf(Object obj) 这样的类方法,这些方法的实现其实就是参数本身的toString方法的实现。最后就是split方法,这个涉及到了正则表达式,这里暂不介绍。:-D
版权声明:本文为博主原创文章,未经博主允许不得转载。
java 基于JDK中的源码总结下String二的更多相关文章
- Java基础-集合框架-ArrayList源码分析
一.JDK中ArrayList是如何实现的 1.先看下ArrayList从上而下的层次图: 说明: 从图中可以看出,ArrayList只是最下层的实现类,集合的规则和扩展都是AbstractList. ...
- Java并发工具类CountDownLatch源码中的例子
Java并发工具类CountDownLatch源码中的例子 实例一 原文描述 /** * <p><b>Sample usage:</b> Here is a pai ...
- JDK源码阅读-------自学笔记(一)(java.lang.Object重写toString源码)
一.前景提要 Object类中定义有public String toString()方法,其返回值是 String 类型. 二.默认返回组成 类名+@+16进制的hashcode,当使用打印方法打印的 ...
- Java并发系列[5]----ReentrantLock源码分析
在Java5.0之前,协调对共享对象的访问可以使用的机制只有synchronized和volatile.我们知道synchronized关键字实现了内置锁,而volatile关键字保证了多线程的内存可 ...
- 观察者模式—jdk自带源码分析
一:观察者模式简介 二:jdk实现观察者模式的源码 三:实际例子 四:观察者模式的优点和不足 五:总结 一:观察者模式简介 有时又被称为发布(publish )-订阅(Subscribe)模式.模型- ...
- java集合系列之ArrayList源码分析
java集合系列之ArrayList源码分析(基于jdk1.8) ArrayList简介 ArrayList时List接口的一个非常重要的实现子类,它的底层是通过动态数组实现的,因此它具备查询速度快, ...
- JDK容器类Map源码解读
java.util.Map接口是JDK1.2开始提供的一个基于键值对的散列表接口,其设计的初衷是为了替换JDK1.0中的java.util.Dictionary抽象类.Dictionary是JDK最初 ...
- 基于Eclipse搭建Hadoop源码环境
Hadoop使用ant+ivy组织工程,无法直接导入Eclipse中.本文将介绍如何基于Eclipse搭建Hadoop源码环境. 准备工作 本文使用的操作系统为CentOS.需要的软件版本:hadoo ...
- Java集合系列[4]----LinkedHashMap源码分析
这篇文章我们开始分析LinkedHashMap的源码,LinkedHashMap继承了HashMap,也就是说LinkedHashMap是在HashMap的基础上扩展而来的,因此在看LinkedHas ...
随机推荐
- Java集合中对象排序
集合中的对象排序需求还是比較常见的.当然我们能够重写equals方法,循环比較:同一时候Java为我们提供了更易使用的APIs.当须要排序的集合或数组不是单纯的数字型时,通常能够使用Comparato ...
- 循环调用修正sic86
create or replace procedure rebuild_sic86_wyl(pi_aac001 in number, po_fhz out varchar2, po_msg out v ...
- CodeForces 385C Bear and Prime Numbers 素数打表
第一眼看这道题目的时候觉得可能会很难也看不太懂,但是看了给出的Hint之后思路就十分清晰了 Consider the first sample. Overall, the first sample h ...
- Week5(10月10日):国庆之后,让我们整装期待元旦吧
Part I:提问 =========================== 1.要将“Hello, Admin",从控制器传递到视图,该如何操作? (1)使用ViewData (2)使用V ...
- QT5.6 编译SQLServer驱动
简要说下编译的主要步骤 @1:打开vs2015的命令行编译环境 ‘ @2:进入到cd到源码目录:cd C:\Qt\Qt5.6.0\5.6\Src\qtbase\src\plugins\sqldrive ...
- 错误解决--oracle中出现ORA-01791: 不是 SELECTed 表达式 错误
Oracle数据库,执行下面语句出现错误“ORA-01791: 不是 SELECTed 表达式”: select distinct t.name from auth_employee t order ...
- java的new BufferedReader(new InputStreamReader(System.in))
流 JAVA /IO 基本小结 通过一行常见的代码讨论:new BufferedReader(new InputStreamReader(System.in)) /*** *** 看到这篇文章挺好的, ...
- BNU 26579 Andrew the Ant 【蚂蚁】
链接: http://www.bnuoj.com/bnuoj/problem_show.php?pid=26579 http://www.bnuoj.com/bnuoj/contest_show.ph ...
- 动态规划——最长公共子序列(LCS)
/** * @brief longest common subsequence(LCS) * @author An * @data 2013.8.26 **/ #include <iostrea ...
- cocos2dx 3.0 飞机大战
因为课程须要.然后又水平有限.所以写了个飞机大战.加上不会画画.所以图片资源也是从微信apk解压出来的,设计思路參考的偶尔e网事. 闲话不说.先讲一下设计.大体上一共分为3个场景.场景以下是Layer ...