這一節我們看靜態在使用過程中應注意的幾個細節。
上一節我們在學習成員變量與靜態變量的區別時,對于兩種變量的調用方式不同時出現了“無法從靜態上下文中訪問非靜態變量”的錯誤,這個問題我們在以后會經常遇到。那么這是什么問題呢?我們從例子說起,我們把上一節中的Person類中方法printInfo進行靜態修飾:
~~~
class Person
{
String name;//姓名,這是一個成員變量
static String country = "中國";//國籍,這是一個靜態變量
public static void printInfo()
{
System.out.println(name+":"+country);
}
}
class StaticTest
{
public static void main(String[] args)
{
Person p = new Person();
p.name = "小強";
p.printInfo();
}
}
~~~
結果:

我們看到了一個和上一節完全相同的錯誤,而當我們把方法進行修改:
~~~
public static void printInfo()
{
System.out.println(":"+country);
}
~~~
結果:

我們看到當把printInfo方法中的非靜態變量name去掉之后,程序正常運行,因此我們可以總結出static關鍵字使用中的一個常見問題,即:
**第一個細節:靜態方法中不能調用非靜態成員,只能調用靜態成員.**這是由于我們知道靜態成員是隨著類的加載而存在,是先于對象存在的,而非靜態的成員變量是隨著對象的創建而存在,所以當我們在靜態方法中調用非靜態成員時,還沒有創建對象,當然就不存在非靜態變量.比如我們上面的例子,靜態方法printInfo和靜態變量country都會隨著Person類的加載而加載,而成員變量name只有隨著Person對象的創建才會存在,當我們在靜態方法中直接調用name時,此時根本就不存在,當然會出錯.
當然對于這個細節,也可以說是靜態方法的一個局限性.非靜態方法既可以訪問靜態成員,也可以訪問非靜態成員.
我們再看下一個比較常見的問題.
**第二個細節:靜態方法中不可以使用this或者super關鍵字.**原因當然可以用靜態的特點解釋,super我們還沒有學習,這里暫不說明,就拿this關鍵字來說,我們說this代表對象,那么當我們在靜態方法中使用this時,this代表的就是當前類的實例,而靜態方法和類是一起存在的,而該類的對象并不存在,所以會出錯.我們看一個例子:
~~~
class Person
{
String name;
static String country = "中國";
public static void printInfo()
{
System.out.println(this.name+":"+country);
}
}
~~~
結果:

我們很清楚的就看到這是不合法的.
**第三個細節:主函數是靜態的.**這個我們大家肯定都不陌生,我們從開始學習就在搞main函數,它的正確格式是:
~~~
public static void main(String[] args)
~~~
那么我們再來看一個例子:
~~~
class StaticTest
{
int num = 4;
public static void main(String[] args)
{
printNum();
}
public void printNum()
{
System.out.println(num);
}
}
~~~
結果:

我們會發現我們沒有用好第一個細節,所以我們進一步修改:
~~~
class StaticTest
{
int num = 4;
public static void main(String[] args)
{
printNum();
}
public static void printNum()
{
System.out.println(num);
}
}
~~~
結果:

哦,還有一個非靜態成員變量,再一次修改:

這個過程真麻煩哦,那么我們是不是要在主函數中調用的成員都是靜態的呢?如果真是這樣,那么要對象干什么呢?我們知道主函數是程序的入口,對于面向對象語言,那么主函數也就對象訪問的入口,是指揮對象工作的,如果沒有對象不知道有多么可怕啊.
我們之前學習了兩種調用方式,一種是通過類名調用,而另一種方式就是通過對象調用,那么我們為了規避靜態的局限性,我們把上面的方法進行非靜態化,并且通過對象去調用:
~~~
class StaticTest
{
int num = 4;
public static void main(String[] args)
{
new StaticTest().printNum();
}
public void printNum()
{
System.out.println(num);
}
}
~~~
并且程序正常運行了.
**第四個細節:在本類中,非靜態成員前面省略的是this,而在靜態成員前面省略的卻是類名.**比如上面的代碼,實際上在Person類中,成員變量name前面省略的this,即this.name,而在靜態變量country前面省略的類名Person,即Person.country,這一點我們在以后的使用多注意就可以了.
- 前言
- 1.1 基本常識
- 1.2 Java語言概述
- 1.3 Java語言的環境搭建
- 1.4 Java程序開發之初體驗--Hello World
- 2.1 關鍵字
- 2.2 標識符
- 2.3 注釋
- 2.4 常量
- 2.5 進制掃盲
- 2.6 變量和數據類型(1)
- 2.7 變量和數據類型(2)
- 2.8 運算符
- 3.1 if語句
- 3.2 switch語句
- 3.3 while和do-while語句
- 3.4 for語句
- 3.5 for循環的嵌套
- 3.6 break語句與continue語句
- 4.1 函數的定義
- 4.2 定義函數的兩個明確
- 4.3 函數的內存加載過程
- 4.4 函數的重載
- 5.1 數組的定義
- 5.2 數組的內存分配及特點
- 5.3 數組操作中常見問題
- 5.4 數組常用操作(1)
- 5.5 數組常用操作(2)
- 5.6 二維數組
- 6.1 面向對象的概述
- 6.2 類與對象的關系
- 6.3 對象的內存體現
- 6.4 成員變量與局部變量
- 6.5 類類型參數與匿名對象
- 6.6 基本數據類型參數與引用數據類型參數的傳遞過程
- 6.7 封裝
- 7.1 構造函數概述與默認構造函數
- 7.2 構造函數與一般函數的區別
- 7.3 構造函數的重載
- 7.4 構造函數的內存加載
- 7.5 構造函數需要注意的幾個細節
- 7.6 this關鍵字的原理
- 7.7 this關鍵字的細節與應用
- 8.1 static關鍵字之特點
- 8.2 成員變量與靜態變量的區別
- 8.3 static關鍵字使用的注意細節
- 8.4 main函數的解析與細節
- 8.5 static關鍵字的使用場景
- 8.6 靜態的內存加載
- 8.7 靜態代碼塊
- 8.8 構造代碼塊
- 9.1 繼承
- 9.2 單繼承與多重繼承
- 9.3 子父類中成員變量特征體現