這是 Stack Overflow 第四周周報,兩篇 Java、兩篇 Python。公眾號「渡碼」為日更,歡迎關注。另外,我搜集了今年的就業數據,對招聘情況和崗位情況做了簡單總結,想了解的朋友點這里。
DAY1. 枚舉對象 == 和 equals 區別
我們在比較枚舉常量時可以使用 == 運算符或者 equals 方法,如:
public class EnumEquals { public enum FRUITS { /** 蘋果 */ APPLE, /** 橙子 */ ORANGE }public static void equalApple(FRUITS fruit) { if (fruit == FRUITS.APPLE) { System.out.println("equals"); } if (fruit.equals(FRUITS.APPLE)) { System.out.println("equals"); } } }
先考慮第一個問題:為什么可以用 == 判斷枚舉常量相等?
我們都知道判斷對象的相等應該用 equals 方法,== 只是判斷對象的引用是否相等,枚舉常量能夠使用 == 判斷相等是因為枚舉常量除了定義時初始化的對象外,沒有其他實例。例如:常量 APPLE 在定義時已經初始化,並且運行時不會再有其他的 APPLE 枚舉常量。根據 JLS 文檔,Java 通過以下四點保證枚舉常量不存在定義之外的實例
- 試圖顯式實例化枚舉類型是編譯時錯誤,例如:new FRUITS()
- Enum 類中的 clone 方法確保永遠不能克隆Enum常量,看看 clone 方法可以看到直接拋出 CloneNotSupportedException 異常
- 序列化機制的特殊處理確保不會因為反序列化而創建重復的實例
- 禁止枚舉類型的反射實例化
因為枚舉常量只有一個實例,因此可以直接用 == 判斷枚舉實例的相等。如果我們看下 equals 源碼就可以發現它也是用 == 進行判斷,所以我們考慮第二個問題:使用 == 和 equals 的區別是什么?
- == 不會拋出 NullPointerException 異常, 而 equals 會
- == 的類型不匹配在編譯時檢查,而 equals 不檢查
public class EnumEquals { public enum FRUITS { /** 蘋果 */ APPLE, /** 橙子 */ ORANGE } public enum SIZE { /** 小 */ SMALL, /** 中 */ MIDDLE, /** 大 */ LARGE } public static void main(String[] args) { FRUITS fruit = FRUITS.APPLE; fruit == SIZE.SMALL; } }
因此使用 == 相比 equals 有以下優勢:
- 更快
- 運行時更安全
- 編譯時更安全
參考:
https://stackoverflow.com/questions/1750435/comparing-java-enum-members-or-equals
https://docs.oracle.com/javase/specs/jls/se9/html/jls-8.html#jls-8.9
DAY2. 用 Python 復制文件
我們都知道 Python 庫非常強大,通常我們想實現一個功能基本都找到現成的庫。今天我們就介紹 Python 標准庫中的一個模塊 —— shutil ,該模塊中定義了文件復制的方法。如:復制一個文件,直接調一個函數即可
src = '1.txt' dst = '2.txt' shutil.copyfile(src, dst)
除了該函數, shutil 模塊還定義了其他的函數提供文件復制的功能,但是細節略有不同,對比如下:
其中 copy2 復制的比較全面,估計性能也是比較低的。下面簡單舉兩個例子對比一下不同函數的區別。
1. 目的路徑是否是目錄,copyfile vs copy2
src = 'test.rar' dst = 'D:\\' shutil.copyfile(src, dst) shutil.copy2(src, dst)
2. 是否能復制 meta 數據,copyfile vs copy2
src = 'test.rar' dst = 'test1.rar' shutil.copyfile(src, dst) shutil.copy2(src, dst)
查看文件的 meta 信息,copyfile 復制的文件的更新時間是最新的, 而 copy2 復制的文件更新時間與源文件一樣。
這里只舉這兩個例子,如對其他函數感興趣可自行嘗試。另外,shutil 模塊應該還有其他更方便的函數可以供我們使用。總之使用 Python 開發效率還是挺高的,掌握 Python 確實能提高工作效率。
參考:
https://stackoverflow.com/questions/123198/how-do-i-copy-a-file-in-python
DAY3. 什么是 Java Bean
- 所有的屬性是 private,提供 getter 和 setter 設置屬性
- 有一個 public 無參構造函數
- 實現 Serializable 接口
Java Bean 其實是一種規范。對於我們學知識來說,往往想問為什么 Java Bean 定義這樣的規范。對照上面三點,我的思考是這樣的:
- getter/setter 方法為了對外暴露屬性的讀寫接口,方便框架調用。同時,屬性用 private 修飾可以提高安全性
- 之前的文章看過 Hadoop 框架反射的例子, public 無參構造可以很方便框架通過反射創建類實例
- 由於 web 框架通常需要數據傳輸,因此需要對象具有序列化與反序列化的能力
我們今天這篇文章比較簡短,只是簡單介紹了一下 Java Bean 規范的定義,並且談了談我自己的一些思考。
參考:
https://stackoverflow.com/questions/3295496/what-is-a-javabean-exactly
DAY3. Python 中實現 switch 語句
我們都知道 Python 原生語法中不支持 switch 語句。當然 Python 這么靈活的語法,我們自己實現一個也比較容易。代碼如下:
def f(x): return { 'a': 1, 'b': 2, }[x]
這樣實現稍微有些不完備,沒有默認值,且如果參數不在字典中會報錯。我們更新一版如下:
def f(x): return { 'a': 1, 'b': 2 }.get(x, 9)
這樣實現看起來比較理想了,我們還可以用 Lambda 表達式實現復雜計算,例如:
def f3(x): return { 'a': lambda x: x * 5, 'b': lambda x: x + 7, 'c': lambda x: x - 2 }.get(x, lambda x: x)
用 Python 實現 switch 語句還是非常方便的。
猜測 Python 原生之所以不支持 switch 語法是因為 Python 語言本身已經很靈活了,不需要額外提供 switch 語句增加語言本身的臃腫。真是應了那句話,人生苦短,我用 Python
以上便是 Stack Overflow 的第四周周報,希望對你有用,后續會繼續更新,如果想看日更內容歡迎關注公眾號。
公眾號「渡碼」,回復 就業 查看各平台完整的分析報告,分享更多高質量內容