半夜思考,为什么 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 容器负责 ...
随机推荐
- [NOI2016]区间 线段树
[NOI2016]区间 LG传送门 考虑到这题的代价是最长边减最短边,可以先把边按长度排个序,双指针维护一个尺取的过程,如果存在包含某个点的区间数\(\ge m\),就更新答案并把左指针右移,这样做的 ...
- Quartz动态添加,修改,删除任务(暂停,任务状态,恢复,最近触发时间)
首页 博客 学院 下载 图文课 论坛 APP 问答 商城 VIP会员 活动 招聘 ITeye GitChat 写博客 小程序 消息 登录注册 关闭 quartz_Cron表达式一分钟教程 09-05 ...
- 洛咕 P3645 [APIO2015]雅加达的摩天楼
暴力连边可以每个bi向i+kdi连边权是k的边. 考虑这样的优化: 然后发现显然是不行的,因为可能还没有走到一个dog的建筑物就走了这个dog的边. 然后就有一个很妙的方法--建一个新的图,和原图分开 ...
- Distributed3:SQL Server 分布式数据库性能测试
我在三台安装SQL Server 2012的服务器上搭建分布式数据库,把产品环境中一年近1.4亿条数据大致均匀地存储在这三台服务器中,每台Server 存储4个月的数据,物理机的系统配置基本相同:内存 ...
- fortran shapefile学习
试图编写一个fortran程序,用以判断给定的点是否落在给定shapefile的范围内. 需要利用到FortranGIS库 ,而该库又依赖于Shapefile C Library 安装shapelib ...
- 2.深入解析数据类型与变量——《Excel VBA 程序开发自学宝典》
2.1 数据类型 数据类型 所占字节 Byte 1 Boolean 2 Integer 2 Long 4 Single 4 Double 8 Currency 8 Decimal 14 Date 8 ...
- Docker容器的启动与停止
启动docker:systemctl start docker 停止docker:systemctl stop docker 重启docker:systemctl restart docker 查看d ...
- [Paper Reading] Image Captioning using Deep Neural Architectures (arXiv: 1801.05568v1)
Main Contributions: A brief introduction about two different methods (retrieval based method and gen ...
- Java多线程编程之不可变对象模式
在多线程环境中,为了保证共享数据的一致性,往往需要对共享数据的使用进行加锁,但是加锁操作本身就会带来一定的开销,这里可以使用将共享数据使用不可变对象进行封装,从而避免加锁操作. 1. 模 ...
- Nginx是如何配置为 Web 服务器的【转载】
详解 Nginx是如何配置为 Web 服务器的 林涛 发表于:2016-11-29 23:23 分类:WebServer 标签:Nginx,web,web服务器 521次 抽象来说,将 Nginx 配 ...

