分析Java中为什么String不可变

 更新时间:2021年06月07日 08:51:42   作者:烟花散尽13141  
Java中为什么String是不可变性的。今天我们从多角度解析为什么Java把String做成不可变的。

常量池

Java中我们创建String对象有两种基本方法。

String str1 = "zxhtom";
String str2 = new String("zxhtom");

上面两种方式我们创建了两个String变量 。 但是第一种通过双引号创建的zxhtom这个对象我们称之为常量 。 在JVM中是存储在一块叫【常量池】中的。而第二种str2是我们称之为普通变量。new一次就在JVM中开辟一块内存。

【常量池】的作用就是复用,当同样的内容再次被通过常量方式创建的时候Java会指向同一块地址。通过如下代码理解:

String z1 = "zxhtom";
String z2 = "zxhtom";

通过上图我们可以了解 z1 , z2两个变量其实引用的是同一内存地址 。 所以z1==z2 为true .

到这里引发出为什么String被设计为不可变 。 上列中z1 被修改成zxh . 如果String是可变得那么z2就会被莫名其妙修改成zxh .

便利

在Java中判断两个对象相等时通过地址判断。但是地址被抽象话为一段hash函数。在Java使用中hash是经常被使用的。将String设置为不可变性那么hash就可以一直使用下去。不需要重新计算体现了便捷性

安全

仍是上面的情况 , z2会被不知情的情况下被修改了。这在多线程中很常见。我们在使用的时候会被其他情况将数据更改。这样我们的数据将会失去了准确性。

引申问题

在上部中我们提到String的常量池。针对常量池引发思考 【String.intern()】

该方法的功能就是扩充【常量池】。z2.intern() 表示判断常量池中是否存在与该值相同的对象如果有则返回该对象的引用。 如果没有则将该值注册到内存中。注意这里并不是将z2对象注册过去。而是将z2的值注册进去。

String z1=new String("zxhtom");
String z2=z1.intern();
System.out.println( z1==z1.intern() );
System.out.println( z1.hashCode()+" "+z2.hashCode() );
System.out.println( z2==z1 );
System.out.println( z2==z1.intern() );

输出结构

false

-688175064 -688175064

false

true

分析一下输出结果不难发现,z1.intern()是常量池中没有zxhtom,会将zxhtom值创建到常量池中,z2就是引用常量池中的引用。这个时候z1==z2 为false说明注册到常量池中的并不是z1的地址,而是相当于z1的一个对象拷贝。

string创建方式的确定简单归结:

  • 通过双引号创建的 == 常量创建
  • 通过常量拼接 == 常量创建
  • 通过非常量与常量拼接 = 非常量创建
  • 通过new 创建 == 非常量创建

String在Java中的【引用传递】

在Java中方法参数传递都是通过值传递的。但是为什么String给我们的感觉是引用传递的呢?

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";
}

String不是基本对象所以String是引用传递。但是这里的引用传递知识传递String引用的地址 .当执行x=cd是原来ab的对象还在JVM中。外部x的引用地址没有变 。 变得知识change方法中x的指向。所以外部打印的还是ab

以上就是分析Java中为什么String不可变的详细内容,更多关于Java中为什么String不可变的资料请关注脚本之家其它相关文章!

相关文章

  • 使用JPA支持多参数列表查询(参数可能为空)

    使用JPA支持多参数列表查询(参数可能为空)

    这篇文章主要介绍了使用JPA支持多参数列表查询(参数可能为空),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05
  • SpringBoot配置主从数据库实现读写分离

    SpringBoot配置主从数据库实现读写分离

    现在的 Web 应用大都是读多写少,本文主要介绍了SpringBoot配置主从数据库实现读写分离,具有一定的参考价值,感兴趣的可以了解一下
    2023-11-11
  • SpringBoot入门原理及优势分析

    SpringBoot入门原理及优势分析

    本篇文章主要来为大家介绍SpringBoot入门原理及优势分析,有需要的朋友可以借鉴参考下,希望可以有所帮助,祝大家多多进步,早日升职加薪
    2021-09-09
  • java中数组list map三者之间的互转介绍

    java中数组list map三者之间的互转介绍

    java中 数组 list map之间的互转一张图清晰呈现并附有代码,不懂的朋友可以参考下
    2013-10-10
  • 关于弱引用WeakReference所引用的对象的回收规则

    关于弱引用WeakReference所引用的对象的回收规则

    这篇文章主要介绍了关于弱引用WeakReference所引用的对象的回收规则,如果一个弱引用实例的成员变量referent引用了一个对象obj,那么就称这个弱引用实例对obj的引用是弱引用,被一个弱引用实例引用的对象,称为弱引用对象,需要的朋友可以参考下
    2023-09-09
  • Java中Prime算法的原理与实现详解

    Java中Prime算法的原理与实现详解

    Prime算法是一种穷举查找算法来从一个连通图中构造一棵最小生成树。本文主要为大家介绍了Java中Prime算法的原理与实现,感兴趣的可以学习一下
    2022-07-07
  • TransmittableThreadLocal线程间传递逻辑示例解析

    TransmittableThreadLocal线程间传递逻辑示例解析

    这篇文章主要介绍了TransmittableThreadLocal线程间传递逻辑示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-06-06
  • 老生常谈spring的事务传播机制

    老生常谈spring的事务传播机制

    这篇文章主要介绍了spring的事务传播机制,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • java多线程volatile内存语义解析

    java多线程volatile内存语义解析

    这篇文章主要介绍了java多线程volatile内存语义解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-01-01
  • idea打不开项目问题的解决过程(典型案例)

    idea打不开项目问题的解决过程(典型案例)

    idea导入项目,起环境的时候经常会碰到项目环境起不来的情况,下面这篇文章主要介绍了idea打不开项目问题的解决过程,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2023-05-05

最新评论