1.靜態方法
除了靜態變量,類也可以有靜態方法。
常規方法綁定到類的對象(實例),可以引用類的普通(非靜態)變量(以及靜態變量和方法)。靜態方法綁定到類的靜態對象,只能訪問類的靜態變量和/或其他靜態方法。
要在類上調用普通(非靜態)方法,必須首先創建該類的對象,然後在該對像上調用該方法。您不能在類而不是對像上調用普通方法。
例子:
您不能在類上調用非靜態方法! |
---|
|
但是要調用靜態方法,類的靜態對像只要簡單存在就足夠了(而且在類加載到內存後就一直存在)。這就是為什麼 main() 方法是靜態的。它綁定到類的靜態對象,所以你不需要創建任何對象來調用它。
聲明一個方法為static,需要在方法頭之前寫上static關鍵字。該構造的一般外觀如下:
static Type name(parameters)
{
method code
}
例子:
代碼 | 筆記 |
---|---|
|
Java 機器 main 使用如下命令調用該方法Solution.main() : 在靜態 test() 方法中調用靜態方法main() 。 |
要從另一個類調用靜態方法,需要在靜態方法名前指定類名。該構造的一般外觀如下:
Type name = ClassName.methodName(arguments)
例子:
代碼 | 靜態方法 |
---|---|
|
|
|
|
|
|
2.靜態與普通(非靜態)方法
靜態方法和普通方法有什麼區別?
普通方法綁定到普通對象(類的實例),而靜態方法則不是。普通方法可以訪問其實例中的變量,但靜態方法不能:它只是沒有關聯的實例。
兩種方法的區別如下表所示:
能力/財產 | 普通方法 | 靜態方法 |
---|---|---|
綁定到類的實例 | 是的 | 不 |
可以調用類的普通方法 | 是的 | 不 |
可以調用類的靜態方法 | 是的 | 是的 |
可以訪問類的普通變量 | 是的 | 不 |
可以訪問類的靜態變量 | 是的 | 是的 |
可以在對像上調用 | 是的 | 是的 |
可以在課堂上被調用 | 不 | 是的 |
如果這些方法受到如此嚴重的限制,為什麼還需要這些方法?答案是這種方式也有它的優勢。
首先,您不需要傳遞任何對象引用來訪問靜態方法和變量。
其次,有時您只需要一個變量實例。例如,System.out
(System 類的靜態輸出變量)。
第三,有時您甚至需要在創建對象之前調用方法。例如,Java 機器甚至在創建類的實例之前就調用 main() 方法開始執行程序。
綁定到類的實例
當一個普通方法被調用時,一個參數——調用該方法的對象——被隱式地傳遞給它。這個參數稱為this
. 這個隱式參數(對調用方法的對象的引用)將普通方法與靜態方法區分開來。
靜態方法沒有這個隱式參數,所以不能this
在靜態方法內部使用關鍵字,也不能在靜態方法內部調用非靜態方法。根本沒有地方可以獲得對類實例的引用。
可以調用類的普通方法
一個普通的方法總是有隱式this
參數,所以你總是有一個對調用該方法的對象的引用。每當您在另一個普通方法中調用一個普通方法時,this
都會使用隱式參數進行該調用。例子
代碼 | 怎麼運行的 |
---|---|
|
|
這就是為什麼不能從靜態方法調用普通方法的原因。this
靜態方法中根本沒有命名的隱式變量。
或者想像另一種情況:在我們的程序中還沒有創建我們類的任何一個對象。我們可以調用我們類的靜態方法嗎?是的。而這個靜態方法是否可以調用一個普通的(非靜態)方法呢?
好吧,我們會在什麼對像上調用它?畢竟,我們類的一個實例還不存在!
可以調用類的靜態方法
可以從任何地方調用靜態方法——從程序中的任何地方。這意味著它們可以從靜態方法和普通方法中調用。這裡沒有限制。
可以訪問類的普通變量
您可以從普通方法訪問類的普通變量,因為它可以通過隱式參數輕鬆獲得對類實例的引用this
。
靜態方法不知道它應該使用類的哪個實例來獲取普通變量的值。更一般地,我們很容易遇到調用靜態方法但尚未在程序中創建該類的單個實例的情況。
因此,靜態方法不能訪問類的普通變量。
假設一個靜態方法調用了一個普通方法。那個普通方法應該調用什麼對象?
沒人知道!這就是為什麼你不能在不傳遞對對象的引用的情況下從靜態方法調用普通方法的原因!
可以訪問類的靜態變量
調用靜態變量的情況與調用靜態方法的情況相同。可以從程序中的任何地方訪問靜態變量。這意味著您可以從靜態方法和普通方法訪問它們。
可以在對像上調用
靜態方法和普通方法都可以在對像上調用。可能的普通方法調用——實際上,這是調用普通方法的唯一方法。也可以在對像上調用靜態方法:在這種情況下,編譯器自己確定變量的類型並根據其類型調用靜態方法:
代碼 | 編譯器如何看待它 |
---|---|
|
|
|
|
|
|
可以在課堂上被調用
您只能調用類的靜態方法。要調用普通方法,您需要引用該類的實例。因此,您不能使用此構造調用普通方法:ClassName.methodName(arguments)
GO TO FULL VERSION