java String不可变对象,但StringBuffer是可变对象
什么是不可变对象?
众所周知, 在Java中, String类是不可变的。那么到底什么是不可变的对象呢? 可以这样认为:如果一个对象,在它创建完成之后,不能再改变它的状态,那么这个对象就是不可变的。不能改变状态的意思是,不能改变对象内的成员变量,包括基本数据类型的值不能改变,引用类型的变量不能指向其他的对象,引用类型指向的对象的状态也不能改变。
区分对象和对象的引用
- String s = "ABCabc";
- System.out.println("s = " + s);
- s = "123456";
- System.out.println("s = " + s);
打印结果为:
s = 123456
为什么String对象是不可变的?
- public final class String
- implements java.io.Serializable, Comparable<String>, CharSequence
- {
- /** The value is used for character storage. */
- private final char value[];
- /** The offset is the first index of the storage that is used. */
- private final int offset;
- /** The count is the number of characters in the String. */
- private final int count;
- /** Cache the hash code for the string */
- private int hash; // Default to 0
在JDK1.7中,String类做了一些改动,主要是改变了substring方法执行时的行为,这和本文的主题不相关。JDK1.7中String类的主要成员变量就剩下了两个:
- public final class String
- implements java.io.Serializable, Comparable<String>, CharSequence {
- /** The value is used for character storage. */
- private final char value[];
- /** Cache the hash code for the string */
- private int hash; // Default to 0
由以上的代码可以看出, 在Java中String类其实就是对字符数组的封装。JDK6中, value是String封装的数组,offset是String在这个value数组中的起始位置,count是String所占的字符的个数。在JDK7中,只有一个value变量,也就是value中的所有字符都是属于String这个对象的。这个改变不影响本文的讨论。 除此之外还有一个hash成员变量,是该String对象的哈希值的缓存,这个成员变量也和本文的讨论无关。在Java中,数组也是对象(可以参考我之前的文章java中数组的特性)。 所以value也只是一个引用,它指向一个真正的数组对象。其实执行了String s = “ABCabc”; 这句代码之后,真正的内存布局应该是这样的:
- String a = "ABCabc";
- System.out.println("a = " + a);
- a = a.replace('A', 'a');
- System.out.println("a = " + a);
打印结果为:
a = aBCabc
- String ss = "123456";
- System.out.println("ss = " + ss);
- ss.replace('1', '0');
- System.out.println("ss = " + ss);
打印结果:
ss = 123456
String对象真的不可变吗?
- public static void testReflection() throws Exception {
- //创建字符串"Hello World", 并赋给引用s
- String s = "Hello World";
- System.out.println("s = " + s); //Hello World
- //获取String类中的value字段
- Field valueFieldOfString = String.class.getDeclaredField("value");
- //改变value属性的访问权限
- valueFieldOfString.setAccessible(true);
- //获取s对象上的value属性的值
- char[] value = (char[]) valueFieldOfString.get(s);
- //改变value所引用的数组中的第5个字符
- value[5] = '_';
- System.out.println("s = " + s); //Hello_World
- }
打印结果为:
s = Hello_World
java String不可变对象,但StringBuffer是可变对象的更多相关文章
- JAVA String、StringBuilder、和StringBuffer的区别,及如何使用
目录 String类 一.String类的理解和创建对象 二.String类创建的方式 两种创建String对象的区别 测试题 三.String常用方法 四.StringBuffer类 1.Strin ...
- Java String, StringBuffer和StringBuilder实例
1- 分层继承2- 可变和不可变的概念3- String3.1- 字符串是一个非常特殊的类3.2- String 字面值 vs. String对象3.3- String的方法3.3.1- length ...
- Java学习之String对象为什么是不可变的
转自:http://www.2cto.com/kf/201401/272974.html,感谢作者的总结 什么是不可变对象? 众所周知, 在Java中, String类是不可变的.那么到底什么是不可变 ...
- Java String StringBuffer StringBuilder
String 字符串常量存储在常量区,每次追加操作会创建新的对象: StringBuffer 字符串变量 线程安全 在堆上创建,每次追加操作在原对象上进行操作: 速度 StringBuffer ...
- 关于Java String对象创建的几点疑问
我们通过JDK源码会知道String实质是字符数组,而且是不可被继承(final)和具有不可变性(immutable).可以如果想要了解String的创建我们需要先了解下JVM的内存结构. 1.JVM ...
- Java——String对象
前言 实际上任何语言都没有提供字符串这个概念,而是使用字符数组来描述字符串.Java里面严格来说也是没有字符串的,在所有的开发里面字符串的应用有很多,于是Java为了应对便创建了String类这个字符 ...
- 【转载】关于Java String, StringBuilder, StringBuffer, Hashtable, HashMap的面试题
REF: http://blog.csdn.net/fightforyourdream/article/details/15333405 题目是一道简单的小程序,像下面这样:[java] view p ...
- java String,StringBuilder和StringBuffer
String:1.java语言中的字符串值属于String类,虽然有其它方法表示字符串(如字符数组),但java一般使用Sting类作为字符串的标准格式,java编译器把字符串值作为String对象. ...
- Java String、StringBuilder和StringBuffer
转载: Java String.StringBuilder和StringBuffer 概览 在Android/Java开发中,用来处理字符串常用的类有3种: String.StringBuilder. ...
随机推荐
- FireFox站点标识按钮
Firefox 的站点标识按钮可以为您提供有关您访问的网站的详细信息.通过站点标识按钮,您可以了解到站点的加密信息.验证信息.网站所有者和网站验证者.这有助于避免恶意网站获得您的重要信息. 站点标识按 ...
- 【python问题系列--4】ValueError: operands could not be broadcast together with shapes (100,3) (3,1)
背景:dataMatrix是(100,3)的列表,labelMat是(1,100)的列表,weights是(3,1)的数组,属性如下代码所示: >>> import types> ...
- Thrift源码解析--transport
这一层主要是用于实现网络通信,现在都是基于Tcp/Ip,而Tcp/Ip协议栈由socket来实现,换句话说就是现在网络通信服务底层大都是通过socket实现的,在thrift源码中,就是将socket ...
- pur-ftpd在ubuntu上的安装2(数据库管理)
1.安装mysql数据库支持的pure-ftpd apt-get install pure-ftpd-mysql 2.添加分组"ftpgroup",并且添加分组虚拟用户" ...
- win 8.1_64 安装usb 转串口驱动
前几天交换机出问题了,想着通过配置口进去看看,用笔记本连接一看. 我去,系统居然自动安装的驱动居然无法使用. 没办法新买的笔记本没几天,也没去装usb转com口的驱动.反正系统可以自己去装嘛.(其实是 ...
- 在Dll中创建对话框并调用
1.第一步创建一“MFC AppWizard (dll)”工程,接下来选择“Regular Dll using shared MFC DLL”,点击“Finish”. 2.添加一对话框资源到工程中,从 ...
- hdu_2227_Find the nondecreasing subsequences_树状数组,离散化
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2227 题意:给你一个集合,让你求递增子序列有多少个,和树状数组求逆序对差不多,不过数据比较大,要离散化 ...
- form异步无刷新提交,提交后可以显示弹出框,否则弹出框会被刷新不见,使用 preventDefault
出错点:确认按钮上.加onclick事件.每次点击都会追加给form追加on监听方法.累加on方法,重复提交 suppress_exception:true 阻止异常 (百度推送 jdk) 向下按 p ...
- 读书有感——《从毕业生到程序员使用C#开发商业软件》
本来想自己写个读书感悟之类的东西,但是苦于自己语文水平太差,算了,我把里面觉得很赞的内容摘抄下来就好了(学习都是从模仿开始的嘛). 书籍:<从毕业生到程序猿使用C#开发商业软件> 作者:袁 ...
- 15分钟快速开发一个kissy组件(流程篇)
Step1: 安装kissy gallery组件工具 npm install yo grunt-cli -g npm install generator-kissy-gallery -g 请确保本地带 ...