前言
歡迎大家來到院長的博客,記錄一下工作中的瑣事。本文主要內(nèi)容白話(說一下)import 導(dǎo)入 應(yīng)不應(yīng)該加上static關(guān)鍵字。
時間,今天下午。同事最近在做代碼優(yōu)化,準(zhǔn)備將代碼合并到Dev分支。我耳朵比較敏銳聽到了,也想了解一下他優(yōu)化了什么內(nèi)容。于是上gitlab上看了一圈,發(fā)現(xiàn)代碼中貌似有一些不妥的地方,并針對import static 導(dǎo)入方式做了一下面對面討論。
下面將我個人想法和建議做一下梳理。希望能幫助到有需要的同學(xué)。如果哪里說的不對,歡迎大家指出。

代碼展示
下面代碼,模擬一下今天下午的真實場景。XXXUtil代碼中大約有20多個常量類 都是采用如下靜態(tài)import導(dǎo)入的形式。
import static com.package.framework.cmd.Constants.LOGINSUCCESS;
import static com.package.framework.cmd.Constants.LOGINFAIL;
import static com.package.framework.cmd.Constants.LOGINCANCEL;
import static com.package.framework.cmd.Constants.N;
import static com.package.framework.cmd.Constants.N;
import static com.package.framework.cmd.Constants.N;
import static com.package.framework.cmd.Constants.N;
import static com.package.framework.cmd.Constants.N;
import static com.package.framework.cmd.Constants.;
public class XXXUtil {//類名
switch (cmd) {
case LOGINSUCCESS:
//執(zhí)行具體的邏輯
break;
}
}
下列展示的是我認(rèn)為這樣寫比較好的代碼,不需要大量靜態(tài)導(dǎo)入,同樣達(dá)到一樣的效果,直觀清晰明了。雖然從編譯結(jié)果、業(yè)務(wù)邏輯角度來說,上面寫的代碼你也不能說錯或者有問題。但是總感覺很別扭,通過接下來說明和小例子。來闡述我得觀點。
public class XXXXXUtil {//類名
switch (cmd) {
case Constants.LOGINSUCCESS:
//執(zhí)行具體的邏輯
break;
}
}
JAVA 知識了解
在 Java 中,靜態(tài)導(dǎo)入的概念在 1.5 版本中引入。借助靜態(tài)導(dǎo)入,我們可以直接訪問類的靜態(tài)成員,無需類名或任何對象。例如:我們可以通過使用 Math 類即Math.sqrt()來使用 Math 類的 sqrt() 方法,但是通過使用靜態(tài)導(dǎo)入,我們可以直接訪問 sqrt() 方法。
據(jù)SUN公司稱,靜態(tài)導(dǎo)入將提高代碼可讀性并增強(qiáng)編碼。但是一些編程大佬們不認(rèn)可這樣的說法,認(rèn)為它會導(dǎo)致程序混亂并且不利于編程。給到的建議是:如果沒有特殊要求,盡量不要使用靜態(tài)導(dǎo)入。為什么呢?文末會給出答案。
正常improt 導(dǎo)入
class HelloWorld{
public static void main(String[] args){
System.out.println(Math.sqrt(4));
System.out.println(Math.pow(2, 2));
System.out.println(Math.abs(6.3));
}
}
輸出:
2.0
4.0
6.3
靜態(tài)導(dǎo)入
靜態(tài)導(dǎo)入的方式,可以觀察到下面的代碼省略了Math。輸出的結(jié)果也是一致的
import static java.lang.Math.*;
public class HelloWorld{
public static void main(String[] args){
System.out.println(sqrt(4));
System.out.println(pow(2, 2));
System.out.println(abs(6.3));
}
}
輸出:
2.0
4.0
6.3
靜態(tài)導(dǎo)入升級版
靜態(tài)導(dǎo)入的方式,可以觀察到下面的代碼省略了Math和System。輸出的結(jié)果也是一致的
import static java.lang.Math.*;
import static java.lang.System.*;
public class HelloWorld{
public static void main(String[] args){
out.println(sqrt(4));
out.println(pow(2, 2));
out.println(abs(6.3));
}
}
輸出:
2.0
4.0
6.3
注意: System 是 java.lang 包中的一個類,out 是 System 類中的靜態(tài)變量。通過靜態(tài)導(dǎo)入的方式,我們可以不用類名去調(diào)用它。
靜態(tài)導(dǎo)入帶來的歧義點:
如果從多個不同的類中導(dǎo)入兩個同名的靜態(tài)成員,編譯器會拋出錯誤,因為在沒有類名限定的情況下,它將無法確定使用哪個成員。 代碼和錯誤截圖如下所示。
import static java.lang.Integer.*;
import static java.lang.Byte.*;
public class HelloWorld{
public static void main(String[] args){
out.println(MAX_VALUE);
}
}

Error:Reference to MAX_VALUE is ambigious //錯誤:對 MAX_VALUE 的引用不明確
說明:在上面的代碼中,我們試圖訪問 MAX_VALUE 變量,但是每個原始數(shù)據(jù)類型都包含 MAX_VALUE 變量,該變量在 Wrapper 類中預(yù)先聲明。這里我們同時導(dǎo)入 Integer 和 Byte 類并嘗試訪問靜態(tài)變量 MAX_VALUE。
但編譯器會因為看到兩個導(dǎo)入語句而感到懵逼,因為 Integer 和 Byte 類都包含一個靜態(tài)變量 MAX_VALUE。因此這里編譯器拋出一個錯誤,說Reference to MAX_VALUE is ambiguous。
正常import 導(dǎo)入和靜態(tài)import 導(dǎo)入的區(qū)別:
在正常import 導(dǎo)包中,我們能夠訪問任何包中存在的類和接口。但是使用靜態(tài)導(dǎo)入,我們可以直接訪問類的所有靜態(tài)成員(變量和方法),而無需顯式調(diào)用類名。
靜態(tài)導(dǎo)入的優(yōu)缺點:
靜態(tài)導(dǎo)入的優(yōu)點:如果經(jīng)常訪問類的任何靜態(tài)成員,則需要較少的代碼。
-
靜態(tài)導(dǎo)入的缺點:過度使用靜態(tài)導(dǎo)入功能,它會使程序不可讀和不可維護(hù)。
- 假如同時導(dǎo)入的兩個類中又有重命名的靜態(tài)成員,會出現(xiàn)報錯。例如Integer類和Long類的MAX_VALUE。
總結(jié):兩個包中包含兩個同名的類/接口是非常少見的。因此,正常導(dǎo)入我們很少會出現(xiàn)問題(歧義)。但是有可能兩個類包含相同的變量,所以在靜態(tài)導(dǎo)入會出現(xiàn)引用不明確報錯。這就是為什么上面提到,如果沒有這樣特殊要求不建議使用靜態(tài)引用的原因。
結(jié)尾
有用的知識又增加了,如果文本對你有幫助,希望給個關(guān)注和點贊。你的支持是我繼續(xù)寫作的動力。(瘋狂暗示 ?。。。?/p>