字符串是任何编程语言都必须支持的变量类型,有些编程语言是直接提供了原生的变量类型,有些编程语言则使用语法特性以 SDK 的形式提供支持。在Java编程平台中,对字符串的支持使用了后者的形式,就是通过在 JDK中提供一个名为String的类,对应字符串这个变量类型。

源码分析

既然JDK中的String类对应了字符串变量类型,为了熟练地掌握Java中字符串相关的技能,我们必须深入地分析和研究一下这个类。编码界有一句名言叫做 “源码面前,了无秘密”,因此,我们第一步就是来看看String类的源码概括。重点部分摘录如下:

public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
        /** The value is used for character storage. */
        private final char value[];
        /** Cache the hash code for the string */
       private int hash; // Default to 0
}

我们得出的几个重点是:

  1. String类的底层使用 char 的数组保存数据。
  2. String类是一个 final 类,不允许被继承。
  3. String类是一个 immutable 类,该类的对象生成后,内容不会发生变化。该类中的所有返回String类型对象的成员方法都是返回一个新的String对象

JVM内存模型

Java作为一门半编译半解释或者即编译又解释的编程语言,Java源码文件需要先被编译器编译成 ByteCode(字节码) 文件,然后在 JVM(Java虚拟机) 上解释执行。为了理解和掌握String类的特性,必须清楚地知道JVM的内存模型。对于字符串类型,也就是String类,JVM从编译源码到执行字节码的整个过程中,都做了特定的调整与优化,正是这些调整与优化造成了String类与对象的一些诡异特性。

关于JVM内存模型的分析与理解,可以参看我的另一篇文件或者通过其他的书籍与资料学习。与本文内容紧密相关的两个知识点总结如下:

  1. JVM的内存模型中有一块区域名为 方法区, 用于存储加载的类信息、方法体和各种符号表。
  2. 方法区中有一块区域名为 常量区, 用于存储编译时和运行时的字符串常量。

方法剖析

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与==

  1. 对于 ==,如果作用与基本数据类型(byte、short、char、int、long、float、double、boolean)的变量,则比较的是其存储的“值”是否相等;如果作用与引用类型的变量,则比较其所指向的对象的地址是否相同(即是否同一个对象)。在Java中,String是引用类型。
  2. 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”);

String strC = new String(“www.tiantianbianma.com”);
System.out.println(strA.equals(strB));
 System.out.println(strA == strB);
System.out.println(strA.equals(strC));
System.out.println(strA == strC);
System.out.println(strB.equal(strC));
System.out.println(strB == strC);

建议思考得出答案后,再上机验证结果。正确的答案是 true、false、true、false、true、false。他们在JVM中的内存布局简图如下:

对照此图,答案就很清楚了。

编译优化

直接来看代码片段二:

final String str = “ma.com”;

String strA = “www.tiantianbianma.com”;
String strB = “wwww.tiantian” + “bianma.com”;
String strC = “www.tiantianbian” + str;
System.out.println(strA.equals(strB));
System.out.println(strA == strB);
System.out.println(strA.equals(strC));
System.out.println(strA == strC);

建议思考得出答案后,再上机验证结果。正确的答案是 true、true、true、true,希望没有出乎你的意料。背后的逻辑是Java编译器在编译源码时,对于编译时就可以确定的字符常量,包括字符序列和final字符变量,会自动进行拼接优化。

intern方法

String类中最诡异的一个方法就是 intern,还是先来看代码片段三:

String strA = “www.tiantianbianma.com”;
String strB = new String(“www.tiantianbianma.com”);
System.out.println(strA.intern().equals(strB.intern()));
System.out.println(strA.intern() == strB.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类的方法与特点的更多相关文章

  1. Java中String类的方法及说明

    String : 字符串类型 一.      String sc_sub = new String(c,3,2);    //      String sb_copy = new String(sb) ...

  2. 【转载】Java中String类的方法及说明

    转载自:http://www.cnblogs.com/YSO1983/archive/2009/12/07/1618564.html String : 字符串类型 一.      String sc_ ...

  3. 『Java』String类使用方法

    Java中的字符串 java.lang.String类表示字符串类,Java程序中所有字符串文字都可以看作实现该类的实例. 特点: 字符串不可变:字符串的值在创建后不能在发生改变 public cla ...

  4. JAVA中String类的方法(函数)总结--JAVA基础

    1.concat()方法,当参数为两字符串时,可实现字符串的连接: package cn.nxl123.www; public class Test { public static void main ...

  5. java.lang.String 类的所有方法

    java.lang.String 类的所有方法 方法摘要 char charAt(int index) 返回指定索引处的 char 值. int codePointAt(int index) 返回指定 ...

  6. 《java入门第一季》之类(String类常见方法小叙)

    String类下面的构造方法和一些常见的方法: /* * 字符串:就是由多个字符组成的一串数据.也可以看成是一个字符数组. * 通过查看API,可以知道 * A:字符串字面值"abc&quo ...

  7. paip。java 高级特性 类默认方法,匿名方法+多方法连续调用, 常量类型

    paip.java 高级特性 类默认方法,匿名方法+多方法连续调用, 常量类型 作者Attilax 艾龙,  EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http ...

  8. java中String类学习

    java中String类的相关操作如下: (1)初始化:例如,String s = “abc”; (2)length:返回字符串的长度. (3)charAT:字符操作,按照索引值获得字符串中的指定字符 ...

  9. java 中String类的常用方法总结,带你玩转String类。

    String类: String类在java.lang包中,java使用String类创建一个字符串变量,字符串变量属于对象.String类对象创建后不能修改,StringBuffer & St ...

随机推荐

  1. Linux(ubuntu)安装MediaWiki

    本篇文档所述步骤,作者完全验证过.一切OK. 作者:http://gaoxingf.blog.51cto.com/612518/188132,Younger Liu 本作品采用知识共享署名-非商业性使 ...

  2. js鼠标移入移出事件会被子元素触发解决方法

    问题:js写了一个鼠标移入移出事件,但是发现会被内部子元素不断的触发 解决方法:建立一个空的div定位到需要触发的位置,然后设置大小和触发范围一样,最后将事件写在空的div上.

  3. MongoDB3.4 shell CRUD操作

    输入db,显示你正在操作的数据库:切换数据库,输入use dbName,如果数据库不存在的话会自动帮我们创建一个:使用show dbs可以显示所有可用的数据库. 测试数据在文末 插入文档 插入操作的行 ...

  4. 一个大数据平台省了20个IT人力——敦奴数据平台建设案例分享

    认识敦奴 敦奴集团创立于1987年,主营服装.酒店.地产,总部位于中国皮都-海宁.浙江敦奴联合实业股份有限公司(以下简称"敦奴")是一家集开发.设计.生产.销售于一体的大型专业服装 ...

  5. LeetCode 题解(一):Two Sum

    LeetCode : two sum 第一次写博客,算是熟悉这些编辑环境吧,本来是打算在csdn上用markdown写的,结果改了博客介绍就被关闭了,晕死...好了,话不多说,今天打算拿LeetCod ...

  6. OC—Setter、Getter

    一.本篇以Setter和Getter 来进行成员变量的赋值. 二.Setter 与 Getter 1. 命名规范 为对象中的某个实例变量赋值的方法称为修改方法,用来修改对象的状态这类修改方法称为set ...

  7. hdu1011 Starship Troopers 树形DP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1011 思路:很明显的树形背包 定义dp[root][m]表示以root为根,派m个士兵的最优解,那么d ...

  8. [刷题]算法竞赛入门经典(第2版) 5-10/UVa1597 - Searching the Web

    题意:不难理解,照搬题意的解法. 代码:(Accepted,0.190s) //UVa1597 - Searching the Web //#define _XIENAOBAN_ #include&l ...

  9. 【企业级框架整合】Springmvc+mybatis+restful+bootstrap框架整合

    1. 使用阿里巴巴Druid连接池(高效.功能强大.可扩展性好的数据库连接池.监控数据库访问性能.支持Common-Logging.Log4j和JdkLog,监控数据库访问)2. 提供高并发JMS消息 ...

  10. 在Adapter中如何关闭当前Activity

    很多时候我们需要在点击adapter条目的时候关闭当前界面,把所点击条目的信息带到前一个界面,同时关闭当前界面. 这个 时候就需要在adapter对某一个点击事件做处理. 代码如下: holder.l ...