final
1. 數據
聲明數據爲常量,可以是編譯時常量,也可以是在運行時被初始化後不能被改變的常量。
- 對於基本類型,final 使數值不變;
- 對於引用類型,final 使引用不變,也就不能引用其它對象,但是被引用的對象本身是可以修改的。
final int x = 1;
// x = 2; // cannot assign value to final variable 'x'
final int a;
a = 5;
// a = 7; // cannot assign value to final variable 'a'
final A y = new A();
y.a = 1;
2. 方法
聲明方法不能被子類重寫。
private 方法的作用域在該類中,如果在子類中定義的方法和基類中的一個 private 方法簽名相同,此時子類的方法不是重寫基類方法,而是在子類中定義了一個新的方法。
3. 類
聲明類不允許被繼承。
static
1. 靜態變量
- 靜態變量:又稱爲類變量,也就是說這個變量屬於類的,類所有的實例都共享靜態變量,可以直接通過類名來訪問它;靜態變量在內存中只存在一份。
- 實例變量:每創建一個實例就會產生一個實例變量,它與該實例同生共死。
public class A {
private int x; // 實例變量
private static int y; // 靜態變量
public static void main(String[] args) {
// int x = A.x; // Non-static field 'x' cannot be referenced from a static context
A a = new A();
int x = a.x;
int y = A.y;
}
}
2. 靜態方法
靜態方法在類加載的時候就存在了,它不依賴於任何實例。所以靜態方法必須有實現,也就是說它不能是抽象方法(abstract)。
public abstract class A {
public static void func1(){
}
// public abstract static void func2(); // Illegal combination of modifiers: 'abstract' and 'static'
}
只能訪問所屬類的靜態字段和靜態方法,方法中不能有 this 和 super 關鍵字。
public class A {
private static int x;
private int y;
public static void func1(){
int a = x;
// int b = y; // Non-static field 'y' cannot be referenced from a static context
// int b = this.y; // 'A.this' cannot be referenced from a static context
}
}
3. 靜態語句塊
靜態語句塊在類初始化時運行一次。
public class A {
static {
System.out.println("123");
}
public static void main(String[] args) {
A a1 = new A();
A a2 = new A();
}
}
123
4. 靜態內部類
非靜態內部類依賴於外部類的實例,而靜態內部類不需要。
public class OuterClass {
class InnerClass {
}
static class StaticInnerClass {
}
public static void main(String[] args) {
// InnerClass innerClass = new InnerClass(); // 'OuterClass.this' cannot be referenced from a static context
OuterClass outerClass = new OuterClass();
InnerClass innerClass = outerClass.new InnerClass();
StaticInnerClass staticInnerClass = new StaticInnerClass();
}
}
靜態內部類不能訪問外部類的非靜態的變量和方法。
5. 靜態導包
在使用靜態變量和方法時不用再指明 ClassName,從而簡化代碼,但可讀性大大降低。
import static com.xxx.ClassName.*
6. 初始化順序
靜態變量和靜態語句塊優先於實例變量和普通語句塊,靜態變量和靜態語句塊的初始化順序取決於它們在代碼中的順序。
public static String staticField = "靜態變量";
static {
System.out.println("靜態語句塊");
}
public String field = "實例變量";
{
System.out.println("普通語句塊");
}
最後纔是構造函數的初始化。
public InitialOrderTest() {
System.out.println("構造函數");
}
存在繼承的情況下,初始化順序爲:
- 父類(靜態變量、靜態語句塊)
- 子類(靜態變量、靜態語句塊)
- 父類(實例變量、普通語句塊)
- 父類(構造函數)
- 子類(實例變量、普通語句塊)
- 子類(構造函數)