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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

后端:Java中如何更优雅的处理空值,看完你就懂了!

發布時間:2023/12/10 java 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 后端:Java中如何更优雅的处理空值,看完你就懂了! 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

導語

在筆者幾年的開發經驗中,經常看到項目中存在到處空值判斷的情況,這些判斷,會讓人覺得摸不著頭緒,它的出現很有可能和當前的業務邏輯并沒有關系。但它會讓你很頭疼。

有時候,更可怕的是系統因為這些空值的情況,會拋出空指針異常,導致業務系統發生問題。

此篇文章,我總結了幾種關于空值的處理手法,希望對讀者有幫助。

業務中的空值

場景

存在一個UserSearchService用來提供用戶查詢的功能:

public?interface?UserSearchService{??List<User>?listUser();??User?get(Integer?id);?? }??

問題現場

對于面向對象語言來講,抽象層級特別的重要。尤其是對接口的抽象,它在設計和開發中占很大的比重,我們在開發時希望盡量面向接口編程。

對于以上描述的接口方法來看,大概可以推斷出可能它包含了以下兩個含義:

  • listUser(): 查詢用戶列表

  • get(Integer id): 查詢單個用戶

在所有的開發中,XP推崇的TDD模式可以很好的引導我們對接口的定義,所以我們將TDD作為開發代碼的”推動者”。

對于以上的接口,當我們使用TDD進行測試用例先行時,發現了潛在的問題:

  • listUser() 如果沒有數據,那它是返回空集合還是null呢?

  • get(Integer id) 如果沒有這個對象,是拋異常還是返回null呢?

深入listUser研究

我們先來討論

listUser()??

這個接口,我經常看到如下實現:

public?List<User>?listUser(){??List<User>?userList?=?userListRepostity.selectByExample(new?UserExample());??if(CollectionUtils.isEmpty(userList)){//spring?util工具類??return?null;??}??return?userList;?? }??

這段代碼返回是null,從我多年的開發經驗來講,對于集合這樣返回值,最好不要返回null,因為如果返回了null,會給調用者帶來很多麻煩。你將會把這種調用風險交給調用者來控制。

如果調用者是一個謹慎的人,他會進行是否為null的條件判斷。如果他并非謹慎,或者他是一個面向接口編程的狂熱分子(當然,面向接口編程是正確的方向),他會按照自己的理解去調用接口,而不進行是否為null的條件判斷,如果這樣的話,是非常危險的,它很有可能出現空指針異常!

根據墨菲定律來判斷:?“很有可能出現的問題,在將來一定會出現!”

基于此,我們將它進行優化:

public?List<User>?listUser(){??List<User>?userList?=?userListRepostity.selectByExample(new?UserExample());??if(CollectionUtils.isEmpty(userList)){??return?Lists.newArrayList();//guava類庫提供的方式??}??return?userList;?? }??

對于接口(List listUser()),它一定會返回List,即使沒有數據,它仍然會返回List(集合中沒有任何元素);

通過以上的修改,我們成功的避免了有可能發生的空指針異常,這樣的寫法更安全!

深入研究get方法

對于接口

User?get(Integer?id)??

你能看到的現象是,我給出id,它一定會給我返回User.但事實真的很有可能不是這樣的。

我看到過的實現:

public?User?get(Integer?id){??return?userRepository.selectByPrimaryKey(id);//從數據庫中通過id直接獲取實體對象?? }??

相信很多人也都會這樣寫。

通過代碼的時候得知它的返回值很有可能是null! 但我們通過的接口是分辨不出來的!

這個是個非常危險的事情。尤其對于調用者來說!

我給出的建議是,需要在接口明明時補充文檔,比如對于異常的說明,使用注解@exception:

public?interface?UserSearchService{??/**??*?根據用戶id獲取用戶信息??*?@param?id?用戶id??*?@return?用戶實體??*?@exception?UserNotFoundException??*/??User?get(Integer?id);??}??

我們把接口定義加上了說明之后,調用者會看到,如果調用此接口,很有可能拋出“UserNotFoundException(找不到用戶)”這樣的異常。

這種方式可以在調用者調用接口的時候看到接口的定義,但是,這種方式是”弱提示”的!

如果調用者忽略了注釋,有可能就對業務系統產生了風險,這個風險有可能導致一個億!

除了以上這種”弱提示”的方式,還有一種方式是,返回值是有可能為空的。那要怎么辦呢?

我認為我們需要增加一個接口,用來描述這種場景.

引入jdk8的Optional,或者使用guava的Optional.看如下定義:

public?interface?UserSearchService{??/**??*?根據用戶id獲取用戶信息??*?@param?id?用戶id??*?@return?用戶實體,此實體有可能是缺省值??*/??Optional<User>?getOptional(Integer?id);?? }??

Optional有兩個含義: 存在 or 缺省。

那么通過閱讀接口getOptional(),我們可以很快的了解返回值的意圖,這個其實是我們想看到的,它去除了二義性。

它的實現可以寫成:

public?Optional<User>?getOptional(Integer?id){??return?Optional.ofNullable(userRepository.selectByPrimaryKey(id));?? }??

深入入參

通過上述的所有接口的描述,你能確定入參id一定是必傳的嗎?

我覺得答案應該是:不能確定。除非接口的文檔注釋上加以說明。

那如何約束入參呢?

我給大家推薦兩種方式:

  • 強制約束

  • 文檔性約束(弱提示)

1.強制約束,我們可以通過jsr 303進行嚴格的約束聲明:

public?interface?UserSearchService{??/**??*?根據用戶id獲取用戶信息??*?@param?id?用戶id??*?@return?用戶實體??*?@exception?UserNotFoundException??*/??User?get(@NotNull?Integer?id);??/**??*?根據用戶id獲取用戶信息??*?@param?id?用戶id??*?@return?用戶實體,此實體有可能是缺省值??*/??Optional<User>?getOptional(@NotNull?Integer?id);?? }??

當然,這樣寫,要配合AOP的操作進行驗證,但讓spring已經提供了很好的集成方案,在此我就不在贅述了。

2.文檔性約束

在很多時候,我們會遇到遺留代碼,對于遺留代碼,整體性改造的可能性很小。

我們更希望通過閱讀接口的實現,來進行接口的說明。

jsr 305規范,給了我們一個描述接口入參的一個方式(需要引入庫 com.google.code.findbugs:jsr305):

可以使用注解: @Nullable @Nonnull @CheckForNull 進行接口說明。

比如:

public?interface?UserSearchService{??/**??*?根據用戶id獲取用戶信息??*?@param?id?用戶id??*?@return?用戶實體??*?@exception?UserNotFoundException??*/??@CheckForNull??User?get(@NonNull?Integer?id);??/**??*?根據用戶id獲取用戶信息??*?@param?id?用戶id??*?@return?用戶實體,此實體有可能是缺省值??*/??Optional<User>?getOptional(@NonNull?Integer?id);?? }??

小結

通過 空集合返回值,Optional,jsr 303,jsr 305這幾種方式,可以讓我們的代碼可讀性更強,出錯率更低!

  • 空集合返回值 :如果有集合這樣返回值時,除非真的有說服自己的理由,否則,一定要返回空集合,而不是null

  • Optional: 如果你的代碼是jdk8,就引入它!如果不是,則使用Guava的Optional,或者升級jdk版本!它很大程度的能增加了接口的可讀性!

  • jsr 303: 如果新的項目正在開發,不防加上這個試試!一定有一種特別爽的感覺!

  • jsr 305: 如果老的項目在你的手上,你可以嘗試的加上這種文檔型注解,有助于你后期的重構,或者新功能增加了,對于老接口的理解!

空對象模式

場景

我們來看一個DTO轉化的場景,對象:

@Data?? static?class?PersonDTO{??private?String?dtoName;??private?String?dtoAge;?? }??@Data?? static?class?Person{??private?String?name;??private?String?age;?? }??

需求是將Person對象轉化成PersonDTO,然后進行返回。

當然對于實際操作來講,返回如果Person為空,將返回null,但是PersonDTO是不能返回null的(尤其Rest接口返回的這種DTO)。

在這里,我們只關注轉化操作,看如下代碼:

@Test?? public?void?shouldConvertDTO(){??PersonDTO?personDTO?=?new?PersonDTO();??Person?person?=?new?Person();??if(!Objects.isNull(person)){??personDTO.setDtoAge(person.getAge());??personDTO.setDtoName(person.getName());??}else{??personDTO.setDtoAge("");??personDTO.setDtoName("");??}?? }??

優化修改

這樣的數據轉化,我們認識可讀性非常差,每個字段的判斷,如果是空就設置為空字符串(“”)

換一種思維方式進行思考,我們是拿到Person這個類的數據,然后進行賦值操作(setXXX),其實是不關系Person的具體實現是誰的。

那我們可以創建一個Person子類:

static?class?NullPerson?extends?Person{??@Override??public?String?getAge()?{??return?"";??}??@Override??public?String?getName()?{??return?"";??}?? }??

它作為Person的一種特例而存在,如果當Person為空的時候,則返回一些get*的默認行為.

所以代碼可以修改為:

@Test??public?void?shouldConvertDTO(){??PersonDTO?personDTO?=?new?PersonDTO();??Person?person?=?getPerson();??personDTO.setDtoAge(person.getAge());??personDTO.setDtoName(person.getName());??}??private?Person?getPerson(){??return?new?NullPerson();//如果Person是null?,則返回空對象??}??

其中getPerson()方法,可以用來根據業務邏輯獲取Person有可能的對象(對當前例子來講,如果Person不存在,返回Person的的特例NUllPerson),如果修改成這樣,代碼的可讀性就會變的很強了。

使用Optional可以進行優化

空對象模式,它的弊端在于需要創建一個特例對象,但是如果特例的情況比較多,我們是不是需要創建多個特例對象呢,雖然我們也使用了面向對象的多態特性,

但是,業務的復雜性如果真的讓我們創建多個特例對象,我們還是要再三考慮一下這種模式,它可能會帶來代碼的復雜性。

對于上述代碼,還可以使用Optional進行優化。

@Test??public?void?shouldConvertDTO(){??PersonDTO?personDTO?=?new?PersonDTO();??Optional.ofNullable(getPerson()).ifPresent(person?->?{??personDTO.setDtoAge(person.getAge());??personDTO.setDtoName(person.getName());??});??}??private?Person?getPerson(){??return?null;??}??

Optional對空值的使用,我覺得更為貼切,它只適用于”是否存在”的場景。

如果只對控制的存在判斷,我建議使用Optional.

Optioanl的正確使用

Optional如此強大,它表達了計算機最原始的特性(0 or 1),那它如何正確的被使用呢!

Optional不要作為參數

如果你寫了一個public方法,這個方法規定了一些輸入參數,這些參數中有一些是可以傳入null的,那這時候是否可以使用Optional呢?

我給的建議是: 一定不要這樣使用!

舉個例子:

public?interface?UserService{??List<User>?listUser(Optional<String>?username);?? }??

這個例子的方法 listUser,可能在告訴我們需要根據username查詢所有數據集合,如果username是空,也要返回所有的用戶集合.

當我們看到這個方法的時候,會覺得有一些歧義:

“如果username是absent,是返回空集合嗎?

還是返回全部的用戶數據集合?”

Optioanl是一種分支的判斷,那我們究竟是關注 Optional還是Optional.get()呢?

我給大家的建議是,如果不想要這樣的歧義,就不要使用它!

如果你真的想表達兩個含義,就給它拆分出兩個接口:

public?interface?UserService{??List<User>?listUser(String?username);??List<User>?listUser();?? }??

我覺得這樣的語義更強,并且更能滿足 軟件設計原則中的 “單一職責”。

如果你覺得你的入參真的有必要可能傳null,那請使用jsr 303或者jsr 305進行說明和驗證!

請記住! Optional不能作為入參的參數!

Optional作為返回值

當個實體的返回

那Optioanl可以做為返回值嗎?

其實它是非常滿足是否存在這個語義的。

你如說,你要根據id獲取用戶信息,這個用戶有可能存在或者不存在。

你可以這樣使用:

public?interface?UserService{??Optional<User>?get(Integer?id);?? }??

當調用這個方法的時候,調用者很清楚get方法返回的數據,有可能不存在,這樣可以做一些更合理的判斷,更好的防止空指針的錯誤!

當然,如果業務方真的需要根據id必須查詢出User的話,就不要這樣使用了,請說明,你要拋出的異常.

只有當考慮它返回null是合理的情況下,才進行Optional的返回

集合實體的返回

不是所有的返回值都可以這樣用的!

如果你返回的是集合:

public?interface?UserService{??Optional<List<User>>?listUser();?? }??

這樣的返回結果,會讓調用者不知所措,是否我判斷Optional之后,還用進行isEmpty的判斷呢?

這樣帶來的返回值歧義!我認為是沒有必要的。

我們要約定,對于List這種集合返回值,如果集合真的是null的,請返回空集合(Lists.newArrayList);

使用Optional變量

Optional<User>?userOpt?=?...??

如果有這樣的變量userOpt,請記住 :

  • 一定不能直接使用get ,如果這樣用,就喪失了Optional本身的含義 ( 比如userOp.get() )

  • 不要直接使用getOrThrow ,如果你有這樣的需求:獲取不到就拋異常。那就要考慮,是否是調用的接口設計的是否合理

getter中的使用

對于一個java bean,所有的屬性都有可能返回null,那是否需要改寫所有的getter成為Optional類型呢?

我給大家的建議是,不要這樣濫用Optional.

即便 我java bean中的getter是符合Optional的,但是因為java bean 太多了,這樣會導致你的代碼有50%以上進行Optinal的判斷,這樣便污染了代碼。

(我想說,其實你的實體中的字段應該都是由業務含義的,會認真的思考過它存在的價值的,不能因為Optional的存在而濫用)

我們應該更關注于業務,而不只是空值的判斷。

請不要在getter中濫用Optional.

小結

可以這樣總結Optional的使用:

  • 當使用值為空的情況,并非源于錯誤時,可以使用Optional!

  • Optional不要用于集合操作!

  • 不要濫用Optional,比如在java bean的getter中!

收外國男騙中國妹子的炮?天朝竟有這樣一幫「女權組織」 2018-03-19 INSIGHT視界 From 酷玩實驗室 微信號:coollabs 其實我讀書的時候 也曾經想過做一個女權主義者 但是后來發生了一些事情 讓我選擇了放棄 簡單來說是這么一個事情:我發現 女權對于一些中國人來說是信仰 但是對另一些中國人來說是生意 所謂的“偽女權”“女權癌” 大概就是這么回事 盡管早就有這樣的思想準備 但讓我沒想到的是 這兩天,知乎上曝光了一件大事 還是讓我三觀震碎 我沒想到,這些“偽女權” 竟然已經形成了黑色產業鏈 讓人細思恐極—— 國內竟然有一群人 打著“女權主義”的名號 從事著組織賣淫的事情 在中國女生不知情的情況下 把她們賣給外國男人!事情是這樣的:根據知乎用戶伊利丹·怒風的爆料 他在知乎和一個偽女權主義者 吵了起來 一開始,他可能以為這只是一個 腦子比較軸的偽女權主義者 所以兩人就吵了一通 本來,他以為就是撕個逼而已 沒想到的是 這個偽女權主義者 可不是什么好惹的主 這個自稱為“瑪麗女王”的人 竟然在半個月中 持續不斷地騷擾他 而最夸張的是 瑪麗女王聲稱 自己有能力 讓伊利丹的QQ號 在5天之內被封掉 到這里為止 伊利丹一直以為 他不過是碰到了一個杠精 但是萬萬沒想到 5天之后 他的QQ號竟然真的被永久封禁了!說真的,這就有點嚇人了 這個不起眼的瑪麗女王 竟然還能操控別人的QQ賬號被封?難不成,她真的背后有人?伊利丹這才意識到 自己好像惹到了一個組織 他去扒了扒這個瑪麗女王的QQ空間 這才發現 自己簡直捅出一個馬蜂窩:這個人平時干的 竟然是把中國女生 賣給外國男人的皮肉生意!真的,我本來以為 我是一個見過不少套路的人 但沒想到 這一套操作 真的是驚為天人 簡單來說是這樣的 首先,瑪麗女王自稱是“女權主義者” 但是實際上她的言論 宣傳的卻是 中國男人配不上中國女人 她甚至惡意辱罵中國男人 恨不得中國男人全部死光 連自己的爸爸都不放過 但是,這么做對她有什么好處呢?很簡單 罵完中國男人以后 接下來她就說—— 既然中國男人這么差勁 那就找外國男人吧!于是,她就經常發布外國男人的介紹 看起來是一個熱心的媒婆 還在各種QQ和微信群里 散播此類信息 但是看到這里 我們不難發現有點問題 看看其中這些不堪入目的措辭 這并不是普通的介紹男友啊!這簡直是在拉皮條啊!果然,伊利丹發現 瑪麗女王真的在 拉皮條的過程中 收外國男人的錢!下面是聊天記錄實錘:而且,請注意—— 在這個過程中 她會收外國男人的錢 但是錢不給中國女生 卻落到了她自己的腰包 于是一個詭異的情況出現了:中國妹子 并不知道收錢這回事 還以為是正常交友 而外國男人 卻都交了錢 很可能認為自己是在買春!額,也就是說 在中國女孩不知情的情況下 她們被“賣”給了外國男人 而好處費 卻全都進了瑪麗女王的腰包... 我真的是沒見過這種操作 這說輕了是騙炮 說重了,已經可以算是賣淫了吧?我想請熟悉刑法的朋友們看看 這個瑪麗女王 至少應該算是個 介紹組織賣淫罪吧?而且,從伊利丹曝光的資料看來 這個組織規模不小 瑪麗女王甚至把外國男生的信息 建了一個完整的表格 有詳細的個人資料、照片 可以說 是一條非常完整的產業鏈 那如果按照這樣操作 外國男人都是來嫖的 中國女生卻不知道 還以為是要跟他們談戀愛 那雙方難道不會穿幫嗎?恩,在這方面 瑪麗女王早有對策 根據知乎一位 從事過這個產業的匿名用戶提供的信息 針對這種情況 瑪麗女王們 還會手把手地教外國男人 怎么快速擺脫女生的糾纏 怎么調教中國女生 怎么讓女生覺得自己很可愛 可以說 各種套路一應俱全 甚至還可以開發票!看到這里 她們背后的產業就非常清楚了 這個瑪麗女王 她根本就不是什么女權主義者 而是打著女權主義的口號 販賣中國女生的人販子 一方面 她們通過辱罵中國男人 吸引對外國男人感興趣的中國女生 另一方面 她們向外國男人收錢 然后把中國女生賣給他們!圖片來源:知乎@渭水徐工 而可憐的中國妹子們 還以為自己是在 追求男女平權 其實,不過是淪為了 這些老鴇的賺錢工具 伊利丹把這整個事情 寫出來以后 在知乎、微博引起了巨大的關注 關于其中提到的 伊利丹的QQ被永久封禁的問題 騰訊經過核查 目前也有了結果:經調查,是瑪麗女王利用偽造證據 惡意舉報了伊利丹的QQ號 目前,騰訊已經將伊利丹的QQ解封 同時封禁了瑪麗女王等人的 兩個QQ賬號 警方也就此事立案偵查了 相信很快就會有結果 這個事情算是告一段落了 但是在我看來 卻有一件事讓我無法釋懷:為什么“女權主義”竟然會和 辱罵中國男性等同起來?為什么“和外國男人交友” 竟然還能演變成 一個免費的陪睡組織?我想,這個瑪麗女王 也許只是一個 發現了惡性賺錢模式的生意人 但是在這背后隱藏的 其實是一個很深的問題:為什么有不少中國女人 越來越看不上中國男人 甚至覺得嫁給外國男人 是一種時尚?這里面的原因可能非常復雜 我這里先提供一個思路 供大家討論:我發現 現在中國很多大型的女權組織 背后都有著西方勢力的影子 她們打著女權的名號 為自己謀取暴利 為西方國家從事破壞活動 而那些真正為女性平權而奔走的人 卻得不到應有的幫助 我之所以這樣說 并不是信口開河 而是有充足的證據 有一個非常有名的民間女權組織 叫做“女權之聲” 它一再聲稱 自己只是一個自發的民間組織 致力于促進男女平等的 它所有的微博賬號、微信賬號 全部都是由一個 叫做婦女傳媒監測網絡的創辦的 而這個婦女傳媒監測網絡 有這么多媒體產品 那它的錢都是哪里來的呢?從她們介紹的合作組織里 我們可以清楚地找到 她們的資助者—— 竟然有西方的福特基金會 有人也許會問 收了西方的錢怎么了?中國的組織不能收西方的錢嗎?然而,她們不只是收了西方的錢而已 女權之聲組織里 有一個人叫做鄭楚然 她除了女權運動之外 沒有任何其他工作 表面上,是一個全職的女權工作者 在2015年的時候 她還因為尋釁滋事 被警察拘留過30多天 甚至在她被拘留的時候 希拉里還借題發揮 指責中國侵犯人權、壓制民主 一個中國的小小民間組織的首領 在互聯網上的粉絲還沒有我多 竟然能得到希拉里這個級別的關注?我真的是驚掉了下巴 這樣看來 我離希拉里也不是很遠了??而不止是希拉里 這樣一個明明思想上毫無建樹的人 卻被西方媒體BBC評為了 全球百大思想家 圖:鄭楚然在王寶強事件中發表的言論 除此以外 更讓人匪夷所思的 是她們平時就喜歡攻擊政府 甚至于,她們還會試圖分裂我們國家 比如,女權之聲這個組織里 著名的女權斗士洪理達 就曾經轉發著名的港獨媒體 Hong Kong Free Press的言論 甚至曾公開發表過 支持藏獨、港獨、臺獨的言論 她也經常和鄭楚然混在一起 我很想不通 如果她們真的只是單純的女權主義者 為何要發表分裂國家的言論?為何要支持藏獨、港獨、臺獨?我只能說,這大概就叫 拿人家的手短,吃人家的嘴軟吧 以前,我在接觸中國的女權組織時 我就覺得很奇怪 她們都喜歡聲稱 自己是不盈利的非政府組織 但是她們無論是宣傳 還是組織各類活動 都需要大量的錢 如果她們真的不盈利 那這些錢都是哪里來的呢?而這些外國的金主 他們也更加不可能是什么慈善組織 大發善心來給中國人投錢 每一分投出去的錢 一定都是要有回報的 那么,他們的回報是什么呢?他們給中國的“女權組織”投錢 能得到什么利益呢?聯想到中國網絡上 如火如荼的對中國男人的討伐 我只能說,細思恐極 我絕不是危言聳聽 因為我們就看不遠的鄰國日本 近些年來日本對于西方的崇拜 可謂深入骨髓 已經到了崇洋媚外的程度 而這其中 當然也包括對白人男性的崇拜 甚至在2016年一個瑞士白人 發了一個視頻,赤裸裸的說 “在東京,只要你是白人, 做什么都可以” 視頻里面他在日本便利店 隨意的親吻不認識的收銀員女孩 在酒吧把不認識的日本女孩 按向自己的褲襠 而日本女孩回應的卻是諂媚的笑容 我想,并不會有那么多中國人 真正被西方偽女權主義控制 但是,我們要警惕的是 別在你自己都沒有察覺的時候 被別有用心的人洗了腦 更有甚者 別在你自己都不知道的情況下 被別人賣給了外國男人 還去幫他數錢 本文系授權發布,From 酷玩實驗室,微信號:coollabs,歡迎分享到朋友圈,未經許可不得轉載,INSIGHT視界 誠意推薦 Forwarded from Official Account 酷玩實驗室 酷玩實驗室 Learn More Scan QR Code via WeChat to follow Official Account 采集文章采集樣式近似文章查看封面

IT技術分享社區

個人博客網站:https://programmerblog.xyz

文章推薦程序員效率:畫流程圖常用的工具程序員效率:整理常用的在線筆記軟件遠程辦公:常用的遠程協助軟件,你都知道嗎?51單片機程序下載、ISP及串口基礎知識硬件:斷路器、接觸器、繼電器基礎知識

總結

以上是生活随笔為你收集整理的后端:Java中如何更优雅的处理空值,看完你就懂了!的全部內容,希望文章能夠幫你解決所遇到的問題。

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