IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: 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基础划重点整理

  1. Java万物皆对象,带你进入编程之旅!
  2. Java运算符,操纵数据全靠它!
  3. Java初始化和清理,控制安全是首要!
  4. Java封装是为了更好的重构!
  5. JavaOOP优雅总是会有回报!
  6. Java集合,日常开发掌握这些就够了
  7. Java不要再问String为什么是不可变的!

Java不要再问String为什么是不可变的!

前言

String 是一个特殊的对象,属于引用类型,一经创建初始化后不能更改,由于String 对象的不可变,所以可以共享。

定义

从概念上讲,Java字符串就是Unicode字符序列。在标准Java类库中提供了一个预定义类String。String就是用双引号引起来的几个字符,每个用双引号括起来的字符串都是String类的一个实例:

String s = "abc";

String 对象是不可变的。查看 JDK 文档你就会发现,String 类中每一个看起来会修改 String 值的方法,实际上都是创建了一个全新的 String 对象,以包含修改后的字符串内容。而最初的 String 对象则丝毫未动。看看下面的代码:

public class User {

    public static String upcase(String s){
        return s.toUpperCase();
    }

    public static void main(String[] args) {
        String name = "manoninsight";
        String name1 = upcase(name);
        System.out.println(name1);
        System.out.println(name);
    }
}

输出:

MANONINSIGHT
manoninsight

当把 name 传递给 upcase() 方法时,实际传递的是引用的一个拷贝。其实,每当把 String 对象作为方法的参数时,都会复制一份引用,而该引用所指向的对象其实一直待在单一的物理位置上,从未动过。

回到 upcase() 的定义,传入其中的引用有了名字 s,只有 upcase() 运行的时候,局部引用 s 才存在。一旦 upcase() 运行结束,s 就消失了。当然了,upcase() 的返回值,其实是最终结果的引用。这足以说明,upcase() 返回的引用已经指向了一个新的对象,而 name 仍然在原来的位置。

对于一个方法而言,参数是为该方法提供信息的,而不是想让该方法改变自己的。在阅读这段代码时,读者自然会有这样的感觉。这一点很重要,正是有了这种保障,才使得代码易于编写和阅读。

  1. 小细节:
    我们知道String是一个对象,然而我们前面说过对象的创建要通过new关键字创建,而我们在创建String时却写成:
    String s = “abc”;
    而非
    String s = new String(“abc”);

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:

    public static void main(String[] args) { 
        String name = "码农洞见"; 
        String age = 30;
        String s = "namge:" + name + "age:" + age; 
        System.out.println(s);
    } 

可以想象一下,这段代码是这样工作的:String 可能有一个 append() 方法,它会生成一个新的 String 对象,以包含“namge:”与 name 连接后的字符串。该对象会再创建另一个新的 String 对象,然后与“age:”相连,生成另一个新的对象,依此类推。

这种方式当然是可行的,但是为了生成最终的 String 对象,会产生一大堆需要垃圾回收的中间对象。我猜想,Java 设计者一开始就是这么做的(这也是软件设计中的一个教训:除非你用代码将系统实现,并让它运行起来,否则你无法真正了解它会有什么问题),然后他们发现其性能相当糟糕。

为了解决这个问题,在JDK5.0中引入 StringBuilder类。在这之前用的是 StringBuffer。后者是线程安全的,因此开销也会大些。使用 StringBuilder 进行字符串操作更快一点。如果需要用许多小段的字符串构建一个字符串,那么应该按照下列步骤进行。首先,构建一个空的字符串构建器:

 StringBuilder builder = new StringBuilder(); 

当每次需要添加一部分内容时,就调用append方法。

builder.append("abc");
builder.append("123");
...

在需要构建字符串时就调用toString方法,将可以得到一个String对象,其中包含了构建器中的字符序列。

String result = builder.toString();

StringBuilder 提供了丰富而全面的方法,包括 insert()、replace()、substring(),甚至还有reverse(),但是最常用的还是 append() 和 toString()。还有 delete()。

总结

String 是只读字符串,它是一个对象。每次+操作隐式在堆上new了一个跟原来字符串相同的StringBuilder对象,在调用append方法拼接+后面的字符串。在使用过程中在细节上要注意效率问题,例如恰当地使用 StringBuilder 等。

我们都知道Java源自于C++,Java设计者认为C++允许编程人员任意重载操作符是一个很复杂的过程,所以没有纳入到Java中。然而就像现在看到的Python和C#,它们都有垃圾回收机制,操作符重载也简单易懂。所以说在Java中使用操作符重载也并非想象中那么复杂。这也是软件设计中的一个教训:除非你用代码将系统实现,并让它运行起来,否则你无法真正了解它会有什么问题。

希望Java越来越好用!

更多精品内容请扫描关注
关注更多

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-07-13 17:19:45  更:2021-07-13 17:21:12 
 
开发: 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年5日历 -2024/5/2 7:48:51-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码