Effective Java代碼規則之六:避免創建不必要的對象

  • 解釋

通常適合重用單個對象,而不是每次需要時創建一個新的功能等效對象。 重複使用可以更快,更優雅。 如果一個對象是不可變的,那麼它總是可以被重用:

1、String對象的重用

 //使用new創建String對象,JVM首先在字符串池中查找有沒有"hello"這個字符串對象,如果沒有,則首先在池中創建一個"hello"字符串對象,有就不創建,然後再在堆中創建一個"hello"字符串對象,然後將堆中對象的地址返回賦給s1引用,這樣,s1指向了堆中創建的這個"hello"字符串對象。
String s1 = new String("hello");

//使用=創建String對象,JVM首先會去字符串池中查找是否存在"hello"這個對象,如果不存在,則在池中創建"hello"這個對象,然後將引用地址返回給"hello"對象的引用s2,這樣s2會指向池中"hello"這個字符串對象;如果存在,則不創建任何對象,直接將池中"hello"這個對象的地址返回,賦給引用s2。
String s2 = "hello";
//使用intern方法創建String對象,如果字符串池已經包含一個等於此String對象的字符串,則返回池中的字符串。否則,將此String對象添加到池中,並返回此String對象的引用。
String s3 = s1.intern();
//使用字符串常量相加創建String對象,如果字符串池已經包含一個等於此String對象的字符串,則返回池中的字符串。否則,將此String對象添加到池中,並返回此String對象的引用。

String s4 = "he"+"llo";

//使用StringBuilder或StringBuffer創建時,等同於new創建String對象
String s5 = new StringBuilder().append("hello").toString();

//當加號的一邊是引用時,等同於使用StringBuilder或StringBuffer創建String對象
String s6 = new String("he") + "llo";

System.out.println(s1==s2);//false
System.out.println(s2==s3);//true
System.out.println(s2==s4);//true
System.out.println(s2==s5);//false
System.out.println(s2==s6);//false

由上述可見,如果用重用String對象,必須要使用“=”或intern或字符串常量相加的方法創建。

2、八大基本類型包裝類的重用

Integer、Short、Long、Byte、Float、Double、Boolean和Charater,儘量使用valueOf創建對象。例如:

 //創建一個新的Integer對象
Integer i1 = new Integer(10);

//返回表示指定int值的Integer實例,此方法將始終緩存範圍內的值-128到127
Integer i2 = Integer.valueOf(10);

Integer i3 = 10;

Integer i4 = new Integer(5)+5;

System.out.println(i1==i2);//false
System.out.println(i3==i2);//true
System.out.println(i4==i2);//true

3、緩存創建成本昂貴的對象

有些對象創建的成本比其他對象要高得多。如果重複地需要這類“昂貴的對象”,建議將它緩存下來重用,例如:

private static final Pattern ROMAN = Pattern
.compile("^(?=.)M*(C[MD]|D?C{0,3})" + "(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");
boolean isRomanNumeral(String s) {
return ROMAN.matcher(s).matches();
}

Pattern對象的創建成本很高,需要緩存,這樣使得isRomanNumeral方法的效率提升很多。

4、儘量使用基本類型而不是裝箱基本類型

每次自動裝箱(autoboxing)都會產生一個多餘的對象。

  • 優點1:更快,更優雅

避免創建不必要的對象,使代碼性能更好,也更優雅。

  • 缺點1:盲目避免創建對象是不可取的

我們應該把目光集中在那些創建成本高的對象上,對於一些創建成本比較低的類,我們應該更重視代碼的簡潔和可維護性。

  • 最佳實踐

使用Spring框架時,bean的創建和銷燬是由Spring容器維護的,默認是單例,也就意味著,默認情況下bean都是一個實例,不會存在創建不必要的對象的問題,但是在使用JDK提供的不可變類時,我們要注意以上我們提出的重用方法,包括String、八大基本類型的包裝類、StringBuilder、BigDecimal等類的重用。

Effective Java代碼規則之六:避免創建不必要的對象

專業從事軟件研發工作多年,在軟件設計、開發、測試、研發管理等領域裡經驗豐富,感興趣的朋友可以關注我的頭條號,相信一定會有所收穫。

如果有軟件研發方面的問題,可以諮詢我。

謝謝!


分享到:


相關文章: