JAVA性能优化(笔记篇)

一、编程优化

 

1、字符串优化

String字符串是开发中使用最频繁,也是最容易忽略的性能委托。高效使用字符串可以提升系统整体性能

String 类被 final 关键字修饰了,而且变量 char 数组也被 final 修饰了。我们知道类被 final 修饰代表该类不可继承,而 char[]被 final+private 修饰,代表了 String 对象不可被更改。Java 实现的这个特性叫作 String 对象的不可变性,即 String 对象一旦创建成功,就不能再对它进行改变。这样做的好处是:

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

第二,保证hash属性值不会频繁变更,确保了唯一性,是的类似HashMap容器才能实现对应的key-value缓存功能。

第三,可以实现字符串常量池。

在java中,通常有两种创建字符串方式:

一是通过字符串常量方式,如String str = “abc”,这种方式JVM首先会检查对象是否在字符串常量池中,如果在就返回引用,否则创建新的字符串常量在常量池中,这种方式可以减少同一个值的字符串对象的重复创建,节省内存;

二是字符变量通过new方式创建,如String str = new String(“abc”)。这种方式,首先在编译类文件时,“abc”常量字符串将会放入到常量结构中,在类加载时,“abc”将会在常量池中创建,同时引用常量池中的“abc”字符串,在堆中创建一个String对象,最后str引用堆中的String对象。

就以下代码,输出结果为例


String str1= "abc";
String str2= new String("abc");
String str3= str2.intern();
assertSame(str1==str2);
assertSame(str2==str3);
assertSame(str1==str3)

str1首先会在常量池中创建“abc”字符串,自己为指向字符串的引用;

str2使用的new,则在堆中创建一个内存,内存指向常量池中的字符串,自己为指向堆中的内存的引用;

str3使用的str2的intern方法,返回的是常量池中的引用;

所以说str1 == str3 != str2

如何使用String.intern节省内存?了解了上面,再看字符串的储存问题。

使用String.intern来节省内存空间,从而优化String对象的存储,具体做法就是在每次赋值时使用String的intern方法,如果常量池中有相同值,就会重复使用该对象,返回对象引用。这样一开始的对象就可以被回收掉,使得字符串存储大小降低。看如下


String a =new String("abc").intern();
String b = new String("abc").intern();
        
if(a==b) {
    System.out.print("a==b");
}

结果显而易见:会输出a==b

在字符串常量中,默认会将对象放入常量池;在字符串变量中,对象是会创建在堆内存中,同时会在常量池中创建一个字符串对象,String对象中的char数组将会引用常量池中的char数组,并返回堆内存对象引用。

如果调用intern方法,会去查看字符串常量池中是否有等于该对象的引用,如果没有,在jdk.6中会复制堆中的字符串到常量池中,并返回该字符串引用,堆内存中原有的字符串由于没有引用指向它,会被GC。在jdk1.7版本以后,由于字符串常量池(根据我翻阅的资料来看,运行时常量池依然在方法区)已经合并到堆中所以不会在复制具体字符串,只是把首次遇到的字符串的引用添加到常量池中;如果有,就返回常量池中的字符串引用。

再看上面的例子,创建a和b两个字符串调用了new方法,都会在堆中创建一个String对象,String对象中的char数组将会引用常量池中的字符串。调用intern方法后,会去常量池查找有没有相等的字符串,有就返回引用;没有jdk1.6就把堆中的字符串复制到字符串常量池,因为堆中的字符串没有引用了,下次gc就会被回收; jdk1.7就把堆中字符串的引用放入字符串常量池,并且返回常量池中的引用,这个引用和new方法创建的在堆中字符串的引用是同一个!!!用下图表示:

另外使用intern方法还有注意的一点是:要结合实际场景,因为常量池的实现时类似于一个HashTable,存储的数据量越大,遍历的性能就越差,会增加整个字符串常量池的负担。

此外,字符串的分割方法使用不当也会导致性能下降,Split()方法使用了正则表达式实现了其强大的分割功能,但是正则表达式性能非常不稳定,使用不恰当会导致性能的下降。所以慎重使用Split方法,使用indexof来替代完成字符串的分割。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值