Java中String字符串常量池和intern方法源码分析

Java中String字符串常量池和intern方法源码分析

什么是字符串常量池

在Java中,字符串是不可变的,也就是说,对一个字符串的任何操作都将返回一个新的字符串对象,而原来的字符串对象不会被修改。

为了提高String对象的创建和删除效率,Java引入了字符串常量池(String Pool),该池用来缓存字符串对象,可以减少新的String对象的创建数量以及对Java虚拟机内存的占用。

在Java中,运行时常量池是方法区(Method Area)的一部分,在类加载时被初始化,存储编译期生成的各种字面量和符号引用。

String类中intern方法

String类中有一个intern()方法,该方法是一个native方法,用于把String对象添加到字符串常量池中,如果字符串常量池中已经存在了该字符串,则返回常量池中的字符串对象,否则将该对象添加到字符串常量池中,并返回该对象的引用。

例如,假设现有一个字符串池:["abc", "def"],现在需要对字符串"abc"进行intern()操作,操作后返回的引用将是"abc"的地址,同时字符串池中的元素不变,仍然是["abc", "def"]。

intern方法源码分析

Java中String类的intern()方法的源码:

public native String intern();

从源码可以看出,String的intern()方法是一个native方法,也就是说该方法在Java程序之外的C++代码中被实现。在OpenJDK中,这个方法的本地实现大致如下:

static jstring string_pool::intern(Handle string_or_null, TRAPS) {
    if (string_or_null() == NULL) {
        // 如果字符串为null则返回null
        return (jstring)string_or_null();
    }

    // 搜索常量池
    StringTable* const pool = JvmtiExport::string_table();
    Symbol* sym = NULL;
    {
        SharedStrings::LockGuard guard(pool->lock, true);
        sym = pool->lookup_stage2(string_or_null, CHECK_NULL);
    }

    if (sym != NULL) {
        // 字符串在常量池中存在
        return (jstring)sym->ref_str();
    } else {
        // 添加到常量池
        return pool->intern(string_or_null, CHECK_NULL);
    }
}

可以看出,intern()方法的实现比较简单,就是在StringTable中查找该字符串,如果该字符串已经在其中,返回该字符串;否则,将其添加到StringTable并返回该字符串。

示例说明

下面是两个示例,说明了字符串常量池和intern()方法的使用:

示例一:

String str1 = "abc";
String str2 = "abc";
System.out.println(str1 == str2); // true

// 以上代码中,str1和str2都指向字符串池中的"abc",因此相等。

String str3 = new String("abc");
System.out.println(str1 == str3.intern()); // true

// 以上代码中,str3.intern()将"abc"字符串添加到字符串池,并返回池中的字符串引用,
// 因此,str1和str3.intern()都指向字符串池中的"abc",因此相等。

示例二:

String str1 = new String("Hello");
String str2 = "Hello";
System.out.println(str1 == str2); // false

// 以上代码中,str1是用new创建的新的String对象,str2指向字符串池中的"Hello",
// 因此不相等。

String str3 = str1.intern();
String str4 = str2.intern();
System.out.println(str3 == str4); // true

// 以上代码中,str1.intern()将"Hello"添加到字符串池,并返回池中的字符串引用,
// str2.intern()直接返回字符串池中的"Hello",
// 因此str3和str4都指向字符串池中的"Hello",因此相等。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java中String字符串常量池和intern方法源码分析 - Python技术站

(0)
上一篇 2023年5月27日
下一篇 2023年5月27日

相关文章

  • 浅谈几种Java自定义异常处理方式

    浅谈几种Java自定义异常处理方式 在Java中,异常是一种非常常见的错误类型,如果没有捕获和处理异常,程序很容易因为意外的错误而导致崩溃。Java允许我们自定义异常类型,来处理程序中特定的异常情况。本文将对几种Java自定义异常处理方式进行探讨,并提供示例代码来帮助读者加深对这些技术的理解。 自定义异常类 我们可以通过继承 Java 内置的异常类(Thro…

    Java 2023年5月20日
    00
  • JPA的多表复杂查询的方法示例

    JPA是Java Persistence API的缩写,它是Java EE中的一个API,提供了Java对象到关系数据库表之间的映射(ORM)功能。JPA中的多表复杂查询是指需要查询多个关联表的查询操作。下面将介绍JPA的多表复杂查询的方法示例。 一、JPA多表查询基本操作 定义多表查询的类 在JPA中,可以定义一个类来封装多表查询的结果,该类中包含了所有需…

    Java 2023年5月20日
    00
  • Java环境中MyBatis与Spring或Spring MVC框架的集成方法

    下面是关于“Java环境中MyBatis与Spring或Spring MVC框架的集成方法”的完整攻略,包含两个示例说明。 Java环境中MyBatis与Spring或Spring MVC框架的集成方法 在Java环境中,MyBatis与Spring或Spring MVC框架的集成非常常见。在本文中,我们将介绍如何将MyBatis与Spring或Spring…

    Java 2023年5月17日
    00
  • SpringMVC中常用注解与使用方法详解

    SpringMVC中常用注解与使用方法详解 SpringMVC是一个基于MVC的Web框架,是Spring Framework的一部分,用于构建Web应用程序。SpringMVC使用注解作为开发的重要手段,本文将详细讲解SpringMVC中常用注解的使用方法。 1. @Controller注解 @Controller注解用于标注一个控制器,也就是Spring…

    Java 2023年6月16日
    00
  • SpringBoot war包部署到Tomcat服务器

    下面我将向您介绍如何将Spring Boot的war文件部署到Tomcat服务器上。 步骤一:修改pom.xml文件 在pom.xml文件中,我们需要将spring-boot-starter-tomcat依赖改为provided,以避免在打包war包时将Tomcat运行时环境打进war包中。代码示例如下: <!–在<dependencies&g…

    Java 2023年5月19日
    00
  • Springboot 配置SqlSessionFactory方式

    在Spring Boot中,我们可以使用多种方式来配置SqlSessionFactory。以下是两种常见的方式: 1. 使用MyBatis-Spring-Boot-Starter MyBatis-Spring-Boot-Starter是一个官方支持的MyBatis集成Spring Boot的插件,它可以帮助我们快速集成MyBatis和Spring Boot。…

    Java 2023年5月14日
    00
  • springmvc项目使用@Valid+BindingResult遇到的问题

    针对“springmvc项目使用@Valid+BindingResult遇到的问题”,我提供以下完整攻略: 1. 理解问题 经过实践和研究,我们发现当使用@Valid和BindingResult配合进行表单数据校验时,有时会遇到一些问题。 问题的根本原因在于BindingResult的处理方式与我们期望的不太一样,它不会使@Valid注解的校验失败,而是将校…

    Java 2023年5月20日
    00
  • 带你入门Java的泛型

    带你入门Java的泛型攻略 什么是泛型? 泛型是Java中一个非常强大的特性,它可以让我们在编程时更加安全和便捷。简单来说,泛型就是一种具有类型参数化能力的编程机制。 Java语言中引入泛型,是为了解决在编译时无法确定类型参数的情况下,对类型检查和类型转换的灵活性问题。 泛型的优点 代码重用:泛型的声明可以与具体类型无关,因此可以使用相同的代码来处理不同类型…

    Java 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部