当前位置: 首页 > news >正文

简单说明String类为什么是final的

声明为final类的目的

主要目的就是保证String是不可变(immutable)。不可变就是第二次给一个String 变量赋值的时候,不是在原内存地址上修改数据,而是重新指向一个新对象,新地址。下面看String类源码如何保证是不可变的:

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence
{
    /** The value is used for character storage. */
    private final char value[];
    
    ...

String类的主力成员字段value是个char[ ]数组,而且是用final修饰的。编译器不允许把value指向另一个地址。但可以直接对数组元素修改。为了保证这个数组元素不能修改,做了如下措施:
(1)所有String的方法里很小心的没有去动数组里的元素,没有暴露内部成员字段。
(2)避免被其他人继承后破坏,整个String设成final禁止继承。如果有一个String的引用,它引用的一定是一个String对象,而不可能是其他类的对象。

为什么要不String设计为不可变

  • 从内存角度来看
    字符串常量池的要求:创建字符串时,如果该字符串已经存在于池中,则将返回现有字符串的引用,而不是创建新对象。字符串池的实现可以在运行时节约很多heap空间,多个String变量引用指向同一个内地地址。如果字符串是可变的,用一个引用更改字符串将导致其他引用的值错误。这是很危险的。

  • 缓存Hashcode
    字符串的Hashcode在java中经常配合基于散列的集合一起正常运行,这样的散列集合包括HashSet、HashMap以及HashTable。不可变的特性保证了hashcode永远是相同的。不用每次使用hashcode就需要计算hashcode。这样更有效率。因为当向集合中插入对象时,是通过hashcode判别在集合中是否已经存在该对象了(不是通过equals方法逐个比较,效率低)。

  • 方便其它类使用
    其他类的设计基于string不可变,如set存储string,改变该string后set包含了重复值。

  • 安全性
    String被广泛用作许多java类的参数,例如网络连接、打开文件等。如果对string的某一处改变一不小心就影响了该变量所有引用的表现,则连接或文件将被更改,这可能导致严重的安全威胁。
    不可变对象不能被写,所以不可变对象自然是线程安全的,因为不可变对象不能更改,它们可以在多个线程之间自由共享。

总结

由于效率和安全性的原因,字符串被设计为不可变

如果大家对java架构相关感兴趣,可以关注下面公众号,会持续更新java基础面试题, netty, spring boot,spring cloud等系列文章,一系列干货随时送达, 超神之路从此展开, BTAJ不再是梦想!

架构殿堂

相关文章:

  • RocketMQ启动broker提示 错误:找不到或无法加载主类
  • CSS盒子模型
  • 总结HashMap和TreeMap的区别
  • Spring AOP中pointcut expression表达式解析 及匹配多个条件
  • typora+picgo+gitee,轻松搞定图片上传
  • 转载-C#事件的使用和讲解
  • 详细描述Error和Exception(运行期和编译期)的区别
  • 线程的生命周期以及状态
  • ArcGIS AddIn调用ArcMap自带的对话框
  • 总结Synchronized与Lock的区别
  • 带你了解 java 各种锁
  • 求一个版本号的正则表达式,版本号的格式可以是1.1或1.1.2或10000这个样子的
  • 序列化和反序列化总结
  • 适配器模式
  • 运行django项目时出错
  • ESLint简单操作
  • Python 使用 Tornado 框架实现 WebHook 自动部署 Git 项目
  • 聚簇索引和非聚簇索引
  • 前端路由实现-history
  • 如何借助 NoSQL 提高 JPA 应用性能
  • 一起参Ember.js讨论、问答社区。
  • ​低代码平台的核心价值与优势
  • ​直流电和交流电有什么区别为什么这个时候又要变成直流电呢?交流转换到直流(整流器)直流变交流(逆变器)​
  • # Pytorch 中可以直接调用的Loss Functions总结:
  • #pragma once
  • $(selector).each()和$.each()的区别
  • (39)STM32——FLASH闪存
  • (html转换)StringEscapeUtils类的转义与反转义方法
  • (Matalb时序预测)PSO-BP粒子群算法优化BP神经网络的多维时序回归预测
  • (NSDate) 时间 (time )比较
  • (Redis使用系列) Springboot 整合Redisson 实现分布式锁 七
  • (阿里巴巴 dubbo,有数据库,可执行 )dubbo zookeeper spring demo
  • (附源码)spring boot公选课在线选课系统 毕业设计 142011
  • (利用IDEA+Maven)定制属于自己的jar包
  • (删)Java线程同步实现一:synchronzied和wait()/notify()
  • . NET自动找可写目录
  • .Net CoreRabbitMQ消息存储可靠机制
  • .NET Core实战项目之CMS 第十二章 开发篇-Dapper封装CURD及仓储代码生成器实现
  • .NET MVC之AOP
  • .NET 依赖注入和配置系统
  • .NET 中让 Task 支持带超时的异步等待
  • .NET 中小心嵌套等待的 Task,它可能会耗尽你线程池的现有资源,出现类似死锁的情况
  • .NET/C# 检测电脑上安装的 .NET Framework 的版本
  • .NET开发不可不知、不可不用的辅助类(一)
  • .net流程开发平台的一些难点(1)
  • @RequestBody与@ModelAttribute
  • @拔赤:Web前端开发十日谈
  • @基于大模型的旅游路线推荐方案
  • [.net 面向对象程序设计进阶] (19) 异步(Asynchronous) 使用异步创建快速响应和可伸缩性的应用程序...
  • [\u4e00-\u9fa5] //匹配中文字符
  • [【JSON2WEB】 13 基于REST2SQL 和 Amis 的 SQL 查询分析器
  • [20150629]简单的加密连接.txt
  • [52PJ] Java面向对象笔记(转自52 1510988116)
  • [AAuto]给百宝箱增加娱乐功能
  • [BZOJ] 1001: [BeiJing2006]狼抓兔子