本文適合對 Java 或 C 有一些了解的用戶閱讀,推薦閱讀時間15分鐘,
導言
寫這個系列的原因?
我曾經聽過一種說法,如果不了解Liunx的網路通訊,就很難理解理解Java的IO;如果不知道Java的IO也很難理解之后的NIO,Netty,(理解是建立在對底層的理解之上的)
一門語言的設計是一項工程,是需要向很多其他編程語言、作業系統學習,站在巨人的肩膀上進行設計的;好的設計,好的語法也不是一蹴而就的,需要對之前版本的優點和缺點進行評估,再進行新語法的設想,
所以,本系列想采用Java從設計之初一直發展到Java8相關的新特性來講述語言為何如此設計,以及語言發展各個重大版本的變化這個角度進行決議如何撰寫好“風格”的代碼,
注:Java已經發展了很多年,目前為止最新的LTS版本為Java11,由于Java8商用已經較為普及,所以采用此版本,
這一節,先從布爾,常量一些特性開始講起,
一、布爾型別
布爾型別在語法上類似于語言內置的常量,所以也做一些簡單的介紹,
在過去撰寫C語言的代碼時,由于缺少布爾型別(C99加入了布爾型別!),默認任何 非零 的值(不為null)假定為 true,把 零 和 null 假定為 false,
#include<stdio.h> int main() { /* 輸出 if(null) is false */ if (null) print("if(null) is true"); else print("if(null) is false"); /* 輸出 if(0) is false */ if (0) print("if(0) is true"); else print("if(0) is false"); /* 輸出 if(1) is true */ if (1) print("if(1) is true"); else print("if(1) is false"); }
這在當時沒有問題,但這種寫法可讀性差,對程式員不太友好,
在這點上,C++往前走了一步,添加了布爾型別bool,但由于要兼容C語言,也可以同時使用C的語法(條件運算式接收int值),列印bool值真偽實際為1和0,
#include <iostream> using namespace std; int main(){ bool flag = true; if(flag) cout<<"true"<<endl; else cout<<"false"<<endl; cout<<flag<<endl; flag = false; if(flag) cout<<"true"<<endl; else cout<<"false"<<endl; cout<<flag<<endl; return 0; } /* 輸出 true 1 false 0 */
Java也沿襲下來,增加了boolean型別,但條件運算式不接受int值,在語法上int值和boolean徹底無關,
package com.xx; public class Demo { public static void main(String[] args) { boolean b1 = true; System.out.println(b1); boolean b2 = false; System.out.println(b2); } } /*輸出 true false */
從C、C++一直到Java,可以看到語言設計者在一步步讓程式撰寫者編出更直觀的、人類可讀的代碼,
二、魔術數字(magic number)
編程初學者碰到一些特殊變數最開始可能會直接采用硬編碼的方式撰寫,這種編碼被人們稱之為魔術數字(原因在于作者在若干月后,甚至自己也不知道這個數字是什么意義)
//100表示成功,其他值表示失敗 if (status == 100) { //成功處理 } else { //失敗處理 }
其中100就是一個典型的魔術數字
這種編碼習慣有以下兩個明顯的缺點
1.數值的意義難以了解
2.數值涉及變動時,可能要改不只一處
后來的編程人員使用了常量來代替魔術數字,常量名力求見名知意(某人說,好的代碼是自解釋(self-explanatory)的),
常量的加入給程式帶來了這兩個好處,
1.增加可讀性,
2.方便修改,
//1.這樣的常量通常用相同的前綴表示同一型別 USER_SEX,且定義位置在最開頭 //2.從C沿襲至今的全大寫,下劃線分隔 public static final int USER_SEX_MALE = 1; public static final int USER_SEX_FEMALE = 0;
但是,在越來越多的常量使用中,人們又發現了自定義的常量也有一些難以解決的問題
1.需編譯后才能生效
2.存在型別轉換的風險
p.s. 第二點正是和C++的布林值bool的問題
再后來,常量的撰寫方式越來越多,比如注解,
通過注解使用的常量值
//application.properties
# 默認使用dev的組態檔
spring.profiles.active=dev
//application-dev.properties
# foo在開發環境的默認次數
default.foo.numbers = 10
//application-test.properties
#foo在測驗環境的默認次數
default.foo.numbers = 1000
//application-prod.properties
# foo在生產環境的默認次數
default.foo.numbers = 100
import org.springframework.beans.factory.annotation.Value; public class Service { @Value("${default.foo.numbers}") private Integer fooNumbers; }
使用注解的好處在于用戶可以定義不同的application-xxx.properties等多個組態檔,每個檔案可以定義同名不同值的常量, 在啟動專案時通過啟動引數 -Dspring.profiles.active=XXX 來選擇使用的組態檔,實作改變配置時改變常量值,
比如 dev組態檔的default.foo.numbers設定為10, test組態檔值設定為1000,根據 啟動專案呼叫 -Dspring.profiles.active=test 呼叫到的值就是1000,
Java設計之初并沒有考慮列舉型別,而是沿用從C一直以來的傳統使用全域int/string值表示常量,為了讓用戶更好地使用常量,從1.5之后引入了列舉型別
/** * 1.自動私有建構式 * 2.強型別,不會因為型別轉換帶來問題 * 3.可以直接使用 == 比較,和String常量需要equals()對比,性能高 * 4.無需編譯生效 */ public enum UserSex { male, //男 female, //女 ; //error // UserSex(); public static UserSex get(String str) { for (UserSex t : UserSex.values()) { if (t.name().equals(str)) return t; } return null; } }
目前為止博主的最佳實踐
對于只有真偽的值,在Java中推薦使用布爾型別表示,比如是否為會員(isVip: true, false),
對于超過兩種以上或今后可能會增加新的型別的推薦用列舉表示,比如會員型別(VipType: week, month, year),考慮之后可能會新加入quarter等時間,
對于不同服之間同一個常量值由于各種需要測驗等原因不一致,可以在各個服的組態檔定義,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/38617.html
標籤:Java
上一篇:Springboot啟動原理
