写点什么

Java-String- 对象,你真的了解了吗?

  • 2022 年 4 月 20 日
  • 本文字数:1936 字

    阅读完需:约 6 分钟

private final char value[];


/** Cache the hash code for the string */private int hash; // Default to 0


/** use serialVersionUID from JDK 1.0.2 for interoperability */private static final long serialVersionUID = -6849794470754667710L;}


从这段源码中可以看出,String类用了 final 修饰符,我们知道当一个类被 final 修饰时,表明这个类不能被继承,所以String类不能被继承。这是String不可变的第一点


再往下看,用来存储字符串的char value[]数组被private?和final修饰,我们知道对于一个被final的基本数据类型的变量,则其数值一旦在初始化之后便不能更改。这是String不可变的第二点。


Java 公司为什么要将String设置成不可变的,主要从以下三方面考虑:


  • 1、保证 String 对象的安全性。假设 String 对象是可变的,那么 String 对象将可能被恶意修改。

  • 2、保证 hash 属性值不会频繁变更,确保了唯一性,使得类似 Java 开源项目【ali1024.coding.net/public/P7/Java/git】 HashMap 容器才能实现相应的 key-value 缓存功能。

  • 3、可以实现字符串常量池

String 对象的优化

字符串是我们常用的Java类型之一,所以对字符串的操作也是避免不了的,在对字符串的操作过程中,如果使用不当,性能会天差地别。那么在字符串的操作过程中,有哪些地方需要我们注意呢?

优雅的拼接字符串

字符串的拼接是对字符串操作使用最频繁的操作之一,由于我们知道String对象的不可变性,所以我们在做拼接时尽可能少的使用+进行字符串拼接或者说潜意识里认为不能使用+进行字符串拼接,认为使用+进行字符串拼接会产生许多无用的对象。事实真的是这样吗?我们来做一个实验。我们使用+来拼接下面这段字符串。


String str8 = "ping" +"tou"+"ge";


一起来分析一下这段代码会产生多少个对象?如果按照我们理解的意思来分析的话,首先会创建ping对象,然后创建pingtou对象,最后才会创建pingtouge对象,一共创建了三个对象。真的是这样吗?其实不是这样的,Java 公司怕我们程序员手误,所以对编译器进行了优化,上面的这段字符串拼接会被我们的编译器优化,优化成一个String str8 = "pingtouge";对象。除了对常量字符串拼接做了优化以外,对于使用+号动态拼接字符串,编译器也做了相应的优化,以便提升String的性能,例如下面这段代码:


String str = "pingtouge";


for(int i=0; i<1000; i++) {str = str + i;}


编译器会帮我们优化成这样


String str = "pingtouge";


for(int i=0; i<1000; i++) {str = (new StringBuilder(String.valueOf(str))).append(i).toString();}


可以看出 Java 公司对这一块进行了不少的优化,防止由于程序员不小心导致String性能急速下降,尽管 Java 公司在编译器这一块做了相应的优化,但是我们还是能看出 Java 公司优化的不足之处,在动态拼接字符串时,虽然使用了 StringBuilder 进行字符串拼接,但是每次循环都会生成一个新的 StringBuilder 实例,同样也会降低系统的性能。


所以我们在做字符串拼接时,我们需要从代码的层面进行优化,在动态的拼接字符串时,如果不涉及到线程安全的情况下,我们显示的使用 StringBuilder 进行拼接,提升系统性能,如果涉及到线程安全的话,我们使用 StringBuffer 来进行字符串拼接

巧妙的使用 intern() 方法

  • <p>

  • When the intern method is invoked, if the pool already contains a

  • string equal to this {@code String} object as determined by

  • the {@link #equals(Object)} method, then the string from the pool is

  • returned. Otherwise, this {@code String} object is added to the

  • pool and a reference to this {@code String} object is returned.

  • <p>public native String intern();


这是 intern() 函数的官方注释说明,大概意思就是 intern 函数用来返回常量池中的某字符串,如果常量池中已经存在该字符串,则直接返回常量池中该对象的引用。否则,在常量池中加入该对象,然后 返回引用。


有一位Twitter工程师在QCon全球软件开发大会上分享了一个他们对?String对象优化的案例,他们利用String.intern()方法将以前需要 20G 内存存储优化到只需要几百兆内存。这足以体现String.intern()的威力,我们一起来看一个例子,简单的了解一下String.intern()的用法。


public static void main(String[] args) {String str = new String("pingtouge");String str1 = new String("pingtouge");System.out.println("未使用 intern()方法:"+(str==str1) 《一线大厂 Java 面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》开源 );System.out.println("未使用 intern()方法,str:"+str);

架构学习资料






由于篇幅限制小编,pdf 文档的详解资料太全面,细节内容实在太多啦,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!

用户头像

还未添加个人签名 2022.04.13 加入

还未添加个人简介

评论

发布
暂无评论
Java-String-对象,你真的了解了吗?_Java_爱好编程进阶_InfoQ写作社区