再谈Java-String

简介: 再谈Java-String


一个案例

有以下案例:

public class Main {
\
    public static void main(String[] args) {
        String s1 = "hello";
        String s2 = "hello";
        String s3 = new String("hello");
        String s4 = new String("hello");
        System.out.println(s1 == s2);
        System.out.println(s1 == s3);
        System.out.println(s3 == s4);
    }
 
}

输出结果为:

true

false

false

为什么s1和s2是同一个对象为什么呢?

在Java程序中,类似于:1,2,3,3.14,“hello"等字面类型的常量经常频繁使用,为了使程序的运行速度更快更节省内存,Java为8种基本数据类型和String类都提供了常量池

这个字符串常量池底层就是一个哈希表, 名为StringTable. 也就是一个String对应一个Value.

什么是池?

池是编程中经常有的概念, 是一种重要的提升效率的方式, 我们会经常遇到各种池, 例如线程池, 内存池等等.

为了节省空间, 和提高运行效率, java中引用了:

  1. Class文件常量池
  2. 运行时常量池
  3. 字符串常量池

字符串常量池

这个字符串常量池底层使用c/c++写的, 我们在jvm中去看源码的话,会发现其实这个常量池是一个StringTable的类, 实际上是一个固定大小的哈希表

String对象的创建

一个完整的String对象:

可以看到里面有一个字符数字, 然后还有一个hash值, 其中这个hash值为0.

图解

那么对于字符串常量池, 字符串的存储又是怎么样的呢?

直接使用字符串常量赋值

public class Main {
    public static void main(String[] args) {
        String s1 = "hello";
        String s2 = "hello";
        System.out.println( s1 == s2); // true
    }
}

运行结果为True;

首先String s1是在main方法中的, 理论上他是一个局部变量,是一个字符串的引用, 他是被放在栈区的.

首先创建字符串S1, 将其放入常量池, 然后创建s2, 然后遍历哈希表, 发现哈希表对应的哈希值已经存在, 所以直接将这个s2引用指向s1的那个字符串.

只要是new的对象,都是唯一的

intern方法

intern方法是一个本地(native)方法, 底层使用c++实现, 看不到其实现的源代码, 该方法的作用是手动将创建的String对象, 添加到常量池当中去.

一个例子:

public class Main {
    public static void main(String[] args) {
        char[] ch = new char[] {'a','b','c'};
        String stringCh = new String(ch);
        String s1 = "abc";
        System.out.println(s1 == stringCh);
    }
}

提问: 在创建了stringCh对象只有, 常量池当中有abc字符串吗?

看运行结果:

结果为false, 说明stringCh中的"abc"没有被放入常量池, 此时再和s1比较的话, 就是两个不同的对象.

如果使用intern将其加入到常量字符串呢?

public class Main {
    public static void main(String[] args) {
        char[] ch = new char[] {'a','b','c'};
        String stringCh = new String(ch);
        stringCh.interm();
        String s1 = "abc";
        System.out.println(s1 == stringCh);
    }
}

结果为true, 可以看到intern方法把stringCh放入了常量池.


目录
相关文章
|
NoSQL 应用服务中间件 Redis
在华为鲲鹏OpenEuler20.03系统上安装Redis, Zookeeper, Nginx
在华为鲲鹏OpenEuler20.03系统上安装Redis, Zookeeper, Nginx
3477 0
在华为鲲鹏OpenEuler20.03系统上安装Redis, Zookeeper, Nginx
|
程序员 编译器 C语言
C语言库函数 — 错误信息报告函数
C语言库函数 — 错误信息报告函数
201 0
|
10月前
|
Kubernetes 监控 负载均衡
深入云原生:Kubernetes 集群部署与管理实践
【10月更文挑战第37天】在数字化转型的浪潮中,云原生技术以其弹性、可扩展性成为企业IT架构的首选。本文将引导你了解如何部署和管理一个Kubernetes集群,包括环境准备、安装步骤和日常维护技巧。我们将通过实际代码示例,探索云原生世界的秘密,并分享如何高效运用这一技术以适应快速变化的业务需求。
166 1
|
安全 Java 数据安全/隐私保护
APP加固技术及其应用
在移动应用开发过程中,APP加固技术起到了非常重要的作用。APP加固是将apk文件进行混淆加密,以防止别人反编译获取我们的源码和资源文件。目前市场上主流的APP加固公司有三家,分别是梆梆加固、360加固和ipagurd加固。本文将介绍APP加固的概念、加固方案和比较,并探讨APP加固在实际开发中的应用。
|
存储 安全 测试技术
渗透测试之白盒测试:一种深入的安全性评估方法
渗透测试中的白盒测试是一种利用系统详细信息(如源代码、数据库结构和网络拓扑)进行深度安全评估的方法。通过源代码审查、数据库分析和网络拓扑研究,测试人员能更准确地发现漏洞并提高测试效率。尽管白盒测试能深入揭露潜在威胁,但也面临信息获取难、代码理解复杂及对测试人员高技能要求的挑战。
渗透测试之白盒测试:一种深入的安全性评估方法
|
人工智能 分布式计算 大数据
AI Native平台,跨越AI应用从创新到生产的鸿沟
2024年是AI应用的元年,以大模型为中心的 AI Native 应用大爆发正在从理想变成现实。云计算带来的应用创新潮,经历了虚拟机时代和云原生时代,正在全面拥抱以大模型为核心的 AI Native 阶段,推动大数据与AI的工作流前所未有地紧密结合。领先大模型、高效的AI计算平台和统一的大数据平台是 AI Native 应用广泛落地背后不可获缺的要素。 9月20日,2024云栖大会上,阿里云副总裁、阿里云计算平台事业部负责人汪军华宣布大数据AI平台全面升级,为 AI Native 应用大爆发提供坚实的平台支撑。
|
11月前
|
SQL 监控 关系型数据库
使用SQL语句查询操作耗时的技巧与方法
在数据库管理和优化过程中,了解SQL查询操作的耗时是至关重要的
1468 0
|
缓存 PHP Nacos
nacos常见问题之nacos点击下线提示报错如何解决
Nacos是阿里云开源的服务发现和配置管理平台,用于构建动态微服务应用架构;本汇总针对Nacos在实际应用中用户常遇到的问题进行了归纳和解答,旨在帮助开发者和运维人员高效解决使用Nacos时的各类疑难杂症。
|
Java 调度 数据库
锁策略之干货分享,确定不进来看看吗?️️️
锁策略之干货分享,确定不进来看看吗?️️️
162 0
|
机器学习/深度学习 算法框架/工具
keras搭建lstm水库流量预测实战
keras搭建lstm水库流量预测实战
127 0