半夜思考,为什么 String 具有不变性
学习 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 具有不变性的更多相关文章
- String的不变性到final在java中用法
final在Java语言里面啥意思 final修饰一个类,那么这个类就是不可继承.string就是一个非常有名的被final修饰的类,不过他的更加有名的是“不可被修改”. 究竟什么是不可改变?stri ...
- 半夜思考, 为什么建议重写 equals() 方法时, 也要重写 hashCode() 方法
我说的半夜, 并不是真正的半夜, 指的是在我一个人的时候, 我会去思考一些奇怪的问题. 要理解 hashCode() 需要理解下面三个点: hash契约 哈希冲突 哈希可变 第一点: hash 契约指 ...
- 通过String的不变性案例分析Java变量的可变性
阅读本文之前,请先看以下几个问题: 1.String变量是什么不变?final修饰变量时的不变性指的又是什么不变,是引用?还是内存地址?还是值? 2.java对象进行重赋值或者改变属性时在内存中是如何 ...
- 半夜思考, Java 重载的实现
因为最近在学 scala,看到了参数的默认值这个特性,但是Java好像没有这个特性, Java8 也没有, 所以特意去查了一下,就牵扯到了 C++了,[只怪 C++没怎么学,,]. 下面将一下为什么 ...
- 半夜思考之查漏补缺, Spring 的 Bean 后处理器
有一篇写的是容器后处理器, 这篇是 Bean 后处理器 , 我对这个 Bean 后处理器的理解就是一个 AOP 编程 . Bean 后处理器 : 是一种特殊的 Bean , 这种 Bean 不对外提供 ...
- 半夜思考之查漏补缺, Spring 中的容器后处理器
之前学 Spring 的时候 , 还没听过容器后处理器 , 但是一旦写出来 , 就会觉得似曾相识 . 容器配置器通常用于对 Spring 容器进行处理 , 并且总是在容器实例化任何其他 Bean 之前 ...
- 半夜思考之查漏补缺 , Spring 中 Bean 之间的依赖问题
每次看书都会发现自己的不足 . 当一个 singten 的 Bean 依赖一个 prototype 的 Bean 时 , 如果不加注意 , 会发生一些奇怪的事情 , prototype 变为了 sin ...
- 半夜思考之查漏补缺 , Spring 中的 Bean 继承机制
这里的继承 , 不是 Java 中的继承 , 下面就总结下 Bean继承与Java继承的区别: Spring 中的子类 Bean 和父 Bean 可以是不同类型 , 但是 Java 中的继承则可保证子 ...
- 半夜思考之查漏补缺, 在 Spring中, 所有的 bean 都是 Spring 创建的吗 ?
Spring 是一个 bean 容器, 负责 bean 的创建, 那么所有的 bean对象都是 Spring 容器创建的吗 ? 答案是否定的. 但是乍一想, 好像所有的对象都是 Spring 容器负责 ...
随机推荐
- Codeforces Round #452 (Div. 2)
第一次打..(太弱(+99积分是几个意思 A 题意:一堆数,只有1和2,问最多凑出多少个3. 分情况即可 #include<cstdio> int main(){ int a=0,b=0, ...
- jsp jstl 值空格拼接导致的异常
红线标记处多了个空格,所以出现值错误
- JAVAWEB dbutils执行sql命令并遍历结果集时不能查到内容的原因
遍历结果集时只遍历bean对象才会只输出第一行那种内容(第一行是输出了UserEntity类实例化的对象),所以这里需要 re.getRepoTableName() 才能通过对象调用相对应的内容 这样 ...
- 一款好看的Sublime Text浅色主题:Ayu大作
上一篇分享的VS Code的文中,界面也是浅色主题,也是Ayu作品.下面看一下Sublime Text中的Ayu浅色主题 不错吧. 如何下载? 首选项——插件控制——安装插件或者ctrl+shift+ ...
- mysql mtr写入数据
BEGIN; --disable_query_log --let $rows= 100 WHILE($rows) { --eval INSERT INTO t1 (a) VALUES ( $rows ...
- C++实现从一个文件夹中读出所有txt文件
前段时间做项目需要读取一个文件夹里面所有的txt文件,查询资料后得到以下实现方法:首先了解一下这个结构体struct _finddata_t { unsigned attrib; t ...
- Jenkins持续部署
Jenkins持续部署 Jenkins提供很好的连续部署和交付的支持.看一下部署任何软件开发的流程,将如下图所示. 连续部署的主要部分,是确保其上面所示的整个过程是自动化的.Jenkins实现所有这些 ...
- MapReduce 基础学习
什么是MapReduce? mapreduce 是一种软件框架 mapreduce job将任务分解为独立的块儿到不同的map task,进行并行处理: map任务输出会做相应的排序处理,并作为r ...
- static笔记
目录 1. static概括 2. static特点 1. 被static修饰的成员变量属于类,不属于这个类的某个对象. 2.被static修饰的成员可以并且建议通过类名直接访问 3. static注 ...
- hive的优化
hive.optimize.cp=true:列裁剪hive.optimize.prunner:分区裁剪hive.limit.optimize.enable=true:优化LIMIT n语句hive.l ...

