深刻理解Java編程的7個例子 佟強 2009年11月7日 http://blog.csdn.net/microtong
1. 閱讀下列代碼回答問題(第一個Java程序,理解PATH和CLASSPATH,學會使用javac和java命令)
- package cn.edu.uibe;
- public class HelloWorld {
- public static void main(String[] args) {
- System.out.println("Hello World!");
- }
- }
問:
(1)上面代碼所在的源文件的文件名是_______________?
(2)在DOS提示符下,當前目錄爲該源文件所在的目錄,PATH環境變量已包含編譯程序所在的路徑,編譯目標路徑爲“D:/classes”,編譯命令行是_____________?
(3)爲了讓Java解釋器能夠找到編譯後的類文件,需要如何設置環境變量___________?
(4)在正確設置了相關的環境變量之後,運行HelloWorld類的命令行是____________?
答案:
(1)HelloWorld.java,公共類必須定義在和類名同名的文件中,文件名區分大小寫。
(2)javac -d D:/classes HelloWorld.java ,-d給出輸出目錄,javac會在D:/classes創建包的目錄層次結構cn/edu/uibe/HelloWorld.class
(3)set CLASSPATH=.;D:/classses,CLASSSPATH給出Java尋找.class文件的多個路徑,路徑之間用分號分隔,“.”表示當前路徑。
(4)java cn.edu.uibe.HelloWorld,注意需要給出包名,類名後面不要加“.class”。
2. 閱讀下列代碼回答問題(關於private的理解)
- public class Light {
- private int brightness = 5;
- public void brighten(Light another){
- another.brightness++;
- }
- public static void main(String[] args) {
- Light light1 = new Light();
- Light light2 = new Light();
- light1.brighten(light2);
- }
- }
問:上面代碼Java編譯器是否會給出錯誤提示?爲什麼?
答案:不會出現錯誤提示,private限制了私有變量只能被同一個類訪問,但是沒有限制同一個類的不同對象之間互相訪問私有變量。實際上,private是在編譯時進行檢查,如果想限制同類對象之間互相訪問,需要在動態運行時實現,開銷較大,而且沒有必要。
3. 閱讀下列代碼回答問題(關於多態性的理解)
- class Base {
- int i=1;
- void f(){
- System.out.println("Base.f()");
- }
- void g(){
- f(); //會調用上面的f()方法嗎?
- }
- }
- public class Derived extends Base { //繼承了Base類
- int i=2; //Derived類的對象有1個i還是2個i呢? 答:2個
- void f(){ //覆蓋override了f()方法
- System.out.println("Derived.f()");
- }
- public static void main(String[] args) {
- Derived d = new Derived(); //創建子類對象
- Base b = d; //沒有創建對象,僅僅是父類引用指向了子類對象
- d.f(); //將會輸出Derived.f()
- b.f(); //也會輸出Derived.f(),方法具有多態性
- System.out.println(d.i); //輸出的是2,d.i訪問子類中定義的變量i
- System.out.println(b.i); //輸出的是1,b.i訪問的是父類中定義的變量i,成員變量是不會動態綁定而表現出多態性的。
- d.g(); //輸出Derived.f()
- b.g(); //也輸出Derived.f(),從父類中調用被覆蓋的方法f(),也將調用到子類中更具體的方法。
- }
- }
問: 寫出上面代碼的輸出?
答案:參見代碼註釋,子類和父類中定義同名的變量時,僅僅是隱藏了,變量沒有多態性;而對於覆蓋的方法,Java表現出多態性,
會調用更具體的子類裏面的方法,無論從哪裏調用,無論使用什麼引用類型調用。
4.閱讀下列代碼回答問題(關於匿名內部類的理解)
- interface A {
- void f();
- }
- public class B {
- public void f(A a) {
- }
- public static void main(String[] args) {
- B b= new B();
- b.f(new A() {
- public void f() {
- }
- });
- }
- }
問:請解釋語句
b.f(new A() {
public void f() {
}
});
的含義與作用。
答案:
這個語句在參數表中定義了一個匿名內部類,這個匿名內部類實現了接口A,實例化了一個匿名內部類的對象,並將這個對象傳遞給了接收接口A作爲參數的方法f(A a)。需要注意的是接口A中的方法f()和類B中的方法f(A a)沒有任何關係,是不同的方法。
5. 閱讀下列代碼回答問題(關於static的理解)
- public class Static {
- static int i = 0;
- int j=0;
- public static void main(String[] args) {
- Static s1 = new Static();
- Static s2 = new Static();
- s1.i++;
- s2.i++;
- s1.j++;
- s2.j++;
- System.out.println(s1.i);
- System.out.println(s1.j);
- System.out.println(s2.i);
- System.out.println(s2.j);
- }
- }
問:寫出上面代碼的輸出。
答案: 2 1 2 1,i是靜態變量,類的所有實例共享同一個i,通常我們不通過引用變量訪問靜態變量,而是通過類名訪問Static.i,注意Static是我們自己定義的類名,而小寫的static是關鍵字,表示靜態的,爲類的所有實例共享的變量或方法。j是實例變量,每個對象具有不同的,屬於其自身的一個變量j。
6. 閱讀下列代碼回答問題(關於引用變量的理解)
- class Counter{
- int i=0;
- }
- public class Reference {
- public void plus(int i){
- i++; //不會改變傳遞進來的參數的值,Java傳遞基本類型時進行了值的拷貝
- }
- public void plus(Counter c){
- c.i++; //會改變,因爲c是一個引用變量,相當於指針
- }
- public void create(Counter c){
- c = new Counter();
- c.i++; //不會改變,因爲c執行了另外一個新建的對象
- }
- public static void main(String[] args) {
- int i = 0;
- Reference r = new Reference();
- Counter c1 = new Counter();
- Counter c2 = new Counter();
- r.plus(i);
- r.plus(c1);
- r.create(c2);
- System.out.println(i);
- System.out.println(c1.i);
- System.out.println(c2.i);
- }
- }
問:上面代碼輸出是?
答案:參考代碼註釋,輸出應該是:0 1 0
7. 閱讀下列代碼回答問題(關於異常的理解)
- class MyException extends Exception{
- public MyException(String message){
- super(message);
- }
- }
- public class ExceptionDemo{
- public void f(int num) throws MyException {
- if(num<0){
- throw new MyException("參數不能爲負數!");
- }
- System.out.println(num);
- }
- public void g(){
- try{
- f(1);
- f(3);
- f(0);
- f(-1);
- f(2);
- f(-5);
- }catch(MyException e){
- System.err.println(e.getMessage());
- return;//會立即返回嗎?答:不會!
- }finally{
- System.out.println("無論什麼時候!");
- }
- }
- public static void main(String[] args) {
- ExceptionDemo demo = new ExceptionDemo();
- demo.g();
- }
- }
問:上面代碼輸出是?
答案:輸出是:1 3 0 參數不能爲負數! 無論什麼時候!
try語句塊裏面的一行代碼拋出了異常,後續代碼就不再執行了,而是轉到catch開始匹配異常類型。finally語句塊裏面的代碼始終會被執行,即使在catch語句塊裏面有行return語句也不會立即返回,Java確保finally語句塊執行完函數纔會返回。
《Java程序設計課件》 http://sit.uibe.edu.cn/java