半夜思考,为什么 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 容器负责 ...
随机推荐
- ubuntu下编译源码 make 出现 make: 'Makefile' is up to date.
其实只需要 make就行了,不需要 make Makefile 当然,make的前提是,执行 ./configure 不报错
- springmvc框架开发常用的注解总结
1.@Controller使用:表示表现层中的JavaBean被spring容器管理. 2.@requestMapping使用: a) 在方法上: 标记url到请求方法的映射, 就相当于从一个ur ...
- SQL语句汇总(一)——数据库与表的操作以及创建约束
首先,非常感谢大家对上篇博文的支持,真是让本菜受宠若惊,同时对拖了这么久才出了此篇表示抱歉. 前言:此文旨在汇总从建立数据库到联接查询等绝大部分SQL语句.SQL语句虽不能说很多,但稍有时间不写就容易 ...
- async/await工作机制探究--NodeJS
ES6中的async/await让Promise变得更加简便,通常await处理的链式Promise会包裹在函数中,返回结果仍然是一个Promise对象. 但是当await直接处理链式Promise时 ...
- 【转】将Centos的yum源更换为国内的阿里云源
摘要: 阿里云是最近新出的一个镜像源.得益于阿里云的高速发展,这么大的需求,肯定会推出自己的镜像源. 阿里云Linux安装镜像源地址:http://mirrors.aliyun.com/ CentOS ...
- 工作之路---记录LZ如何在两年半的时间内升为PM
引言 之前的伪PM纠结之路已经渐渐结束,LZ也终于正式爬上了PM的位置,对于LZ来说,这个时间比LZ预计的早来了两年半.说起来,两年半的速度已经算是比较快了,但这之中的努力唯有LZ一人知晓.写这篇文章 ...
- Git使用教程(一)---本地git管理
之前写过不少小demo,因为没有很好的整理,很多demo都找不到了,必要的时候又要重新写这些demo:这是一个很头疼的问题,很烦躁.网上看到git的版本控制以及托管,很nice.开始学习使用git,关 ...
- VGGnet——从TFrecords制作到网络训练
作为一个小白中的小白,多折腾总是有好处的,看了入门书和往上一些教程,很多TF的教程都是从MNIST数据集入手教小白入TF的大门,都是直接import MNIST,然后直接构建网络,定义loss和opt ...
- [C++]模板类和模板函数
参考: C++ 中模板使用详解 C++模板详解 概念 为了避免因重载函数定义不全面而带来的调用错误,引入了模板机制 定义 模板是C++支持参数化多态的工具,使用模板可以使用户为类或者函数声明一种一般模 ...
- Ubuntu解压zip包中文乱码
解决方法:通过unar 工具解压 步骤一: 安装unar: sudo apt-get install unrar 步骤二: 解压(以test.zip为例):unar test.zip 解压成功,乱码问 ...