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

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() 方法
  • 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.

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);

架构学习资料

准备两个月,面试五分钟,Java中高级岗面试为何越来越难?

准备两个月,面试五分钟,Java中高级岗面试为何越来越难?

准备两个月,面试五分钟,Java中高级岗面试为何越来越难?

准备两个月,面试五分钟,Java中高级岗面试为何越来越难?

准备两个月,面试五分钟,Java中高级岗面试为何越来越难?

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值