【系列】重新认识Java——字符串(String)

本文深入探讨Java中的String类,包括其初始化方法(字面量法和构造方法法)、与JVM常量池的关系、不可变性原理以及与StringBuffer、StringBuilder的区别。此外,还讨论了"+"操作符的使用和编译时优化策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对于任何编程语言来说,接触字符串都是不可避免,Java也不例外。Java中String类位于java.lang包下,是整个Java语言的基石。同时String类使用final关键词修饰,意味着外部调用者无法通过继承和重写来更改其功能。Java中的字符串与语言相比,也有其特殊性。本文深入地理解Java字符串,主要内容有:

  1. String的初始化
  2. String与常量池
  3. String的不变性
  4. String、StringBuffer与StringBuilder
  5. “+”操作符

String初始化

首先要强调的是,String并不是Java中的基础类型,它也是一个对象。在源代码层面来说,String有多种不同的初始化方法,本节就介绍这些初始化方法。

字面量法

String的字面量初始化法如下所示:

String a = "abc";
String b = "hello world";

这种方法首先从常量池中查找是否有相同值的字符串对象,如果有,则直接将对象地址赋予引用变量;如果没有,在首先在常量池区域中创建一个新的字符串对象,然后将地址赋予引用变量。

构造方法法

String的构造方法初始化法如下所示:

String a = new String("abc");
String b = new String("hello world");

String类的构造方法有:

public String() {} // 构造空串(注意与null的区别)
public String(String original) {} // 基于另外一个字符串构造一个新字符串对象
public String(char value[]) {} // 使用byte数组构造字符串
public String(char value[], int offset, int count){} // 使用byte数组以及偏移参数构造
public String(int[] codePoints, int offset, int count) {} // 基于Uncode编码数组以及偏移量构造

这种初始化方法与一般对象的初始化方法完全一样。与字面量法不同的是,每次调用构造方法都会在堆内存中创建一个新的字符串对象。下面的例子可以清楚地显示它们的区别:

/*
 * 个人主页:http://hinylover.space
 *
 * Creation Date: 2016年7月6日 下午9:14:56
 */
package demo.blog.java.string;

/**
 * 不同初始化方法的区别。
 * @author xialei
 * @version 1.0 2016年7月6日下午9:14:56
 */
public class StringEqual {
   
   

    public static void main(String[] args) {
        String a1 = "123";
        String b1 = "123";
        System.out.println(a1 == b1); // true

        String a2 = new String("123");
        String b2 = new String("123");
        System.out.println(a2 == b2); // false
    }
}

我们知道,Java中的“==”符比较的变量保存的实际内存数据,由于基础数据类型变量保存的是数据的实际值,而引用类型变量保存的是对象的地址,不同的地址代表着不同的对象。a1 == b1true表明a1和b1指向同一个对象,而a2和b2分别指向不同的对象。

String与JVM常量池

说起String ,就不能不提到JVM常量池,是笔试和面试中经常喜欢出题的点。

常量池

在正式进入常量池之前,首先简单地介绍一下JVM(Java虚拟机,由于市面上有多种不同的JVM,本文中仅考虑Hotspot VM)的内存结构,也是作为Java程序员必须要了解的内容(以后再深入JVM)。由于本文的主体并不是Java虚拟机,内容会比较粗糙,更加详细的JVM知识会在以后撰写。

JVM的内存顶层结构如下图所示:

JVM内存结构

下面分别来说说主要的内存区域:

  1. 程序计数器:这是一块比较小的内存区域,可以看做是当前线程所执行的字节码的行号指示器。每一个线程都会需要有一个独立的程序计数器,各个程序计数器之间相互不影响。如果线程当前执行的是Java方
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值