網上羅列了很多關於變數的理解,良莠不齊,不知道哪些是對的,哪些是錯的,所以筆者就這些部落格和自己的理解寫出這篇文章,如果有不對的地方,希望讀者能夠指正,感謝。
變數是我們經常用到的一種,我在剛學 Java 的時候,也經常被各種變數的概念折磨,當時並沒有細摳,但是我在寫一篇類似的文章中,想把變數作為一種小標題來簡述一下,但是發現,變數這個概念還是比較繁瑣的,本篇文章就來深入認識一下 Java 中這些變數的概念
變數彙總
所以,到底有哪些變數的概念呢?距今為止,目前已知的變數主要有
- 例項變數
- 全域性變數
- 靜態變數
- 類變數
- 區域性變數
- 成員變數
- 常量
下面我們就採用各個擊破的方式來認識每個概念
例項變數
例項變數又被稱為Instance variables
。不使用 static
關鍵字定義,並且在任何方法、構造方法、塊之外的變數都是例項變數
。例項變數都是基於特定例項的,例項變數不會在例項之間共享,也就是說,每一個物件的例項都有自己的一個例項變數。下面是例項變數的一個例子
class Fruits {
public String fruitName; // 具有公共訪問許可權的 fruitName;
private int fruitNum; // 具有私有訪問許可權的 fruitNum;
}
你可以使用下面這種方式進行例項變數的呼叫
public class Fruits {
public String fruitName;
private int fruitNum;
public static void main(String[] args) {
Fruits fruits = new Fruits();
fruits.fruitName = "strawberry";
fruits.fruitNum = 100;
}
}
如何識別例項變數
那麼我如何知道一個變數它是例項變數呢?下面是一些關於例項變數的定義規則
- 例項變數可以使用四種訪問修飾符進行修飾:public、protected、default、private
- 例項變數可以使用
transient、final
關鍵字進行修飾 - 例項變數不可以使用
abstract、synchronized、strictfp、native、static
關鍵字進行修飾
例項變數帶有預設值,也就是說,例項變數不用初始化就能使用。下面是常用例項變數的初始值
例項變數的特點
上面我們瞭解了例項變數的基本特徵和如何區分例項變數,下面我們來講一下例項變數的特點。
-
例項變數的只能在類中宣告,但是在方法、建構函式或任何塊之外。
-
當在為堆中物件分配空間時,將為每個例項變數分配一塊區域。
-
例項變數只能通過建立物件來使用,當使用
new
關鍵字進行建立物件時,例項變數同時也被建立,當垃圾回收器回收物件時,例項變數也會被銷燬。 -
例項變數可以使用訪問
修飾符
來修飾 -
例項變數不用強制初始化,它有自己的預設值。
-
每個物件都有自己的一個例項變數的副本,因此在一個物件中修改變數不會對其他物件中的例項變數造成影響
-
例項變數只能通過建立物件引用來使用。
全域性變數
全域性變數又被稱為Global variables
。如果你有其他語言的程式設計經驗,比如 C、C++ 的話,你會接觸到全域性變數這個概念,你可以使用下面程式碼來建立全域性變數
#include<stdio.h>
// 全域性變數
int A;
int B;
int Add()
{
return A + B;
}
但是在 Java 中,是不存在全域性變數的。因為 Java 是一門物件導向的程式語言,所有的內容都是屬於類的一部分。Java 這麼做的原因是為了防止資料和類成員被其他程式的其他部分有意或者無意的修改。所以在 Java 中,使用 靜態變數
來起到全域性訪問的目的。
靜態變數
靜態變數又被稱為Static variables
。靜態變數的定義比較簡單,靜態變數是屬於該類
的變數,它是由 static
關鍵字來修飾的。static 修飾的變數屬於靜態變數,它只能定義在類的內部、方法的外部。
靜態變數的特點
- 靜態變數只能使用 static 關鍵字進行修飾,它不能在方法中進行宣告,不論是靜態方法還是非靜態方法。
- 靜態變數會在程式執行前進行初始化,並且只初始化一次。靜態變數會有一個初始化順序,我們後面說。
- 靜態變數的所有例項共享同一個副本。也就是說,靜態變數只有一個,它不會隨著物件例項的建立而進行副本拷貝
- 靜態變數可以通過
類名.變數名
進行訪問,並且不需要建立任何物件就能訪問。
public class Fruits {
public String fruitName;
private int fruitNum;
static String fruitType;
public static void main(String[] args) {
Fruits.fruitType = "apple"; // 類名.變數名
System.out.println(fruitType);
}
}
- 可以在
非靜態方法
中使用靜態變數
類變數
類變數又被稱為 Class variables
在 Java 中,類變數就是靜態變數,它們都用 static
關鍵字進行修飾,所以,如果你再聽到說靜態變數的時候,它也就是類變數。
區域性變數
還有一種說法,說 Java 中只有類變數、例項變數和區域性變數。這麼分也沒有問題,可能有人會問到,你把成員變數和常量放在哪了?彆著急我們後面會說
先來說一下什麼是區域性變數
區域性變數又稱為 Local variables
。它指的是在方法中、構造器中或者塊程式碼中定義的變數。區域性變數的生命週期隨方法、構造器、程式碼塊的執行完畢而銷燬。
不管上面的一些變數概念如何變換、區域性變數都站如鬆,坐如鐘,行如風,臥如弓,從容應對各種不同文章的比較。真是一個省事的變數。
那麼這麼好的東西我們可要仔細研究一下其特點是啥
- 根據定義可知,區域性變數定義在方法、構造器或者程式碼塊中;
- 然後區域性變數的生命週期隨方法、構造器、程式碼塊的執行完畢而銷燬;
- 區域性變數不能使用訪問修飾符,例如如下程式碼
-
區域性變數僅在方法的宣告、建構函式或者塊內可見,區域性變數只能在呼叫這些方法、建構函式或者塊的內部使用
-
區域性變數沒有預設值,所以區域性變數應該在第一次使用或者宣告的時候就應該初始化完成
成員變數
什麼?成員變數在 Java 中就是例項變數?這個結論對嗎?
常量
驗證過程
為了驗證這個結論,我們求助於了 stackoverflow
網站
我們搜尋 java member variable and instance variable 就幫我們定為到了這個標題
大致意思是:什麼是成員變數?成員變數和例項變數是否相同呢?我們下面有個回答
第一句就給出,例項變數和類變數都稱為成員變數,然後給出了 JDK 官網手冊對變數的定義。意思是在 Java 中,只有三中型別的變數
- 定義在類中的成員變數 --- 被稱為屬性
- 定義在方法(包含構造方法)或者塊程式碼中的變數 --- 被稱為區域性變數
- 定義在方法定義中的變數 --- 被稱為引數
嗯。。。或許還不是很好解決我們的問題,我帶著問題再次求助 JDK 官網手冊,又看到了關於 Variables
的定義
意思是在 Java 中,只有下面幾種型別的變數(別扯別的了,莫非你比官網還靠譜?)
例項變數(非靜態屬性)
:大致意思就是說
非靜態屬性也就被稱為例項變數
,因為它們的值是相對於每個例項來說的。換句話說,對於每個物件來講,例項變數的值都是唯一的;
-
類變數(靜態屬性)
:類變數就是使用 static 修飾符宣告的欄位,這就會告訴編譯器:無論該類被例項化了多少次,該變數只存在一個副本。另外,可以新增關鍵字 final 來表示常量
。 -
區域性變數
:沒有特殊的關鍵字將制定的變數宣告為區域性變數、確定其宣告的完全取決於宣告變數的位置。 -
引數
:想一下我們平常用到最多的方法是什麼方法?當然是main
方法啊,main 方法是怎麼定義的?
public static void main(String[] args) {}
其中的 args 是不是就是 String 的陣列的變數,我們也稱其為引數
,所以引數也沒有關鍵字進行宣告,標識其為引數也只是取決於其宣告位置。
bilibili
所以
我寫了一篇文章為了給你講清楚,現在你應該知道 Java 中到底有哪些變數了吧。
如果你用 static 來定義變數,只能是類變數、或者說靜態變數、而且其定義位置只能在類中,方法或程式碼塊外,變數的副本只有一個。
如果你不用 static 來宣告變數,那麼就會有三種變數的叫法
- 定義在構造方法、程式碼塊、方法
外
的變數被稱為例項變數,例項變數的副本數量和例項的數量一樣。 - 定義在方法、構造方法、程式碼塊
內
的變數被稱為區域性變數; - 定義在方法引數
中
的變數被稱為引數。
也就是下面程式碼所描述的這樣
public class VariablesInJava {
int instanceVariable; // 例項變數
static String staticVariable; // 類變數
public void method() {
String localVariable = "localVariable"; // 區域性變數
System.out.println(localVariable);
}
public static void main(String args[]) {} //引數
}