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();