摘要:文本已收錄至我的倉庫,歡迎記錄一次在寫代碼時愚蠢的操作,本文涉及到的知識點不可變性一交代背景我這邊有一個系統(tǒng),提供一個接口去發(fā)送短信。
前言
只有光頭才能變強。文本已收錄至我的GitHub倉庫,歡迎Star:https://github.com/ZhongFuCheng3y/3y
記錄一次在寫代碼時愚蠢的操作,本文涉及到的知識點:String不可變性
一、交代背景我這邊有一個系統(tǒng),提供一個RPC接口去發(fā)送短信。外部調(diào)用我的接口需要傳入手機號等等參數(shù),我這邊負責(zé)解析這些參數(shù)、做一些業(yè)務(wù)的處理,然后調(diào)用短信渠道商的接口發(fā)送短信。
每當調(diào)用完短信渠道商的接口時,我會對這次發(fā)送的記錄入庫(存入MySQL中),同樣地短信渠道商會返回發(fā)送或失敗的回執(zhí)給我,我也會入庫(存入MySQL中)。
那天,有人來找到我,說某個手機號收不到短信,用戶并沒有屏蔽短信(欠費、關(guān)機)等等一些操作,就是收不到短信。
于是我就去排查啦,首先我先去DB里邊找有沒有對應(yīng)的發(fā)送記錄,發(fā)現(xiàn)這條記錄是存在的,而且在DB上看不出來有什么異常。
所以,這就排除了這個操作在中途被攔截的情況(因為已經(jīng)入庫了,就肯定調(diào)用過短信運營商的接口)
后來就去撈日志,看看調(diào)用短信運營商返回的Result對象的信息是什么,然后就去問了一下短信運營商可能出現(xiàn)這種問題的原因是什么。那邊回復(fù)的是:“如果是部分的手機號出現(xiàn)這種狀況,是不是你們的手機號沒有trim???”
于是,我又去撈日志,發(fā)現(xiàn)手機號后面真的帶有一個空格(扎心了,之前一直看不到)。要處理這個問題就變得異常簡單了,我只要在入口里邊對手機號進行trim就好了。
二、編寫代碼我這邊是支持同一條短信向多個手機號發(fā)送,于是手機號我這邊用的是HashSet來進行接收。對手機號進行trim我寫下了如下的代碼:
// 說明:Task對象 有個 key屬性,這個key屬性的類型是HashSet if (task.getKey() != null && task.getKey().size() > 0) { for (String s : task.getKey()) { s.trim(); } }
代碼很簡單,我做的就兩步:
判斷是否為null,不為null值則遍歷手機號集合
對每個手機號進行trim
上面的代碼有問題嗎?必須有問題啊,沒問題我還寫啥。
下面寫個小Demo,我們會發(fā)現(xiàn):在代碼的11行上調(diào)用trim()方法后,在12行再輸出,還是會有空格的情況。
2.1 為什么會有這種錯覺?其實,我們在初學(xué)Java的時候,肯定會學(xué)到String類。在學(xué)習(xí)的時候也是明確String是不可變的,但總是有個感覺我們把String對象給改了,為什么?
我覺得第一點是這樣的:我們操作的往往是可變的對象,對象的某些屬性改了,我們就認為已經(jīng)改了。比如下面的代碼:
HashSetstudents = getStudent(); for (Student s1 : students) { s1.setName("Java3y"); }
執(zhí)行完,我們就認為在HashSet里邊的Student的名字全改成Java3y了,而實際上也是如此。
我覺得第二點是這樣的:我們平時操作String對象,都是直接把操作后的結(jié)果傳過去,這看起來就像修改原對象了一樣。比如下面類似的代碼:
// 去重 String phone = " 137888888888 "; sendPhone(phone.trim()); // 轉(zhuǎn)成大寫后輸出 System.out.println(phone.toUpperCase()); // ... 等等2.2 怎么改
現(xiàn)在問題已經(jīng)知道了,String對象是不可變的,對String對象進行操作,“看似”把原來的String對象改了,實際上是生成了一個新的String對象。
回到我那個問題,也很好解決,把trim好的手機號設(shè)置到HashSet就行了
// 說明:Task對象 有個 key屬性,這個key屬性的類型是HashSet HashSet最后hs = new HashSet(); if (task.getKey() != null && task.getKey().size() > 0) { for (String s : task.getKey()) { hs.add(s.trim()); } } task.setKey(hs);
這個B寫了一篇文章來解釋自己是怎么“合理“寫B(tài)ug的,真不要臉。
樂于輸出干貨的Java技術(shù)公眾號:Java3y。公眾號內(nèi)有200多篇原創(chuàng)技術(shù)文章、海量視頻資源、精美腦圖,關(guān)注即可獲取!
覺得我的文章寫得不錯,點贊!
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/75554.html
摘要:文本已收錄至我的倉庫,歡迎記一次在工作中愚蠢的操作,本文關(guān)鍵字線程安全我怎么天天在寫啊一交代背景我這邊有一個系統(tǒng),提供一個接口去發(fā)送各種信息比如短信郵件微信等等渠道。小王用了一陣子也沒說有什么問題,于是這個需求就交付了。 前言 只有光頭才能變強。文本已收錄至我的GitHub倉庫,歡迎Star:https://github.com/ZhongFuCheng3y/3y 記一次在工作中愚蠢...
從事 Android 開發(fā)工作要滿 5 年了,雖然明白自己技術(shù)很一般,但是也總是期望能夠有機會進入更好的平臺發(fā)展。這不,因為機緣巧合有了一次 Booking 的面試邀請(是在 hackerrank 上),然后開始臨時抱佛腳 (leetcode 走起),最終選擇了一個周末去完成線上測試,結(jié)果我完全沒預(yù)料到。本以為會被某道題的邏輯繞昏,結(jié)果哪知道被標準輸入這個東西卡得死死的,現(xiàn)在就記錄一下這次非常糟...
摘要:第一是在對象生命周期中初始化是最重要的一步每個對象必須正確初始化后才能正常工作。第二是參數(shù)值可以有多種形式。基類對象的方法對象生命周期的基礎(chǔ)是它的創(chuàng)建初始化和銷毀。在某些情況下,這種默認行為是可以接受的。 注:原書作者 Steven F. Lott,原書名為 Mastering Object-oriented Python __init__()方法意義重大的原因有兩個。第一是在對象生命...
摘要:盡可能地將數(shù)據(jù)寫入,例如創(chuàng)建設(shè)置的都會將數(shù)據(jù)立即的寫入再來看看文檔怎么描述的看看這可愛的默認值我們終于知道了當我們不做任何設(shè)置時,默認采用的是方式顯而易見,使用方式能最大限度的減少與的交互,而在大多數(shù)場景下都是沒有問題的。 0.問題背景 此次問題源于一次挺嚴重的生產(chǎn)事故:客戶的訂單被重復(fù)生成了,而出問題的代碼其實很簡單: // .... redisLockUtil.lock(membe...
閱讀 2687·2023-04-25 22:09
閱讀 2893·2021-10-14 09:47
閱讀 2110·2021-10-11 11:10
閱讀 2765·2021-10-09 09:44
閱讀 3482·2021-09-22 14:57
閱讀 2560·2019-08-30 15:56
閱讀 1670·2019-08-30 15:55
閱讀 834·2019-08-30 14:13