日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

构造函数 构造代码块_构造函数必须没有代码

發布時間:2023/12/3 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 构造函数 构造代码块_构造函数必须没有代码 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

構造函數 構造代碼塊

構造函數中應完成多少工作? 在構造函數內部進行一些計算然后封裝結果似乎是合理的。 這樣,當對象方法需要結果時,我們將準備好它們。 聽起來是個好方法? 不,這不對。 這是一個壞主意,原因有一個:它阻止了對象的組合并使它們不可擴展。

殺死比爾 2(2004)由昆汀·塔倫蒂諾(Quentin Tarantino)

假設我們正在制作一個代表一個人的名字的接口:

interface Name {String first(); }

很簡單,對不對? 現在,讓我們嘗試實現它:

public final class EnglishName implements Name {private final String name;public EnglishName(final CharSequence text) {this.parts = text.toString().split(" ", 2)[0];}@Overridepublic String first() {return this.name;} }

這怎么了 更快吧? 它僅將名稱分成幾部分,然后將其封裝。 然后,無論我們調用first()方法有多少次,它都將返回相同的值,并且無需再次進行拆分。 但是,這是有缺陷的想法! 讓我向您展示正確的方法并說明:

public final class EnglishName implements Name {private final CharSequence text;public EnglishName(final CharSequence txt) {this.text = txt;}@Overridepublic String first() {return this.text.toString().split("", 2)[0];} }

這是正確的設計。 我可以看到你在微笑,所以讓我證明我的觀點。

不過,在開始證明之前,請允許我閱讀這篇文章: 可組合裝飾器與命令式實用方法 。 它解釋了靜態方法和可組合裝飾器之間的區別。 上面的第一個代碼段看起來非常像一個對象,它非常接近命令式實用程序方法。 第二個例子是一個真實的對象。

在第一個示例中,我們正在濫用new運算符,并將其轉換為靜態方法,該方法現在和現在都為我們進行所有計算。 這就是命令式編程的目的。 在命令式編程中,我們立即執行所有計算并返回完全準備好的結果。 相反,在聲明式編程中,我們嘗試盡可能長時間地延遲計算。

讓我們嘗試使用我們的EnglishName類:

final Name name = new EnglishName(new NameInPostgreSQL(/*...*/) ); if (/* something goes wrong */) {throw new IllegalStateException(String.format("Hi, %s, we can't proceed with your application",name.first())); }

在此代碼段的第一行中,我們只是創建一個對象的實例并將其標記為name 。 我們還不想進入數據庫并從那里獲取全名,將其拆分為多個部分,然后將其封裝在name 。 我們只想創建一個對象的實例。 這種解析行為對我們來說將是一個副作用,在這種情況下,將減慢應用程序的速度。 如您所見,如果出現問題,我們可能只需要name.first() ,而我們需要構造一個異常對象。

我的觀點是,在構造函數內部進行任何計算都是一種不好的做法,必須避免這樣做,因為它們是副作用,對象所有者不要求這樣做。

您可能會問,重用name期間的性能如何? 如果我們創建了EnglishName的實例,然后調用了name.first()五次,則最終將對String.split()方法進行五次調用。

為了解決這個問題,我們創建了另一個類,一個可組合的decorator ,它將幫助我們解決這個“重用”問題:

public final class CachedName implements Name {private final Name origin;public CachedName(final Name name) {this.origin = name;}@Override@Cacheable(forever = true)public String first() {return this.origin.first();} }

我正在使用jcabi-aspects的Cacheable批注,但是您可以使用Java(或其他語言)可用的任何其他緩存工具,例如Guava Cache :

public final class CachedName implements Name {private final Cache<Long, String> cache =CacheBuilder.newBuilder().build();private final Name origin;public CachedName(final Name name) {this.origin = name;}@Overridepublic String first() {return this.cache.get(1L,new Callable<String>() {@Overridepublic String call() {return CachedName.this.origin.first();}});} }

但是請不要使CachedName可變并且延遲加載-這是一種反模式,我之前在“ 對象應該是不可變的”中已經討論過。

這是我們的代碼現在的樣子:

final Name name = new CachedName(new EnglishName(new NameInPostgreSQL(/*...*/)) );

這是一個非常原始的示例,但我希望您能理解。

在此設計中,我們基本上將對象分為兩部分。 第一個知道如何從英文名稱中獲取名字。 第二個知道如何將計算結果緩存到內存中。 現在,作為這些類的用戶,我將決定如何正確使用它們。 我將決定是否需要緩存。 這就是對象構成的全部內容。

讓我重申一下,構造函數中唯一允許的語句是賦值。 如果您需要在此處放置其他內容,請開始考慮進行重構-您的課程肯定需要重新設計。

翻譯自: https://www.javacodegeeks.com/2015/05/constructors-must-be-code-free.html

構造函數 構造代碼塊

總結

以上是生活随笔為你收集整理的构造函数 构造代码块_构造函数必须没有代码的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。