| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> Java知识库 -> Java不要再问String为什么是不可变的! -> 正文阅读 |
|
[Java知识库]Java不要再问String为什么是不可变的! |
Java基础划重点整理
前言String 是一个特殊的对象,属于引用类型,一经创建初始化后不能更改,由于String 对象的不可变,所以可以共享。 定义从概念上讲,Java字符串就是Unicode字符序列。在标准Java类库中提供了一个预定义类String。String就是用双引号引起来的几个字符,每个用双引号括起来的字符串都是String类的一个实例:
String 对象是不可变的。查看 JDK 文档你就会发现,String 类中每一个看起来会修改 String 值的方法,实际上都是创建了一个全新的 String 对象,以包含修改后的字符串内容。而最初的 String 对象则丝毫未动。看看下面的代码:
输出:
当把 name 传递给 upcase() 方法时,实际传递的是引用的一个拷贝。其实,每当把 String 对象作为方法的参数时,都会复制一份引用,而该引用所指向的对象其实一直待在单一的物理位置上,从未动过。 回到 upcase() 的定义,传入其中的引用有了名字 s,只有 upcase() 运行的时候,局部引用 s 才存在。一旦 upcase() 运行结束,s 就消失了。当然了,upcase() 的返回值,其实是最终结果的引用。这足以说明,upcase() 返回的引用已经指向了一个新的对象,而 name 仍然在原来的位置。 对于一个方法而言,参数是为该方法提供信息的,而不是想让该方法改变自己的。在阅读这段代码时,读者自然会有这样的感觉。这一点很重要,正是有了这种保障,才使得代码易于编写和阅读。
String s=new String(“abc”);创建了两个对象 1,在字符串池中创建一个对象(此对象是不能重复的) 2,new 出一个对象。Java 运行环境有一个字符串池,由 String 类维护。执行语句 String s=“abc"时,首先查看字符串池中是否存在字符串"abc”,如果存在则直接将"abc"赋给 s,如果不存在则先在字符串池中新建一个字符串"abc",然后再将其赋给 s。执行语句 String s=new String(“abc”)时,不管字符串池中是否存在字符串"abc",直接新建一个字符串"abc"(注意:新建的字符串"abc"不是在字符串池中),然后将其付给 s。 重载String不可变性会带来一定的效率问题。为 String 对象重载的 + 操作符就是一个例子。重载的意思是,一个操作符在用于特定的类时,被赋予了特殊的意义。操作符 + 可以用来连接 String:
可以想象一下,这段代码是这样工作的:String 可能有一个 append() 方法,它会生成一个新的 String 对象,以包含“namge:”与 name 连接后的字符串。该对象会再创建另一个新的 String 对象,然后与“age:”相连,生成另一个新的对象,依此类推。 这种方式当然是可行的,但是为了生成最终的 String 对象,会产生一大堆需要垃圾回收的中间对象。我猜想,Java 设计者一开始就是这么做的(这也是软件设计中的一个教训:除非你用代码将系统实现,并让它运行起来,否则你无法真正了解它会有什么问题),然后他们发现其性能相当糟糕。 为了解决这个问题,在JDK5.0中引入 StringBuilder类。在这之前用的是 StringBuffer。后者是线程安全的,因此开销也会大些。使用 StringBuilder 进行字符串操作更快一点。如果需要用许多小段的字符串构建一个字符串,那么应该按照下列步骤进行。首先,构建一个空的字符串构建器:
当每次需要添加一部分内容时,就调用append方法。
在需要构建字符串时就调用toString方法,将可以得到一个String对象,其中包含了构建器中的字符序列。
StringBuilder 提供了丰富而全面的方法,包括 insert()、replace()、substring(),甚至还有reverse(),但是最常用的还是 append() 和 toString()。还有 delete()。 总结String 是只读字符串,它是一个对象。每次+操作隐式在堆上new了一个跟原来字符串相同的StringBuilder对象,在调用append方法拼接+后面的字符串。在使用过程中在细节上要注意效率问题,例如恰当地使用 StringBuilder 等。 我们都知道Java源自于C++,Java设计者认为C++允许编程人员任意重载操作符是一个很复杂的过程,所以没有纳入到Java中。然而就像现在看到的Python和C#,它们都有垃圾回收机制,操作符重载也简单易懂。所以说在Java中使用操作符重载也并非想象中那么复杂。这也是软件设计中的一个教训:除非你用代码将系统实现,并让它运行起来,否则你无法真正了解它会有什么问题。 希望Java越来越好用! 更多精品内容请扫描关注 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 | -2024/12/18 18:08:57- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |