跟大佬展开激励讨论String的不可变性

news2024/11/17 0:31:36

 

目录

大佬证明:

我的证明:

后续

什么是不可变?

String为什么不可变

为什么要设计成为不可变的呢? 

1.首先我们最先可以想到的Java主要做的就是安全

2.其次是字符串常量池的需要

String真的不可变吗?


ps:事情是这样的,前段时间跟一位大佬随口提了一嘴String的不可变的原因,也是比较浅的说了一嘴,都没有放心上。过了几天大佬给我发消息过来说他翻找了一下他之前的笔记,对于String不可变的关键原因final才是不可变的关键,这一下激起来我的兴趣,于是我们各持观点展开了“辩论赛”,首先我们来看一下Java源码

 我们可以看到String类中有两个属性,分别为value数组与hash,其中value数组是被private final所修饰的,我们的观点产生了分歧,大佬所持的观点是final是String不可变的关键,我所持的观点是private是String不可变的关键

大佬证明:

 随后大佬问了我一个这样的问题,当这么定义的时候,str1==str2输出的结果

public static void main (String[] args) {
        String str1="hello";
        String str2="hello";
        System.out.println(str1==str2);
}

我大概看了一下,想到只要是变量就会开辟栈帧,对于对象引用之间比较的是地址,所以输出false;肯定是错了,我忘记了他们指向的都是常量池中同一个对象。如此一来,我直接落入下风,大佬趁势继续提了一个问题

public static void main (String[] args) {
        String str1=new String("hello");
        String str2="hello";
        System.out.println(str1==str2);
}

这个我答对了 是false,回答出这个问题我才想到我之前上个问题回答错了;随后我便要开始狡辩了~

我的证明:

首先我给大佬看了这个图

 看完之后我们突然发现~讨论的问题尺度偏了,但是这也正好展现出了String类在JVM中存储的简图,再回到我们之前的问题后,我开始了我的证明,我的观点是:

final修饰类表明该类不可以被继承,final修饰引用类型表明该引用变量不能引用其他对象,但是其引用对象中的内容是可以修改的,所以final不是String不可变的关键原因,为何说private是String不可变的关键原因,是因为private是封装的意思,被private修饰后,类外无法访问到,并且String类中也没有提供到任何可以用来修改value数组中值的方法,所以才造成String不可变

后续

大佬听完我的观点后,之后一起去查阅资料发现了真正原因


什么是不可变?

        对象一旦被创建后,对象所有的状态及属性在其生命周期内不会发生任何变化。这就意味着,一旦我们将一个对象分配给一个变量,就无法再通过任何方式更改对象的状态了

String 不可变的表现就是当我们试图对一个已有的对象 "abcd" 赋值为 "abcde",String 会新创建一个对象,从而引用其他对象;


String为什么不可变

        String中的value属性被final所修饰,这个数组无法被修改,这么说确实没啥问题。

但是!!!这个无法被修改仅仅是指引用地址不可被修改(也就是说栈里面的这个叫 value 的引用地址不可变,编译器不允许我们把 value 指向堆中的另一个地址),并不代表存储在堆中的这个数组本身的内容不可变

我们来看一下以下例子

 但是我们如果仅仅改变数组中的值,如下是可以的

那既然说String是不可变的,那显然仅仅靠final支撑是不够的

1)首先,char 数组是 private 的,并且 String 类没有对外提供修改这个数组的方法,所以它初始化之后外界没有有效的手段去改变它;

2)其次,String 类被 final 修饰的,也就是不可继承,避免被他人继承后破坏;

3)最重要的!是因为 Java 作者高斯林老爷子String 的所有方法里面,都很小心地避免去修改了 char 数组中的数据,涉及到对 char 数组中数据进行修改的操作全部都会重新创建一个 String 对象。

4)所以说,对于String不可变的解释,我们可以说两者都是缺一不可的,两者是互相搭配,final和private 都影响了


为什么要设计成为不可变的呢? 

1.首先我们最先可以想到的Java主要做的就是安全

        然而private就是为了安全所诞生的,这也更加体现出private是不可缺少的,作为最基础最常用的数据类型,String 被许多 Java 类库用来作为参数,如果 String 不是固定不变的,将会引起各种安全隐患。

2.其次是字符串常量池的需要

        为什么会存在字符串常量池呢?它所存在的意义是什么呢?大量频繁的创建字符串,将会大大的影响程序的性能,为此,JVM 为了提高性能和减少内存开销,在实例化字符串常量的时候进行了一些优化

  • 为字符串开辟了一个字符串常量池 String Pool,可以理解为缓存区
  • 创建字符串常量时,首先检查字符串常量池中是否存在该字符串
  • 若字符串常量池中存在该字符串,则直接返回该引用实例,无需重新实例化;若不存在,则实例化该字符串并放入池中。

我们可以将之前的代码再拿出来看看

public static void main (String[] args) {
        String str1="hello";
        String str2="hello";
        System.out.println(str1==str2);
}

为什么他们会使true呢?因为他们共同指向了常量池中的“hello”所在的地址,假设我们的String是可以变的,那么我们通过修改str2=“world”; 那么我们的str1中所指向的内容也会被改变,这显然不是老爷子设计Java之初,也不是我们想要看到的


String真的不可变吗?

        想要改变 String 无非就是改变 char 数组 value 的内容,而 value 是私有属性,那么在 Java 中有没有某种手段可以访问类的私有属性呢?

我们Java中有一种反射的手段,反射是什么意思呢,大概给大家来一张图理解一下

假设我们帅气的博主今天去过安检,带着一个行李箱,行李箱中装着一把加特林

 那么我们肯定是过不去安检的啦,安检会发现我们在行李箱中的加特林,反射就类似于安检机。

那么我们看如下代码

 如此一来便做到了修改值,所以说这个跟安全也是互斥的~至于为什么设计,那就不得而知了,可能老爷子有着自己的想法~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/96756.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

平淡无奇,2022年终总结

1前言 一年又一年,时间过得太快啦! 最近总是想着2022年的点点滴滴,一年时光不得写点什么不一样的,可是思前想后觉得这一年也没什么不一样的啊。所以呢,2022年终总结标题就取名为平淡无奇。 人一生最重要的是什么&#…

Java Servlet + H2数据库之集成环境配置

在 EclipseMavenTomcat 集成开发环境配置 搭建了一个Servlet的开发环境,整合Tomcat 作为Web容器。如何要加入数据库开发要怎么处理呢? 在实际开发中,一般会选择MySQL,Oracle 等数据库, 但是如果只是学习和演示&#x…

DPDK源码分析之网络基础知识

字节对齐 attribute ((aligned (1))); 在设计不同CPU下的通信协议时,或者编写硬件驱动程序时寄存器的结构这两个地方都需要按一字节对齐。即使看起来本来就自然对齐的也要使其对齐,以免不同的编译器生成的代码不一样. 如果跨越了4字节边界存储&#xff…

java之JVM的位置和体系结构

JVM的概念: JVM 即 Java Virtual Machine,中文名为 Java虚拟机,一般情况下,对于C/C 程序,编译成二进制文件后,就可以直接执行了,但Java 需要使用 javac 编译成 .class 文件,还需要使…

【LSTM回归预测】基于matlab主成分分析结合BiLSTM数据回归预测【含Matlab源码 2276期】

一、LSTM和BiLSTM神经网络结构及原理介绍 长短期记忆网络(Long short-term memory, LSTM)实质上可以理解为一种特殊的RNN,主要是为了解决RNN网络在长序列训练过程中发生梯度消失和梯度爆炸的问题。相比于RNN,LSTM主要是引入了细胞形态(cell state)用于保存长期状态&#xff0c…

世界杯决赛倒计时,你最看好谁

一、期待终极决赛 C站肯定有许多看球的朋友吧。明天即将迎来2022年世界杯终极对决,阿根廷队对战法国。来赶个晚集,也来聊聊世界杯,下一个四年就是2026,会不会还有这种精神呢。先来回顾一下本轮世界杯比赛中的对阵吧。 本轮世界杯中…

Win11+RTX3060+Anconda+CUDA11.3+cuDNN8.2+Pytorch1.10一条龙服务2

Win11RTX3060AncondaCUDA11.3cuDNN8.2Pytorch1.10一条龙服务 (1)查看安装了哪些包 conda list(2)查看当前存在哪些虚拟环境 conda env list (3)创建虚拟环境,你可以创建好几个虚拟环境,虚拟环…

Flex布局小练--博文列表item布局实现

文章目录前言元素组成实现html部分布局总结前言 今天划一个水先,没办法,作孽没写完,什么这不是作孽的一部分嘛?!听不见,听不见。 来先看一下我们要做的一个效果: 首先是这个页面下面的&#xf…

如何基于Jetbrains IDEA DataBase从数据库表中生成对应的Java Bean

在日常的项目开发过程中,大部分人可能都会遇到过想从表自动生成带有注释的Java Bean,在Jetbrains IDEA中通过DataBase工具也是可以生成的。Jetbrains IDEA的Database借助一个名称为Generate POJOs.groovy的groovy模板文件,可以帮我们做代码生…

Python工程师Java之路(t)SpringBoot部署步骤 java -jar

文章目录步骤1、开发环境2、新建工程3、新建controller4、开发环境试运行和测试5、打包运行命令补充步骤 1、开发环境 WIN10IDEA2021Maven3.6.3JDK1.8 2、新建工程 选择Spring和Java版本 添加依赖 3、新建controller package com.example.demo.controller;import org.spr…

macOS Ventura 13.1 (22C65) Boot ISO 原版可引导镜像

本站下载的 macOS Ventura 软件包,既可以拖拽到 Applications(应用程序)下直接安装,也可以制作启动 U 盘安装,或者在虚拟机中启动安装。 2022 年 12 月 13 日,macOS Ventura 13.1 推出了“无边记”&#x…

基于python的PatchMatchStereo立体匹配算法实现

文章目录前言一、PatchMatchStereo是什么?1.随机初始化2.迭代传播2.1空间传播2.2视图传播2.3帧间传播2.4平面细化二、PatchMatchStereo立体匹配算法实现前言 PatchMatchStereo是Michael Bleyer等在2011年发表于British Machine Vision Conference(BMVC&a…

机器学习 鸢尾花数据集划分 训练集和测试集

目录 一:加载数据 二:数据集整理 三:数据集划分 一:加载数据 加载数据,并创建一个DataFrame,便于数据分析 from sklearn.datasets import load_iris import pandas as pd import numpy as np from skle…

大数据:计算学生成绩

文章目录一、提出任务二、任务进行(一)准备数据1、在虚拟机上创建文本文件2、上传文件到HDFS指定目录(二)实现步骤1、创建Maven项目2、添加相关依赖3、创建日志属性文件4、创建成绩映射器类5、创建成绩驱动器类6、启动成绩驱动器类…

【JavaSE】类和对象(三)——内部类

目录 1. 何为内部类 2. 内部类的分类 2.1 静态内部类 2.1.1 如何实例化静态内部类的对象? 2.1.2 外部类与静态内部类如何相互访问? 2.2 非静态内部类/实例内部类 2.2.1 非静态内部类不能定义静态的成员变量以及方法 2.2.2 非静态内部类的实例化 2.2.…

三层-生成树-ospf-速端口思科练习实验

♥️作者:小刘在这里 ♥️每天分享云计算网络运维课堂笔记,疫情之下,你我素未谋面,但你一定要平平安安,一 起努力,共赴美好人生! ♥️夕阳下,是最美的,绽放,…

Spark-SaprkStreaming(概述、架构、原理、DStream转换、案例)

文章目录SparkStreaming概述特点架构原理DStream和RDD的区别DAG如何读取数据(※)WordCount 案例实操代码解析RDD 队列用法及说明案例实操自定义数据源Kafka 数据源DStream 转换无状态转化操作Transformjoin有状态转化操作UpdateStateByKeyWindowOperationsDStream 输出优雅关闭…

pip命令安装torchnet包,超简单!

pip命令安装torchnet包,超简单! torchnet是torch的框架,它提供了一组抽象,旨在鼓励代码重用以及鼓励模块化编程。 目前,torchnet提供了四组重要的类: Dataset:以各种方式处理和预处理数据。 …

Typora入门教程

文章目录Typora入门教程1 简要介绍2 下载安装包3 常用操作3.1 标题3.2 加粗3.3 斜体3.4 高亮3.5 分割线3.6 图片3.7 链接3.8 引用3.9 列表3.10 目录3.11 表格3.12 代码块3.13 行内代码3.14 按键效果4 自定义快捷键5 Typora PicGo 阿里云OSS搭建个人笔记5.1 注意事项5.2 准备工…

Hibernate学习总结

文章目录一、图解运行过程二、核心代码三、session方法2、session缓存3、save()与persist()4、get()5、update()6、delete()7、evict()8、doWork(),可获得connection对象四、hibernate.cfg.xml(使用数据库连接池)五、*…