首先介紹一下靜態(tài)成員和實例成員
1.1 什么是靜態(tài)成員
- 靜態(tài)成員也叫做共享成員能庆,靜態(tài)成員包括:靜態(tài)屬性九杂、靜態(tài)方法闽寡、靜態(tài)塊(靜態(tài)字段)
- 靜態(tài)成員是通過 static 修飾的屬性、方法尼酿、字段
public class Person{
//靜態(tài)屬性
static String name;
static int age;
//靜態(tài)方法
public static void sayHello(){
System.out.println(name);
}
//靜態(tài)塊(靜態(tài)字段)爷狈,為static變量初始化,靜態(tài)塊在首次類名出現(xiàn)時調(diào)用裳擎,但后于分配靜態(tài)變量涎永。
static{
age = 20;
}
}
1.2 什么是實例成員
- 沒有通過 static 修飾的屬性、方法就是實例成員
public class Person{
//實例屬性
String name;
int age;
//實例方法
public void sayHello(){
System.out.println(name);
}
}
1.3 區(qū)別
- 靜態(tài)成員需要通過 static 修飾,實例成員不需要通過 static 修飾
- 靜態(tài)成員屬于類羡微,可以直接通過“類名.靜態(tài)成員”的方式訪問(類名可以省略不寫)谷饿,也可以通過“對象.靜態(tài)成員”的方式訪問
(不推薦此用法,容易與實例訪問方法混淆)
妈倔。 - 實例成員屬于對象博投,必須實例化對象后,才能夠通過“對象.實例成員”的方式訪問盯蝴。
- 當程序首次運行到類時毅哗,該類下的所有靜態(tài)成員都會在方法區(qū)中被分配內(nèi)存,且只分配一次捧挺,直到程序退出時才會被釋放虑绵;
當類實例化對象時,才會為對象的實例成員在堆中分配內(nèi)存闽烙,且實例化幾個對象就會為其分配幾個內(nèi)存 - 靜態(tài)方法中不允許調(diào)用實例成員翅睛,而實例方法可以調(diào)用靜態(tài)成員。
因為靜態(tài)成員在首次運行到所在類時就會分配空間黑竞,實例成員在類實例化時才會分配內(nèi)存捕发,不實例化就不會分配內(nèi)存。所以此時讓靜態(tài)方法去調(diào)用一個不知道存不存在的實例成員(也就是內(nèi)存)很魂,這顯然是不合理的扎酷。
靜態(tài)方法和實例方法的訪問權(quán)限:
靜態(tài)變量 | 靜態(tài)方法 | 實例變量 | 實例方法 | |
---|---|---|---|---|
靜態(tài)方法 | ||||
實例方法 |
`
1.4 常見的問題---判斷代碼編寫是否正確
例1:
public class Test {
static int age;
public static void main(String[] args) {
age = 2;
}
}
正確
分析:此時是靜態(tài)方法調(diào)用靜態(tài)屬性,age = 2 等同于 Tset.age = 2 代碼正確
例2:
public class Test {
int age;
public static void main(String[] args) {
age = 2;
}
}
錯誤
分析:此時是靜態(tài)方法調(diào)用實例屬性莫换,代碼錯誤
修改方法:
public class Test {
int age;
public static void main(String[] args) {
Test test = new Test();
test.age = 2;
}
}
例3:
public class Test {
public static void main(String[] args) {
}
public void sayHello(){
}
public static void sayHi(){
sayHello();
}
}
錯誤
分析:靜態(tài)方法 sayHi() 調(diào)用實例方法 sayHello() 代碼錯誤
修改方法:去掉sayHi()方法的static,或在sayHello ()方法添加static修飾符
例4:
public static void main(String[] args) {
}
public void sayHello(){
this.sayHi(null);
}
public static void sayHi(Test t){
t.sayHello();
}
正確
分析:靜態(tài)方法 sayHi() 調(diào)用實例方法 sayHello()骤铃,但因為實例方法 sayHello() 又調(diào)用靜態(tài)方法 sayHi()拉岁,相當于靜態(tài)方法 sayHi()自己調(diào)自己。代碼正確
例5:
public class Test {
int age;
public static void main(String[] args) {
new Test().age = 2;
}
public static void sayHi(){
}
public static void sayHello(){
this.sayHi();
}
}
正確
分析:靜態(tài)方法 sayHi() 調(diào)用靜態(tài)方法 sayHello()惰爬,第四行代碼等同于 例2修改方法中的 4喊暖、5 行,代碼正確