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 ...
随机推荐
- Flow Problem(最大流)
Flow Problem Time Limit: 5000/5000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Tot ...
- sqlite3 脚本的使用
本来想找个专门查看数据库的工具的,后来发现脚本也非常easy,就直接用脚本了. sqlite3的脚本能够方便的查看当前数据库里的内容,使用起来事实上非常easy,这一列举一些最简单的使用方法,以后假设 ...
- VIM: 解决vi/vim中粘贴时行首出现很多缩进和空格的问题
解决vi/vim中粘贴时行首出现很多缩进和空格的问题 http://www.jbxue.com/LINUXjishu/12232.html 由于在secureCRT中会将原来的文本原封不动的按照字符串 ...
- [Swust OJ 1126]--神奇的矩阵(BFS,预处理,打表)
题目链接:http://acm.swust.edu.cn/problem/1126/ Time limit(ms): 1000 Memory limit(kb): 65535 上一周里,患有XX症的哈 ...
- centos 安装lua
yum install readline-develwget http://www.lua.org/ftp/lua-5.1.4.tar.gztar -xzvf lua-5.1.4.tar.gz3.编译 ...
- [转]CentO下限制SSH登录次数
应公司内部网站等级测评的需求,正逐渐加强系统安全防护. 设备默认 3 次验证失败自动退出,并且结束会话:网络登录连接超时自动退出时间 5 分钟: 第一种方法:已验证. 1.ssh超时时间设置 # cd ...
- Codeforces 490B Queue【模拟】
题意还是很好理解的,根据题目给出描述条件然后求出这串QUEUE 我的做法就是用两个数组 before[] 和 after[] 表示 ai 前面的前面的人的学号 和 ai 后面的后面的人的学号 ex[] ...
- (Problem 5)Smallest multiple
2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any rema ...
- C++中的智能指针(auto_ptr)
实际上auto_ptr 仅仅是C++标准库提供的一个类模板,它与传统的new/delete控制内存相比有一定优势.使用它不必每次都手动调用delete去释放内存.当然有利也有弊,也不是全然完美的. 本 ...
- struts2_4_为Action属性注入值
Struts2为Action中的属性提供了依赖注入功能,在struts2的配置文件里,能够为Action中的属性注入值,属性必须提供setter方法. 1)employeeAction类: publi ...