文章目录

  • 简介
  • String是不可变的
  • 传值还是传引用
  • substring() 导致的内存泄露
  • 总结

一文弄懂String的所有小秘密

简介

String是java中非常常用的一个对象类型。可以说java中使用最多的就是String了。那么String到底有哪些秘密呢?接下来本文将会一一讲解。

String是不可变的

String是不可变的,官方的说法叫做immutable或者constant。

String的底层其实是一个Char的数组。

private final char value[];

所有的String字面量比如"abc"都是String的实现。

考虑下面的赋值操作:

String a="abc";
String b="abc";

对于java虚拟机来说,"abc"是字符串字面量,在JDK 7之后,这个字符串字面量是存储在java heap中的。而在JDK 7之前是有个专门的方法区来存储的。

有了“abc”,然后我们将“abc” 赋值给a和b。

可以看到这里a和b只是java heap中字符串的引用。

再看看下面的代码发生了什么:

String c= new String("abc");

首先在java heap中创建了“abc”,然后调用String的构造函数:

    public String(String original) {this.value = original.value;this.hash = original.hash;}

在构造函数中,String将底层的字符串数组赋值给value。

因为Array的赋值只是引用的赋值,所以上述new操作并不会产生新的字符串字面值。

但是new操作新创建了一个String对象,并将其赋值给了c。

String的不可变性还在于,String的所有操作都会产生新的字符串字面量。原来的字符串是永远不会变化的。

字符串不变的好处就在于,它是线程安全的。任何线程都可以很安全的读取字符串。

传值还是传引用

一直以来,java开发者都有这样的问题,java到底是传值还是传引用呢?

我想,这个问题可以从两方面来考虑。

首先对于基础类型int,long,double来说,对他们的赋值是值的拷贝。而对于对象来说,赋值操作是引用。

另一方面,在方法调用的参数中,全部都是传值操作。

public static void main(String[] args) {String x = new String("ab");change(x);System.out.println(x);
}public static void change(String x) {x = "cd";
}

我们看上面的例子,上面的例子输出ab。因为x是对“ab”的引用,但是在change方法中,因为是传值调用,所以会创建一个新的x,其值是“ab”的引用地址。当x被重新赋值之后,改变的只是拷贝之后的x值。而本身的x值是不变的。

substring() 导致的内存泄露

第一次看到这个话题,大家可能会很惊讶,substring方法居然会导致内存泄露?这个话题要从JDK 6开始讲起。

我们先看下JDK 6的实现:

String(int offset, int count, char value[]) {this.value = value;this.offset = offset;this.count = count;
}public String substring(int beginIndex, int endIndex) {//check boundaryreturn  new String(offset + beginIndex, endIndex - beginIndex, value);
}

可以看到,JDK 6的substring方法底层还是引用的原始的字符串数组。唯一的区别就是offset和count不同。

我们考虑一下下面的应用:

String string = "abcdef";
String subString = string.substring(1, 3);
string = null;

虽然最后我们将String赋值为null,但是subString仍然引用了最初的string。将不会被垃圾回收。

在JDK 7之后,String的实现发送了变化:

public String(char value[], int offset, int count) {//check boundarythis.value = Arrays.copyOfRange(value, offset, offset + count);
}public String substring(int beginIndex, int endIndex) {//check boundaryint subLen = endIndex - beginIndex;return new String(value, beginIndex, subLen);
}

Arrays.copyOfRange将会拷贝一份新的数组,而不是使用之前的数组。从而不会发生上面的内存泄露的问题。

总结

虽然String是我们经常使用的对象,但是里面的原理还是值得我们了解的。

更多精彩内容且看:

  • 区块链从入门到放弃系列教程-涵盖密码学,超级账本,以太坊,Libra,比特币等持续更新
  • Spring Boot 2.X系列教程:七天从无到有掌握Spring Boot-持续更新
  • Spring 5.X系列教程:满足你对Spring5的一切想象-持续更新
  • java程序员从小工到专家成神之路(2020版)-持续更新中,附详细文章教程

本文作者:flydean程序那些事

本文链接:http://www.flydean.com/string-all-in-one/

本文来源:flydean的博客

欢迎关注我的公众号:程序那些事,更多精彩等着您!

一文弄懂String的所有小秘密相关推荐

  1. 一文弄懂EnumMap和EnumSet

    文章目录 简介 EnumMap 什么时候使用EnumMap EnumSet 总结 一文弄懂EnumMap和EnumSet 简介 一般来说我们会选择使用HashMap来存储key-value格式的数据, ...

  2. deque stack java_一文弄懂java中的Queue家族

    简介 java中Collection集合有三大家族List,Set和Queue.当然Map也算是一种集合类,但Map并不继承Collection接口. List,Set在我们的工作中会经常使用,通常用 ...

  3. 一文弄懂元学习 (Meta Learing)(附代码实战)《繁凡的深度学习笔记》第 15 章 元学习详解 (上)万字中文综述

    <繁凡的深度学习笔记>第 15 章 元学习详解 (上)万字中文综述(DL笔记整理系列) 3043331995@qq.com https://fanfansann.blog.csdn.net ...

  4. 一文弄懂神经网络中的反向传播法

    最近在看深度学习的东西,一开始看的吴恩达的UFLDL教程,有中文版就直接看了,后来发现有些地方总是不是很明确,又去看英文版,然后又找了些资料看,才发现,中文版的译者在翻译的时候会对省略的公式推导过程进 ...

  5. 一文弄懂各种loss function

    有模型就要定义损失函数(又叫目标函数),没有损失函数,模型就失去了优化的方向.大家往往接触的损失函数比较少,比如回归就是MSE,MAE,分类就是log loss,交叉熵.在各个模型中,目标函数往往都是 ...

  6. 一文弄懂神经网络中的反向传播法——BackPropagation【转】

    本文转载自:https://www.cnblogs.com/charlotte77/p/5629865.html 一文弄懂神经网络中的反向传播法--BackPropagation 最近在看深度学习的东 ...

  7. CAD2010 为了保护_一文弄懂,锂电池的充电电路,以及它的保护电路方案设计

    原标题:一文弄懂,锂电池的充电电路,以及它的保护电路方案设计 锂电池特性 首先,芯片哥问一句简单的问题,为什么很多电池都是锂电池? 锂电池,工程师对它都不会感到陌生.在电子产品项目开发的过程中,尤其是 ...

  8. 一文弄懂Flink网络流控及反压

    一文弄懂Flink网络流控及反压 1. 为什么需要网络流控? 2. 网络流控的实现:静态限速 3. 网络流控的实现:动态反馈/自动反压 3.1 案例一:Storm 反压实现 3.2 案例二:Spark ...

  9. 一文弄懂halcon例程:rim.hdev

    一文弄懂halcon例程:rim.hdev 打怪的路上总是无聊的,但是也不能不打啊,我自己现在也在每天打怪升级呢.昨天就因为一个问题,我到视觉群问里面的大牛,结果,他不帮我解答,他不告诉我怎么解决就算 ...

最新文章

  1. java中JFrame类中函数addWindowListener(new WindowAdapter)
  2. .NET框架设计—常被忽视的框架设计技巧
  3. 美国农业生产与农产品国际贸易 对话国际农民丰收节贸易会
  4. 【Linux网络编程】原始套接字实例:MAC 地址扫描器
  5. HttpClient的简单使用
  6. 八个老师随机分配三个办公室
  7. python合并csv文件_Python学习——pandas 合并csv文件
  8. tensorFlow13卷积神经网络发展
  9. 贪婪算法在求解最小生成树中的应用(JAVA)--Prim算法
  10. “熊猫血”产妇诞双胞胎困难 丈夫全城寻找血源
  11. Windbg 查看SSDT表
  12. docker 笔记(2) -- 镜像
  13. 设置element-iu中table滚动条位置
  14. 三星宣布7nm LPP芯片量产!性能高20%,功耗降50%,面积降40%
  15. Mongoose源码分析之--简单的服务器搭建(C语言)
  16. vim编辑器操作汇总
  17. React 路由 中 BrowserHistory 刷新报404
  18. 利用HTML简单语句来制作个人简历
  19. 商淘软件五周年:着力打造S2B2C及电商一站式服务专家
  20. Notepad++添加读取十六进制插件HexEditor

热门文章

  1. ubuntu安装linux deepin,如何在Ubuntu中安装Deepin终端 | MOS86
  2. SlopOne推荐算法
  3. Burnside引理和Polya定理学习笔记
  4. PostgreSQL学习笔记1之表定义
  5. cocos2d-x初探学习笔记(12)--图形绘制
  6. C++ STL : 模拟实现STL中的关联式容器unordered_map/unordered_set
  7. scrapy设置代理的方法
  8. 微服务架构统一安全认证设计与实践
  9. 干货!全面认识Docker和基本指令
  10. 以高并发著称的 Go 如何与 MySQL 搭档应对千亿级数据?