[译] 为什么String在Java中是不可变的

代码星冰乐

专注成就未来

首页 归档 关于

[译] 为什么String在Java中是不可变的

Jul 8, 2019 | haifeiWu | Java | 阅读
文章目录
  1. 1. 1. 字符串池
  2. 2. 2. 缓存的哈希码
  3. 3. 3. 其他对象中的字符串
  4. 4. 4. 安全
  5. 5. 5. 不可变保证了线程安全

作 者:haifeiWu
原文链接:https://www.hchstudio.cn/article/2019/496a/
版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。


由于版权原因,请阅读原文 --> [译] 为什么String在Java中是不可变的

关注我们

作 者:haifeiWu
原文链接:https://www.hchstudio.cn/article/2019/496a/
版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。

作 者:haifeiWu
原文链接:https://www.hchstudio.cn/article/2019/496a/
版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。

String 在 Java 中是不可变的。 不可变类只是一个无法修改其实例的类。 创建实例时,将初始化实例中的所有信息,并且无法修改信息。 不可变类有许多优点。 本文总结了为什么 String 设计为不可变的。 这篇文章从内存,同步和数据结构的角度说明了不变性概念。

1. 字符串池

字符串池(String intern pool)是方法区域中的特殊存储区域。 创建字符串并且池中已存在该字符串时,将返回现有字符串的引用,而不是创建新对象。

以下代码将在堆中仅创建一个字符串对象。

1
2
String string1 = "abcd";
String string2 = "abcd";

如下图所示:

字符串池

如果字符串是可变的,则使用一个引用更改字符串将导致其他引用的错误。

2. 缓存的哈希码

字符串的哈希码经常在 Java 中使用。 例如,在 HashMap 或 HashSet 中。 不可变保证哈希码总是相同的,这样它就可以缓存起来而不用担心变化。这意味着,每次使用时都不需要计算哈希码。 这更有效率。

在String类中,它具有如下代码:

1
private int hash;//this is used to cache hash code.

3. 其他对象中的字符串

为了具体,请参考以下程序:

1
2
3
4
5
6
7
HashSet<String> set = new HashSet<String>();
set.add(new String("a"));
set.add(new String("b"));
set.add(new String("c"));

for(String a: set)
a.value = "a";

在此示例中,如果 String 是可变的,则可以更改其值,这将违反 set 的设计(set包含非重复元素)。 当然,上面的示例仅用于演示目的,并且实际字符串类中没有值字段。

4. 安全

String 被广泛用作许多 java 类的参数,例如 网络连接,打开文件等。字符串不是不可变的,连接或文件将被更改,这可能会导致严重的安全威胁。 该方法认为它连接到一台机器,但事实并非如此。 可变字符串也可能在 Reflection 中引起安全问题,因为参数是字符串。

如下例子:

1
2
3
4
5
6
7
boolean connect(string s){
if (!isSecure(s)) {
throw new SecurityException();
}
//here will cause problem, if s is changed before this by using other references.
causeProblem(s);
}

5. 不可变保证了线程安全

由于无法更改不可变对象,因此可以在多个线程之间自由共享它们。 这消除了进行同步的要求。

综上所诉,出于效率和安全原因,String 被设计为不可变的,这也是在一般情况下在一些情况下优选不可变类的原因。

关注我们

作 者:haifeiWu
原文链接:https://www.hchstudio.cn/article/2019/496a/
版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。

分享
Java
lang3 的 split 方法误用双重检查锁定与单例
微信关注我们
分类
  • Android8
  • Go4
  • Java59
  • Kafka,Java1
  • Kotlin2
  • Linux1
  • MapReduce1
  • Python2
  • Raft1
  • Redis1
  • ThreadPoolExecutor1
  • go1
  • 工具1
  • 总结8
  • 旅游日记1
标签
Nginx ChanghuiN haifeiWu Android Java 设计模式 hexo Kotlin 算法 MySQL 源码解析 Python Redis golang web Kafka 配置中心 总结 性能优化 旅游日记 Shell Go 问题排查 译文 Docker Spring Boot 工具 学习笔记 WebFlux 性能测试 go 散列表 源码 netty Raft
最近文章
  • Kafka的日志复制机制
  • 从20到21
  • go 并发编程
  • 【译】了解Linux CPU负载-您何时应该担心?
  • Zookeeper 与分布式锁
  • 基于Redis的分布式锁到底安全吗?
  • 【译】Raft 学生指南
  • ThreadPoolExecutor 的简单梳理
  • MapReduce 的简单实现
  • 使用 Map 实现策略模式
福利专区
    免费SSL证书
      阿里云红包
        腾讯云专属福利
        Copyright © 2021 代码星冰乐. Powered by ChanghuiN. 版权所有 晋ICP备15001365号
        特别感谢: 云服务器服务商 、 CDN 服务商