小小字符串竟然如此嚣张 —— 聊聊 Java 的 String

2024-05-25 16:52

本文主要是介绍小小字符串竟然如此嚣张 —— 聊聊 Java 的 String,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

大家好,我是徒手敲代码。

今天来分享几个 String 在面试当中,比较常见的问题。这个东西用得最多,而且底层的原理,面试也经常问。

两种创建方式,有什么区别?

比如,要创建一个 “Gary” 的字符串,可以采用以下这两种方式:

String s1 = new String("Gary");String s2 = "Gary";
  • 第一种方式,用 new 关键词创建,无论字符串常量池中,是否存在相同内容的字符串,都会在堆内存中新建一个String对象。这种方式相对耗资源,因为即使内容相同,也会产生不同的对象实例。

  • 第二种方式,叫做字面量赋值,JVM 会在字符串常量池中,查找是否有相同的字符串。如果有,则直接引用它;如果没有,则创建一个新字符串并放入池中,然后引用它。这种方式可以减少内存分配和垃圾回收的负担。

String 的 +

对字符串进行拼接的时候,通常会用+,那么这个的底层原理是什么呢?举个例子:

String s = "abc" + "def";

这行代码,编译器会自动 new 一个 StringBuilder出来,然后进行 append操作,如下:

String s = (new StringBuilder()).append("abc").append("def").toString();

这也是为什么,尽管 Stirng 不是 Java 的 8 大基本数据类型和对应的装箱类型,而是个引用类型,但还能够使用 + 来运算的理由。是 Java 的设计者们开了条好路。

String 不可变

这也是个老生常谈的问题了。

首先来说说,改变一个变量、改变一个变量的值 有什么区别?

  • 改变量:修改这个变量所指的内存地址

  • 改变量的值:在这个变量所指的内存地址上,修改存储的内容

接着来说,可变类型、不可变类型 有什么区别?

  • 可变类型:拥有方法可以修改自己的值/引用

  • 不可变类型:一旦被创建,其值不能改变(但可以修改所引用的对象),任何修改操作都会创建一个新的对象

来看看以下这段代码,针对可变类型的对象,在方法内部,修改入参的值:

class Demo {public static void main(String[] args) {Person person = new Person("Gary",30);System.out.println("一开始的person:" + person);Demo.changePerson(person);System.out.println("执行了change方法之后的person:" + person);}public static void changePerson(Person person){person.setName("Tam");person.setAge(20);}
}

输出:

一开始的person:Person{name='Gary', age=30}
执行了change方法之后的person:Person{name='Tam', age=20}

再来看看 String 这种不可变类型的对象,如果在方法内部修改入参的值,会发生什么:

class Demo {public static void main(String[] args) {String s = "abc";System.out.println(s);Demo.change(s);System.out.println(s);}public static void change(String s){s = "111";System.out.println("方法内打印的结果:" + s);}
}

输出:

abc
方法内打印的结果:111
abc

虽然方法内部改了 s 对象的值,但实际上是在这个方法的内部,将 s 引用到了一个新的对象,也就是在方法内部新建了一个 s 对象,当方法结束的时候,这个新建的 s 对象会被回收,main 方法中的 s 对象并不受影响。

下面总结一下,String 设计成不可变的原因,主要从安全和性能两个方面来考虑:

安全

多线程环境下,共享一个 String 类型的对象,不用担心线程安全问题,因为它是不可变的

性能

第一,String 在初始化的时候会缓存自己的哈希值,每次要用的时候都可以直接获取,而不需要重新计算,比如 Map 集合用 String 类型作为 Key ,可以大大提高查询效率;

第二,字符串常量机制,通过字面量赋值的方式创建 String 对象,先检查常量池有没有这个对象,有就直接引用,没有才创建,这种方式可以减少内存消耗和垃圾回收的压力

今天的分享到这里结束了。

关注公众号“徒手敲代码”,免费领取由腾讯大佬推荐的Java电子书!

这篇关于小小字符串竟然如此嚣张 —— 聊聊 Java 的 String的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1002078

相关文章

SpringBoot整合Flowable实现工作流的详细流程

《SpringBoot整合Flowable实现工作流的详细流程》Flowable是一个使用Java编写的轻量级业务流程引擎,Flowable流程引擎可用于部署BPMN2.0流程定义,创建这些流程定义的... 目录1、流程引擎介绍2、创建项目3、画流程图4、开发接口4.1 Java 类梳理4.2 查看流程图4

一文详解如何在idea中快速搭建一个Spring Boot项目

《一文详解如何在idea中快速搭建一个SpringBoot项目》IntelliJIDEA作为Java开发者的‌首选IDE‌,深度集成SpringBoot支持,可一键生成项目骨架、智能配置依赖,这篇文... 目录前言1、创建项目名称2、勾选需要的依赖3、在setting中检查maven4、编写数据源5、开启热

Java对异常的认识与异常的处理小结

《Java对异常的认识与异常的处理小结》Java程序在运行时可能出现的错误或非正常情况称为异常,下面给大家介绍Java对异常的认识与异常的处理,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参... 目录一、认识异常与异常类型。二、异常的处理三、总结 一、认识异常与异常类型。(1)简单定义-什么是

SpringBoot项目配置logback-spring.xml屏蔽特定路径的日志

《SpringBoot项目配置logback-spring.xml屏蔽特定路径的日志》在SpringBoot项目中,使用logback-spring.xml配置屏蔽特定路径的日志有两种常用方式,文中的... 目录方案一:基础配置(直接关闭目标路径日志)方案二:结合 Spring Profile 按环境屏蔽关

Java使用HttpClient实现图片下载与本地保存功能

《Java使用HttpClient实现图片下载与本地保存功能》在当今数字化时代,网络资源的获取与处理已成为软件开发中的常见需求,其中,图片作为网络上最常见的资源之一,其下载与保存功能在许多应用场景中都... 目录引言一、Apache HttpClient简介二、技术栈与环境准备三、实现图片下载与保存功能1.

SpringBoot排查和解决JSON解析错误(400 Bad Request)的方法

《SpringBoot排查和解决JSON解析错误(400BadRequest)的方法》在开发SpringBootRESTfulAPI时,客户端与服务端的数据交互通常使用JSON格式,然而,JSON... 目录问题背景1. 问题描述2. 错误分析解决方案1. 手动重新输入jsON2. 使用工具清理JSON3.

java中long的一些常见用法

《java中long的一些常见用法》在Java中,long是一种基本数据类型,用于表示长整型数值,接下来通过本文给大家介绍java中long的一些常见用法,感兴趣的朋友一起看看吧... 在Java中,long是一种基本数据类型,用于表示长整型数值。它的取值范围比int更大,从-922337203685477

java Long 与long之间的转换流程

《javaLong与long之间的转换流程》Long类提供了一些方法,用于在long和其他数据类型(如String)之间进行转换,本文将详细介绍如何在Java中实现Long和long之间的转换,感... 目录概述流程步骤1:将long转换为Long对象步骤2:将Longhttp://www.cppcns.c

SpringBoot集成LiteFlow实现轻量级工作流引擎的详细过程

《SpringBoot集成LiteFlow实现轻量级工作流引擎的详细过程》LiteFlow是一款专注于逻辑驱动流程编排的轻量级框架,它以组件化方式快速构建和执行业务流程,有效解耦复杂业务逻辑,下面给大... 目录一、基础概念1.1 组件(Component)1.2 规则(Rule)1.3 上下文(Conte

SpringBoot服务获取Pod当前IP的两种方案

《SpringBoot服务获取Pod当前IP的两种方案》在Kubernetes集群中,SpringBoot服务获取Pod当前IP的方案主要有两种,通过环境变量注入或通过Java代码动态获取网络接口IP... 目录方案一:通过 Kubernetes Downward API 注入环境变量原理步骤方案二:通过