学习 Java 的数据类型时,特殊关照了 String 类型,具有不变性。

当时没有深入思考为什么 String 有不变性。而且我只碰到了 String 才有不变性。Java这样设计的缘由何在。

突然在想,为什么 Struts2 中的 action 的返回值为什么也是 String 类型的,不是其他类型,SpringMVC中 handle 也是返回的是 String 类型【ModelAndView 里面也包含了视图名的字符串形式,void就不提了,处理 AJAX 】。

下面就好好分析这个字符串不变性。

所谓不变性就是一旦创建一个字符串对象,这个字符串对象的内容就不会被改变了。比如:

package com.msym.test;

public class Test {
public void show() {
String str1 = "aaa";
String str2 = "aaa";
String str3 = new String("aaa");
System.out.println("str1的hashCode: " + str1.hashCode());
System.out.println("str2的hashCode: " + str2.hashCode());
System.out.println("str3的hashCode: " + str3.hashCode()); str1 = "aaa" + "b";
System.out.println("str1的hashCode: " + str1.hashCode());
System.out.println("str2的hashCode: " + str2.hashCode());
}
@org.junit.Test
public void test(){
show();
}
}

打印出来的结果说明,str1,str2,str3是指向同一块内存空间的,当修改了 str1时,就创建了一个新的字符串了。

上面创建 str1,str2,str3:

创建 str1 时,常量池里面肯定是没有常量“aaa”,所以会创建出一个,但是当创建 str2时,因为之前已经创建过  “aaa”了,所以会直接指向这个“aaa”;创建 str3 时,尽管使用了 new 关键字,但是还是会先去常量池去搜寻“aaa”,如果存在,就只在堆内存中开辟一段空间,用以存放常量池中“aaa”的地址,如果不存在,那么就先在常量池中创建“aaa”,然后在堆中开辟空间,存储常量池中“aaa”的地址。

下面画张图来说明:【其中的 0X1122 是常量池中“aaa”的地址头,】

而且 String 类的任何方法都不是去修改字符串的值,而是创建了一个新的字符串,原来的字符串如果没有被引用的话,会在一段时间内被 gc 掉,这样貌似看来,这个不变性并没有带来什么好处,反倒浪费了不少内存,但是这样的机制正好有了安全性,只要创建出一个 String 对象,只要他没有被 gc ,任何方法来读取这个对象都会是同一个,不会出现两个一样的,这也是为什么 String 类型在网络连接,数据传递,以及各大框架使用的这么频繁。

当然,如果只是想使用 String类的功能,有更好的选择,那就是线程安全的 StringBuffer和线程不安全的StringBuilder。

1

半夜思考,为什么 String 具有不变性的更多相关文章

  1. String的不变性到final在java中用法

    final在Java语言里面啥意思 final修饰一个类,那么这个类就是不可继承.string就是一个非常有名的被final修饰的类,不过他的更加有名的是“不可被修改”. 究竟什么是不可改变?stri ...

  2. 半夜思考, 为什么建议重写 equals() 方法时, 也要重写 hashCode() 方法

    我说的半夜, 并不是真正的半夜, 指的是在我一个人的时候, 我会去思考一些奇怪的问题. 要理解 hashCode() 需要理解下面三个点: hash契约 哈希冲突 哈希可变 第一点: hash 契约指 ...

  3. 通过String的不变性案例分析Java变量的可变性

    阅读本文之前,请先看以下几个问题: 1.String变量是什么不变?final修饰变量时的不变性指的又是什么不变,是引用?还是内存地址?还是值? 2.java对象进行重赋值或者改变属性时在内存中是如何 ...

  4. 半夜思考, Java 重载的实现

    因为最近在学 scala,看到了参数的默认值这个特性,但是Java好像没有这个特性, Java8 也没有, 所以特意去查了一下,就牵扯到了 C++了,[只怪 C++没怎么学,,]. 下面将一下为什么 ...

  5. 半夜思考之查漏补缺, Spring 的 Bean 后处理器

    有一篇写的是容器后处理器, 这篇是 Bean 后处理器 , 我对这个 Bean 后处理器的理解就是一个 AOP 编程 . Bean 后处理器 : 是一种特殊的 Bean , 这种 Bean 不对外提供 ...

  6. 半夜思考之查漏补缺, Spring 中的容器后处理器

    之前学 Spring 的时候 , 还没听过容器后处理器 , 但是一旦写出来 , 就会觉得似曾相识 . 容器配置器通常用于对 Spring 容器进行处理 , 并且总是在容器实例化任何其他 Bean 之前 ...

  7. 半夜思考之查漏补缺 , Spring 中 Bean 之间的依赖问题

    每次看书都会发现自己的不足 . 当一个 singten 的 Bean 依赖一个 prototype 的 Bean 时 , 如果不加注意 , 会发生一些奇怪的事情 , prototype 变为了 sin ...

  8. 半夜思考之查漏补缺 , Spring 中的 Bean 继承机制

    这里的继承 , 不是 Java 中的继承 , 下面就总结下 Bean继承与Java继承的区别: Spring 中的子类 Bean 和父 Bean 可以是不同类型 , 但是 Java 中的继承则可保证子 ...

  9. 半夜思考之查漏补缺, 在 Spring中, 所有的 bean 都是 Spring 创建的吗 ?

    Spring 是一个 bean 容器, 负责 bean 的创建, 那么所有的 bean对象都是 Spring 容器创建的吗 ? 答案是否定的. 但是乍一想, 好像所有的对象都是 Spring 容器负责 ...

随机推荐

  1. Codeforces 938 D. Buy a Ticket (dijkstra 求多元最短路)

    题目链接:Buy a Ticket 题意: 给出n个点m条边,每个点每条边都有各自的权值,对于每个点i,求一个任意j,使得2×d[i][j] + a[j]最小. 题解: 这题其实就是要我们求任意两点的 ...

  2. SQL Server 内存和换页(Paging)

    在进程开始执行时,进程首先申请虚拟地址空间VAS(Virtural Address Space),VAS是进程能够访问的地址空间,由于VAS不是真正的物理内存空间,操作系统必须将VAS隐射到物理内存空 ...

  3. Python爬虫入门 之 如何在豆瓣中获取自己喜欢的TOP N电影信息

    什么是爬虫 按照一定规则自动的获取互联网上的信息(如何快速有效的利用互联网上的大量信息) 爬虫的应用 搜索引擎(Google.百度.Bing等搜索引擎,辅助人们检索信息) 股票软件(爬取股票数据,帮助 ...

  4. ffmpeg 踩坑实录 添加实时水印(二)

    一.背景介绍 最近领导要求做一个视频录制的相关项目.其中,需要对视频文件进行添加 实时时间水印.于是,我想到了使用之前的ffmpeg来做. 二.ffmpeg实际操作 首先把需要添加水印的视频文件,上传 ...

  5. 简单字典实现(KV问题)

    搜索二叉树基本概念请看上篇博客 这两个问题都是典型的K(key)V(value)问题,我们用KV算法解决. 判断一个单词是否拼写正确:假设把所有单词都按照搜索树的性质插入到搜索二叉树中,我们判断一个单 ...

  6. cadence allegro16.6 pcb文件转pads pcb文件方法教程

    在pcb设计工作中,有时会被要求将pcb文件转成其他软件的格式,pcb Allegro装Pads的方法如下. 在转换的过程中我们需要用到三种软件,ad.pads.allegro.转换的流程是:alle ...

  7. PSR编码规范

    PSR-1 代码风格规范(1)常量命名:类中的常量所有字母都必须大写,单词间用下划线分隔(2)类命名:类的命名必须遵循 StudlyCaps 大写开头的驼峰命名规范(3)方法命名:方法名称必须符合 c ...

  8. 什么是REST,RESTful?

    转载自https://www.zhihu.com/question/28557115 https://blog.csdn.net/hjc1984117/article/details/77334616 ...

  9. 一切的浮点型进行计算操作都要用BigDecimal

    简化: 1.引言 float和double类型的主要设计目标是为了科学计算和工程计算.他们执行二进制浮点运算,这是为了在广域数值范围上提供较为精确的快速近似计算而精心设计的.然而,它们没有提供完全精确 ...

  10. Python的requests、greenlet和gevent模块在windows下安装

    一.requests模块在windows下安装 Linux系统下requests的安装方法在http://docs.python-requests.org/en/latest/user/install ...