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() 方法
<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 文档的详解资料太全面,细节内容实在太多啦,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!
评论