靜態字段就是將字段定義爲 static 的字段,類的全部實例共享一個靜態字段。靜態字段屬於類,而不屬於任何單個對象。而對於非靜態的實例字段,每一個對象都有本身的一個副本。java
class Employee { private static int nextId = 1; private int id; ... }
如今,每一個 Employee 對象都一個本身的 id 字段,但 Employee 類的全部實例將共享一個 nextId 字段。即便沒有 Employee 對象,靜態字段 nextId 也存在。它屬於類,而不屬於任何單個對象。ide
靜態變量使用得比較少,但靜態常量卻很經常使用。例如,在 Math 類中定義了一個靜態常量。單元測試
public final class Math { ... public static final double PI = 3.14159265358979323846; ... }
在程序中,能夠用 Math.PI 來訪問這個常量。測試
若是省略關鍵字 static,PI 就變成了 Math 類的一個實例字段。也就是說,須要經過 Math 類的一個對象來訪問 PI,而且每個 Math 對象都有它本身的一個 PI 副本。ui
另外一個靜態常量是 System.out。在 System 類中聲明以下:this
public final class System { ... public static final PrintStream out = null; ... }
因爲每一個類對象均可以修改公共字段,因此,最好不要有公共字段。然而,公共常量(即 final 字段)卻沒有問題。所以 out 被聲明爲 final,因此,不容許再將它從新賦值爲另外一個打印流:
System.out = new PrintStream(...); // 錯誤,out 是 final 常量
code
註釋: 若是查看 System 類,就會發現有一個 setOut 方法能夠將 System.out 設置爲不一樣的流。你可能會感到奇怪,爲何這個方法能夠修改 final 變量的值。緣由在於,setOut 方法是一個原生方法,而不是在 Java 語言中實現的。原生方法能夠繞過 Java 語言的訪問控制機制。這是一種特殊的解決方案,在本身編寫程序時不要模仿這種作法。orm
靜態方法是不在對象上執行的方法。例如,Math 類的 pow 方法就是一個靜態方法。表達式:
Math.pow(x, a)
會計算冪 x<sup>a</sup>。在完成計算時,它並不使用任何 Math 對象。換句話說,它沒有隱式參數。對象
能夠認爲靜態方法是沒有 this 參數的方法(在一個非靜態的方法中,this 參數指示這個方法的隱式參數)。ci
靜態方法不能訪問實例字段,由於靜態方法不能在對象上執行操做。可是,靜態方法能夠訪問靜態字段。
class Employee { private static int nextId = 1; private int id; public static int getNextId(){ return nextId; // 返回靜態字段 } ... }
能夠提供類名來調用這個方法:
int n = Employee.getNextId();
註釋:可使用對象調用靜態方法,這是合法的。例如,若是 harry 是一個 Employee 對象,可使用 harry.getNextId()
替代 Employee.getNextId()
。不過,這種方式很容易形成混淆,其緣由是 getNextId 方法計算的結果與 harry 毫無關係。咱們建議使用類名而不是對象來調用靜態方法。
在下面兩種狀況下使用靜態方法:
靜態方法還有另一種常見的用途。相似 LocalDate 和 NumberFormat 的類使用靜態工廠方法(factory method)來構造對象。例如工廠方法 LocalDate.now 和 LocalDate.of。NumberFormat 類以下生成不一樣風格的格式化對象。
NumberFormat currencyFormatter = NumberFormat.getCurrencyInstance(); NumberFormat percentFormatter = NumberFormat.getPercentInstance(); double x = 0.1; System.out.println(currencyFormatter.format(x)); // prints ¥0.10 System.out.println(percentFormatter.format(x)); // prints 10%
NumberFormat 類不利用構造器完成這些操做的兩個主要緣由:
能夠調用靜態方法而不須要任何對象。例如,不須要構造 Math 類的任何對象,就能夠調用 Math.pow。
main 方法是一個靜態方法。
public class Application { public static void main(String[] args) { // 在這裏構造對象 } }
main 方法不對任何對象進行操做。事實上,在啓動程序時尚未任何一個對象。靜態 main 方法將執行並構造程序所須要的對象。
每個類能夠有一個 main 方法。這是經常使用於對類進行單元測試的一個技巧。
java.util.Objects 7
static <T> void requireNonNull(T obj)
若是 obj 爲 null,會拋出一個 NullPointerException 異常而沒有拋出消息。
static <T> void requireNonNull(T obj, Strimg message)
若是 obj 爲 null,會拋出一個 NullPointerException 異常而拋出給定消息。
static <T> void requireNonNull(T obj, Supplier<Strimg> messageSupplier)
若是 obj 爲 null,會拋出一個 NullPointerException 異常而拋出給定消息。
static <T> T requireNonNullElse(T obj, T defaultObj)
若是 obj 不爲 null 則返回 obj,或者若是 obj 爲 null 則返回默認對象。
static <T> T requireNonNullElseGet(T obj, Supplier<T> defaultSupplier)
若是 obj 不爲 null 則返回 obj,或者若是 obj 爲 null 則返回默認對象。