final關鍵字
- 修飾變量:關鍵字final修飾變量,表示這個變量只能被賦值一次,一旦被賦值之後,就不能再更改了,即final修飾變量時,是用來定義常量的,常量名應該全大寫。例如如下代碼:
final double PI = 3.14;
PI = 24.1; // error: cannot assign a value to variable 'PI'
- 修飾方法:可被子類繼承,但是不能被子類覆蓋
- 修飾類:不需要被繼承,(final類的所有方法自動地成爲final方法,但是類中域不會自動變成final)
命令行參數
每一個Java應用程序都有一個帶String args[ ]參數的main方法,這個參數表明main方法將接收一個字符串數組,也就是命令行參數。例如
public class Test {
public static void main (String[] args) {
System.out.println("1" + args[0]);
System.out.println("2" + args[1]);
System.out.println("3" + args[2]);
}
}
// 編譯上述源碼後,在終端輸入一下指令
java Test hi my world
// 運行結果
1hi
2my
3world
無參數的構造器
僅當類沒有提供任何構造器的時候,系統纔會提供一個默認的不帶參數的構造器,如果在編寫類的時候,編寫了一個構造器,哪怕是很簡單的,要想讓這個類的用戶能夠採用new ClassName()的方式構造實例,就必須提供一個默認的不帶參數的構造器。
初始化塊
- 對象初始化塊,第一次構造了類的實例,該初始化塊就被會執行;
- 靜態初始化塊,虛擬機第一次加載該類,該初始化就會被執行;
// 不創建類實例,只會執行靜態初始化塊,不執行對象初始化塊
public class Test {
// object initialization block
{
System.out.println(" object initialization block");
}
// static initialization block
static {
System.out.println(" static initialization block");
}
public static void main (String[] args) {
}
}
輸出爲:static initialization block
// 創建類實例情境下,先執行靜態初始化塊(因爲類先被加載),再在構造實例時執行對象初始化塊
public class Test {
// object initialization block
{
System.out.println(" object initialization block");
}
// static initialization block
static {
System.out.println(" static initialization block");
}
public static void main (String[] args) {
new Test();
}
}
輸出爲:
static initialization block
object initialization block
抽象類
-
包含一個或多個抽象方法的類本身必須被聲明爲抽象的;
-
抽象方法,不能有方法體:Abstract methods cannot have a body;
- 抽象類不能被實例化,但是可以定義一個抽象類的對象變量,只是它只能引用非抽象子類的對象。例如,
// 抽象父類Person
public abstract class Person {
}
// 子類Student
public class Student extends Person {
public static void main (String[] args) {
new Person(); // error:Person is abstract, cannot be instantiated
Person p = new Student(); // OK: 這裏是正確的,p是一個抽象類Person的變量,Person引用了一個非抽象子類Student的對象
}
}
- 如上所述,抽象類變量可以引用非抽象子類的實例,並且可以通過該變量訪問該引用子類的方法,如
// 抽象父類 Person 聲明瞭抽象方法saying()
public abstract class Person {
public abstract void saying();
}
// 非抽象子類 Student 繼承Person 並實現父類中聲明的抽象方法saying()
public class Student extends Person {
public static void main (String[] args) {
Person p = new Student();
p.saying(); // 雖然Person中沒有定義saying的具體實現,但是由於其引用的是子類實例,所以調用的子類的方法,
// 但是是否可以省略Person父類中的抽象方法saying呢?
// 答案是不行,因爲編譯器只允許調用類中聲明的方法,Person中如何沒有聲明該方法,即便是引用的是子類實例,也不能調用子類中獨有的方法
}
public void saying() {
System.out.println("Hello world");
}
}
- 在正常的類繼承中,對上述情境進行試驗:父類變量引用子類實例時,按繼承鏈優先執行子類中的方法
public class Person {
public void saying(){
System.out.println("Person Hello world");
}
}
//-------------------- Student 子類中覆蓋父類的saying方法 ----------------------------//
public class Student extends Person {
public static void main (String[] args) {
Person p = new Student();
p.saying();
}
public void saying() {
System.out.println(" Student Hello world");
}
}
輸出結果爲:Student Hello world
//-------------------- Student 子類中正常繼承父類的saying方法 ----------------------------//
public class Student extends Person {
public static void main (String[] args) {
Person p = new Student();
p.saying();
}
}
輸出結果爲:Person Hello world
// --------------對比結論-------------- //
結論:父類變量引用子類實例時,按繼承鏈優先執行子類中的方法
訪問控制修飾符