1. 程式人生 > 實用技巧 >Head First Java總結

Head First Java總結

一.可以用陣列建立物件

public class Demo {
    public static void main(String[] args) {
        Dog[] pets;
        pets = new Dog[7];
        pets[0] = new Dog();
        pets[1] = new Dog();
        pets[0].name = "Fido";
        pets[0].eat();
    }
}

二.方法可以宣告多個返回值嗎?有沒有別的方法可以返回多個值?

答:方法只能宣告單一的返回值。如果需要返回3個int值,就把返回值型別說明為int型別的陣列,將值裝進陣列中來返回。

如果有混合不同型別的值要返回時,可以用ArrayList。

三.==和equals

==來比較兩個基本資料型別是否相等,或者判斷兩個引用是否引用同一個物件

equals()來判斷兩個物件在意義上是否相等

在原始碼中,equals()和==是一樣的:

    public boolean equals(Object obj) {
        return (this == obj);
    }

四.繼承中呼叫哪個方法

呼叫物件引用的方法時,得呼叫到與該物件型別最接近的方法——最低階的勝出

如:wolf繼承canine,canine繼承animal,呼叫方法時JVM會從最低階也就是wolf找起,向上找直到找到為止

(wolf不必像介面那樣在implement的類中一定得實現接口裡的全部方法(畢竟介面中的全是抽象方法),wolf可以不寫父類的方法,呼叫的時候直接調父類的方法)

五.多型

public class Demo {
    public static void main(String[] args) {
        Animal[] animals = new Animal[5];
        animals[0] = new Cat();
        animals[1] = new Dog();
        animals[2] = new Wolf();
        
for (int i = 0; i < animals.length; i++) { animals[i].eat(); } } }

使用多型時,可以編寫出引進新型子類時也不必修改的程式

六.方法覆蓋的規則

覆蓋的方法必須要有相同的引數和返回型別

如以下就不是覆蓋:

boolean turnOn()

=====

boolean turnOn(int level)

不能降低方法的存取許可權:不能覆蓋掉一個公有的方法並將其標記為私有

如以下就不是覆蓋:

public boolean turnOn()

======

private boolean turnOn()

定義為final的方法不能被覆蓋

七.萬用類

7.1.Object類是java所有類的子類

如:ArrayList的方法都用到Object這個終極類,因為每個類都是物件的子類,所以ArrayList可以處理任何類

7.2.Object類是可以例項化的,因為有時候你就是需要一個通用的物件,一個輕量化的物件

7.3.為什麼不把所有的返回值型別都設定成Object型別的?

答:比如:

Object o = new Ferrai();
o.goFast();

第二行無法通過編譯,因為這時候JVM會把它當做Object型別的例項,這代表你只能用Object裡的方法

即:你只能從確實有該方法的類中去呼叫!

7.4.如果將一個ArrayList宣告為Object的

ArrayList<Object> myDogArrayList = new ArrayList<Object>();
Dog aDog = new Dog();
myDogArrayList.add(aDog);
//這時候要嘗試把Dog物件取出來並賦給Dog的引用時會發生什麼?
Dog d = myDogArrayList.get(0);

無法通過編譯!

任何從ArrayList<Object>取出的東西都會被當做Object型別的引用而不管它原來是什麼!

取出的Object都會被當做是Object這個類的例項,無法將其識別為除Object以外的事物

調用出的物件只能當做Object型別,無法呼叫除Object類意外的方法——編譯器只管引用的型別,而不管物件的型別

八.父類的構造器

8.1.

public class Animal{
    public Animal(){
        System.out.println("Making an Animal");
    }
}

public class Hippo extends Animal{
    public Hippo(){
        System.out.println("Making a Hippo");
    }
}

public class TestHippo{
    public static void main(String[] args){
        System.out.println("Starting...");
        Hippo h = new Hippo();
    }
}

這時候執行new Hippo()操作,構造器會如何呼叫?

答:先呼叫Hippo(),再呼叫Animal(),再呼叫Object(),將這三個分別壓棧

然後執行的時候彈棧,先輸出Object()的neir,再是Animal(),接著Hippo()

想呼叫父類的構造器,就用super()

也可以用諸如super(name)的方式將引數給父類的構造器

public class Animal{
    private String name;
    public String getName(){
        return name;
    }
    public Animal(String theName){
        name = theName;
    }
}

public class Hippo extends Animal{
    public Hippo(){
        super(name); 
    }
}

public class TestHippo{
    public static void main(String[] args){
        System.out.println("Starting...");
        Hippo h = new Hippo();
        System.out.println(h.getName());
    }
}

先傳入給父類,然後呼叫父類的方法

8.2.帶有private的構造器來限制非抽象類被初始化,如防止Math被初始化,這樣就無法建立它的例項

九.final

class Foo{
    final static int x;
    static{
        x = 42;
    }
}

以上是能被初始化的!如果沒有static後面的就不能通過編譯

十.多執行緒

10.1.如何啟動新的執行緒

  • 建立Runnable物件(執行緒的任務)

  Runnable threadJob = new MyRunnable();

  • 建立Thread物件(執行工人)並賦值Runnable(任務)

  Thread myThread = new Thread(threadJob);

  即將Runnable物件傳給Thread的構造器,這會告訴Thread物件要把哪個方法放在執行空間去執行——Runnable的run()方法

  • 啟動Thread

  myThread.start();

Thread是個工人,Runnable是這個工人的工作,Runnable這個介面只有一個方法——run();