首页 > 代码库 > 深入分析Java的String类的方法与特点
深入分析Java的String类的方法与特点
字符串是任何编程语言都必须支持的变量类型,有些编程语言是直接提供了原生的变量类型,有些编程语言则使用语法特性以 SDK 的形式提供支持。在Java编程平台中,对字符串的支持使用了后者的形式,就是通过在 JDK中提供一个名为String的类,对应字符串这个变量类型。
源码分析
既然JDK中的String类对应了字符串变量类型,为了熟练地掌握Java中字符串相关的技能,我们必须深入地分析和研究一下这个类。编码界有一句名言叫做 “源码面前,了无秘密”,因此,我们第一步就是来看看String类的源码概括。重点部分摘录如下:
我们得出的几个重点是:
- String类的底层使用 char 的数组保存数据。
- String类是一个 final 类,不允许被继承。
- String类是一个 immutable 类,该类的对象生成后,内容不会发生变化。该类中的所有返回String类型对象的成员方法都是返回一个新的String对象。
JVM内存模型
Java作为一门半编译半解释或者即编译又解释的编程语言,Java源码文件需要先被编译器编译成 ByteCode(字节码) 文件,然后在 JVM(Java虚拟机) 上解释执行。为了理解和掌握String类的特性,必须清楚地知道JVM的内存模型。对于字符串类型,也就是String类,JVM从编译源码到执行字节码的整个过程中,都做了特定的调整与优化,正是这些调整与优化造成了String类与对象的一些诡异特性。
关于JVM内存模型的分析与理解,可以参看我的另一篇文件或者通过其他的书籍与资料学习。与本文内容紧密相关的两个知识点总结如下:
- JVM的内存模型中有一块区域名为 方法区, 用于存储加载的类信息、方法体和各种符号表。
- 方法区中有一块区域名为 常量区, 用于存储编译时和运行时的字符串常量。
方法剖析
String类作为对应字符串的类,该类中含有大量的方法用来完成字符串相关的构造、裁剪、拼接与替换等功能。具体而言,在 JDK8 时,该类中已经有多于80个方法,好在其中有大部分都是重载方法。我们应该按照他们的功能把他们分类如下:
方法名 | 功能 | 方法名 | 功能 |
---|---|---|---|
String | 构造 | codePoint* | 取值 |
length | 长度 | getChars | 取值 |
isEmpty | 判空 | getBytes | 取值 |
charAt | 取值 | *equals* | 判等 |
compareTo* | 比较 | regionMatches | 正则 |
startWith | 判断 | *indexOf | 取值 |
substring | 截取 | concat | 拼接 |
replace* | 替换 | matches | 正则 |
contains | 包含 | split | 分割 |
join | 拼接 | to* | 转换 |
trim | 去空格 | format | 格式化 |
*valueOf | 转换 | intern | 获取 |
特性剖析
由于字符串类型的特殊性和频繁性,出于功能和效率的考虑,Java在处理字符串类型时,提供了几个重要的特性。
equals与==
- 对于 ==,如果作用与基本数据类型(byte、short、char、int、long、float、double、boolean)的变量,则比较的是其存储的“值”是否相等;如果作用与引用类型的变量,则比较其所指向的对象的地址是否相同(即是否同一个对象)。在Java中,String是引用类型。
- String的 equals 方法继承自Java中的超级父类Object,Object的equals方法用来比较两个对象的引用是否相等(即是否同一个对象)。但是,String的equals方法不仅是简单地继承,而是进行了重写(Override),用来比较两个String对象所存储的字符序列值是否相等。
创建方式
对于Java中的类而言,创建对象的方式一般有 5种。它们分别是 new 关键字、Class类的 newInstance 方法、Constructor类的 newInstance 方法、String对象的 clone方法、反序列化机制。但是String对象还有一种特殊的创建方式,就是通过使用 “ 或 ’ 包裹字符序列。现在,我们重点关注一下 new关键字 与 字符序列 这两种创建String对象的方式的异同。
我们直接以代码实例的方式来学习两种方式的优缺点。首先看代码片段一:
String strA = “www.tiantianbianma.com”;
String strB = new String(“www.tiantianbianma.com”);
建议思考得出答案后,再上机验证结果。正确的答案是 true、false、true、false、true、false。他们在JVM中的内存布局简图如下:
对照此图,答案就很清楚了。
编译优化
直接来看代码片段二:
final String str = “ma.com”;
建议思考得出答案后,再上机验证结果。正确的答案是 true、true、true、true,希望没有出乎你的意料。背后的逻辑是Java编译器在编译源码时,对于编译时就可以确定的字符常量,包括字符序列和final字符变量,会自动进行拼接优化。
intern方法
String类中最诡异的一个方法就是 intern,还是先来看代码片段三:
建议思考得出答案后,再上机验证结果。正确的答案是 true、true。背后的原理是:无论是字符串常量区中的String对象,还是堆内存中的String对象,它们的intern方法都是去JVM中的字符串常量区获取相等字符序列的String对象返回。上述代码片段的JVM内存布局简图如下:
对照此图,答案就很清楚了。
总结
本文通过从源码入手,再到方法和特性的分析,基本上覆盖了Java中String类的重点和难点。特别是其中的不可变特性与编译优化特性,更是在实际项目中和笔试面试题中经常遇到,还有就是intern方法的诡异性。当然了,String的这些特性也不是完美的,不可变特性在大量拼接字符串时就会带来性能的极大损耗,所以需要使用StringBuilder 类或者 StringBuffer 类来代替。另外,本文对于String类中的方法的具体功能与注意点都没有仔细分析,但需要读者熟练掌握,无论对于笔试面试还是实际工作都大有裨益。
声明: 本文转载自IT技术分析网站: 天天编程,转载自 http://www.tiantianbianma.com/deep-insight-java-string-class/
深入分析Java的String类的方法与特点