學姊最棒! 無論你如何引用、使用更改此文件,必定要讓以上那句話隨著此份文件出現,並且這幾句話也要跟著出現,讓別人能夠知道引用時的規矩。 此份文件於2002 6/25 10:00 更新 |
Polymorphism |
int m;
int n;
}
class B extends A {
int o;
}
則一個B的物件,看少一點也可以看成A的物件。(以Java Compiler的角度來看,繼承下來的變數是一直疊上去的,所以B的物件實際上按順序有m,
n, o這三個變數。你若是把這三個變數都看進去,可以看成B;你也可以看少一點,只看m, n,可以看成A)
另一個是從變數的概念:
A o = new B();
o = new A();
同一個變數可以指向不同型態的物件。
Interface |
int m;
}
class B {
int n;
}
class C extends A, B {
int o;
}
則class C中的變數排列也許會是這樣:
int m;
int n;
int o;
則class C可不可以用Polymorphism的方法看成class A?可以,因為從上往下看一個變數int
m;完全符合class A。但是問題來了,可不可以看成class B?當我們從上往下看C一個變數(因為class
B只有一個變數),是int m,不是int n。這就不符合了。所以Java並不支援多重繼承,就是為了避免這種麻煩。所以interface捨棄了和implementation有關的instance
var, static method,就是為了要Polymorphism的方便。
用法大概是這樣:
interface I {
public static final int var = 1;
public abstract void Method();
}
class B implements I {
public void Method() {
//... implementation
}
}
I v = new B();
v.method();
嗯,還有interface可以繼承別的interface,而且可以多重繼承。
interface J extends I, K {
//....
}
AWT |
觀念:老師講過的另外一個小地方就是Canvas,當你invoke canvas.repaint()的時候,並不是直接去呼叫那個Canvas的paint()
method,而是產生一個repaint Event,丟到EventQueue中,再由AWT-EventQueue0去把Event抓出來,找EventSource,再去invoke
Canvas.paint()。
Nested Class |
TextField t;
MyFrame() {addWindowListener(new WindowAdapterF());
setVisible(true);
t = new TextField(40); // Create TextField Instance
add("North", t);
Button b = new Button("Clear"); //Create Button Instance
add("South", b);
b.addActionListener(new MyActionListener());
// 給Button一個EventListener,讓Button可以去處理被按下的Event
pack();}
}
那我們的EventListener要怎麼寫呢?
class MyActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
???.t.setText("");
//我們要怎樣摸到那個t?沒有任何辦法!e.getSource()只能摸到Button。}
}
當然,有另外的方法可以解決這個問題,但是我們覺得太麻煩了,所以禁不起大眾的要求,加入了Inner
Class的功能。
Static Nested Class (Interface) |
上課沒講,不算Inner Class,是最單純的一種Nested Class。
}
} |
Inner Class |
Non-static Nested Class叫做Inner Class,它的宣告和Static Nested Class差不多,少了static:
} |
Local Inner Class |
} |
Anonymous Inner Class |
更簡化的Local Inner Class。因此和Local Inner Class一樣,可以access一樣的東西。
}
} |
關於Nested Class,若有空我會整理一張表。
Exception |
也是物件,繼承自Throwable。
分為synchronous exception與asynchronous exception:
synchronous exception
由JVM產生的,可能是JVM發生錯誤,這時候就已經沒救了,你的Program也管不著。
asynchronous exception
由你的Program來產生。
而asynchronous exception又分成兩種:
checked exception
被定義好,明確知道在哪裡會被throw出來的exception,compiler會檢查。
unchecked exception
分成兩種:RuntimeException
Error不知道在哪裡會產生的,有可能隨時隨地產生也不一定。例如ArrayIndexOutOfBound Exception、ArithmeticException…等。
Exception Handling
try-catch-finally:
try {
//try block
} catch (XXException e) {
//catch block
} catch (Exception e) {
//catch block
} finally {
//finally block
}
在try-block裡面的程式碼就是要測試的程式碼。如果執行try-block裡面的程式碼安然無事,沒有Exception,就會忽略下面的那些catch,要是有Exception發生,就會立刻從發生處中斷,依序往下找catch
block。若是Exception符合catch後面的型態(用Polymorphism的觀點,只要是那個型態的Sub-class就算符合),就會把這個Exception給assign到catch後面的變數(本例是e),然後執行catch-block裡面的東西。
而finally則是無論如何一定會執行的block,它會在這塊try-catch-finally執行將要執行完時,例如要try裡面執行完畢什麼事都沒發生,或是try執行到一半有Exception,被catch抓到然後catch
block執行完畢,或是catch抓到後catch block內又產生新的Exception於是被中斷,或是catch
block根本抓不到的時候…等,都一樣,當它們要離開這個try-catch-finally block時,就會執行finally裡面的程式碼,然後才離開。注意一個觀念,finally是以組合語言為單位,並非以statement為單位。例如:
int i = 1;
try {
return i++;
} finally {
System.out.println(i);
}
return i++;這行statement會先把右邊的值evaluate出來,我們知道i++ evaluate出來的值是1。此i已經變成2了。這時候return原本會離開這個block,但是因為有finally
block,它會在要離開之前先做,於是就把i給印出來,印出2。等到印完了以後,才會真正把原來那個1給return回去。
而剛剛說到Exception符合catch-block後面的型態就會被catch住,但是要是Exception都沒有符合的型態,就會一路衝,任何不在try-block裡面的程式碼發生了Exception只有一個動作:中斷並且往上一層扔!這Exception除非找到一個try-block,並且被catch住才會停下來。否則的話,一直往上扔的結果,到了main也無法處理,就往上扔給JVM,JVM就幫你印出printStackTrace(),然後結束掉。舉例:
public static void main(String arg[] ) {
try {
m(); //#4
}catch (AException e) {
//.... #5
}
}
static void m() {
try {
int a = 3/0;
//.... #1}catch(BException e) {
//.... #2
}catch(AException e) {
//.... #3
}
}
int a = 3/0;這行因為除以零,會發生ArithmeticException,而且這exception的發生點又在try-block內,因此就會中斷掉,然後往下面的catch-block找看看能不能被catch。所以#1的地方是不會被執行到的!現在假設這個ArithmeticException被紅色那行catch(BException e)給抓住了,然後現在執行#2處的程式碼,這時竟然又發生了AException,因為Exception發生之處並不在try-block內,所以它會中斷,並且立刻丟到上一層。因此並不會被#3處給catch到,而是回到上一層,也就是m()被invoke的地方,此時#4之處因為有一個AException,而且#4又在try-block內,因此會去找catch,於是就被#5處給catch到了。要是#5處又發生exception,那往main的上一層丟,就是JVM了。於是程式結束。這個觀念比較容易考trace,大家多多注意。喔,對了,try後面一定要有catch或finally,不能都兩個沒有。只要有其中任一個就可以。
throw
throw是什麼呢?throw的意思就是你要丟出一個exception了!(相當於之前講的Exception發生)你new
出一個exception的物件沒有用,它只是一個Object而已,只是一塊memory而已。要你throw它了以後,才會發生以上的事情。用法很簡單,像這樣:
throw new MyException() ;
throws
throws是一個子句,用來修飾method。是這樣用的:
int method () throws IOException, AException {
//....
}
他說明了一個method可能會丟出什麼checked Exception。一個Method若是要丟checked exception,一定要把那些exception給寫在throws後面,Compiler會檢查。至於unchecked
exception就不用寫。
Thread |
我好累喔…這部份我看就算了吧!
另外Virtual Method Invocation,Hiding的觀念大家一定要弄清楚喔!太累了我就不寫了