String类的解析

来源:互联网 发布:wamp怎么打开php 编辑:程序博客网 时间:2024/06/05 18:34

String 是java开发中最经常用到的类型之一,今天来整理一下String的内容。

从string的创建开始
String有两种创建方式:

String a = "mac";String b = new String("mac");

两种创建方式有本质上的不同,
本质上来说,两个方式创建的对象存储于JVM内存布局模型中的不同区域。

这里写图片描述

这两种创建方法

第一种字符序列方式创建对象的时候,会将数据存储在常量池中,之后再次创建字符串的时候jvm会先到常量池查看是否已经存在这个字符串,如果没有就创建。

第二种使用new运算符方式创建对象,JVM会直接在 堆 中分配一个新的String对象。

创建时内存分布图
ps:图片转自网络

从源码来理解String

public final class Stringimplements java.io.Serializable, Comparable, 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对象

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

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

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类的方法与特点

原创粉丝点击