一、static關鍵字的作用
1、可以用於修改類的成員變量、代碼塊和類
- 通過static可以將類的成員聲明為靜態成員,靜態的成員歸屬於整個類,而不是屬於某個對象。無論通過類還是對象訪問靜態成員,操作的都是同一個靜態成員。
- 使用static修飾的代碼塊是靜態代碼塊,靜態代碼塊在類加載時執行。
- 靜態代碼塊和靜態方法不能訪問非靜態屬性和方法。
- 靜態方法可以被繼承,但不能被覆蓋(重寫);如果父類中定義的靜態方法在子類中被重新定義,那么父類中定義的靜態方法將被隱藏。即:子類中如果有一個返回類型,方法名和參數列表均與父類同名的靜態方法,那么該子類實際上只是將父類中該同名方法進行了隱藏,而非重寫。它們的行為也不具有多態性。
具體示例如下所示:
class Person { private int age;
//2.使用static修飾的代碼塊是靜態代碼塊 static { System.out.println("靜態代碼塊!"); } //構造代碼塊 { eat(); say(); age = 10; } //3. 靜態方法不能訪問非靜態屬性和方法;因為其屬於對象,靜態方法執行時, //對象還沒有創建 public static void say() { //age = 12; System.out.println("靜態方法說..."); } public static void say(String str) { //age = 12; System.out.println("靜態方法說..."); } //非靜態方法可以調用靜態方法和屬性 public void eat() { say(); System.out.println("吃..." + name); } public static String name; } class Teacher extends Person {
//4.靜態方法不能被重寫,但是可以被繼承 //@Override public static void say() { System.out.println("子類靜態函數重寫"); } } public class Demo01 { public static void main(String[] args) { /*Person p = new Person();
//1.靜態屬性可以通過類和對象訪問 Person.name = "zhansangfen"; System.out.println(Person.name); p.name = "李四"; Person p1 = new Person(); System.out.println(p.name);*/ System.out.println(Person.name); } }
2.靜態的原理
使用static修改的成員屬性、成員方法和代碼塊在類加載時,被放到靜態區,並且只加載一次;只有當類被釋放時,靜態區所占的內存才會釋放。因此,使用不當會造成內存泄漏。其原理圖如下所示:
3.靜態和非靜態互訪
總結:靜態只能訪問靜態,普通可以訪問所有(靜態、普通)
靜態屬性 | 靜態方法 | 普屬性 | 普通方法 | |
靜態方法 | 可以 | 可以 | 不可以 | 不可以 |
靜態代碼塊 | 可以:前提是只能訪問到在靜態代碼塊之前聲明的靜態屬性,之后的不可以。 | 可以 | 不可以 | 不可以 |
普通方法 | 可以 | 可以 | 可以 | 可以 |
構造代碼塊 | 可以 | 可以 | 可以 | 可以 |
靜態方法可以重載嗎? | 可以 | |||
靜態方法可以重寫嗎? | 不可以 |
4.靜態的作用
- JVM的入口方法main是靜態放方法
- 用作工具類:就是將一類常用功能提取成若干方法寫入到一個類中,這些方法通常聲明為靜態方法方便使用。並且將該類的構造函數私有化,禁止創建對象,直接使用類名調用方法。比如常見的數學方法:Math.asin(double a)返回一個值得正弦角度。
- 其他情況下使用靜態。
二、new關鍵字的作用
new關鍵字用於創建一個對象,在其創建對象的過程中大致經歷了一下三個步驟;
1、將類加載到方法區
JVM首先會檢查這個new指令的參數能否在常量池中定位到一個類的符號引用;如果找不到就將該類加載到方法區並經過解析和初始化等步驟,計算實例化對象所需要的內存;為類的靜態變量賦予正確的初始值。
2、在堆中開辟一塊內存用於存儲新創建的對象
將類實例化出一個新的對象,根據類加載時計算所需的內存大小;在堆中開辟一塊內存,用於存儲新對象的成員屬性和方法區地址的引用。成員方法引用指向方法區中該對象對應的方法。
3、在棧中創建指向對象的引用
在棧中創建一個棧針,用於指向堆中創建的對象。