一、判斷題(正確的描述打鉤,錯誤的打叉,每題 1 分,共 10 分)
1. 一個 Java 源文件中只能定義一個公有類,并且類名必須與文件名一致。(對)
2. 通過在程序中引入“ import javax.swing.*; ”語句,就可以使用 javax.swing 包中的所有類(包括其嵌套的子包中的類)。 (錯)
要使用嵌套子包中的類,必須再次添加 import 子句
3. J2SE 的功能是 J 2 ME 的一個子集。(錯)
4. Java 字節(jié)碼只有被裝入到內(nèi)存中之后,才能被執(zhí)行。(對)
在當前計算機體系結(jié)構(gòu)之下,CPU無法直接讀取保存于磁盤上的程序文件,這些文件所包容的指令必須被裝入到內(nèi)存之后,CPU才能讀取。
5. Swing是一套GUI組件,采用了新的思路設計Java應用程序的界面,它完全地替換掉了原有的AWT。(錯)
Swing仍然使用AWT的事件模型,并非完全拋棄。
值得注意的NetBeans 6.9.1完成最新的更新組件后,創(chuàng)建Java桌面應用程序時,有了一個新的提示消息框:
看來Oracle也知道Java在桌面上沒戲,干脆放棄了對Swing框架的進一步開發(fā)。已經(jīng)存在這么多年的Swing框架被“新主人”拋棄,真不知道該說什么。
6. 在編程時編寫過多的注釋,會使編譯之后生成的程序文件變大。(錯)
放心, 編譯器會刪除所有的注釋。所以,哪怕你在程序中寫了一部長篇小說,也不會拖慢程序的運行速度。
7. Java Applet 可運行于瀏覽器中,這意味著瀏覽器本身就可以直接執(zhí)行 Applet 程序。(錯)
瀏覽器本身只認識HTML,它對其他類型信息的支持,比如Flash,Applet,Silverlight應用程序等都是通過啟動本地計算機安裝的附加插件來實現(xiàn)的。
8. JDK 5.0新增的枚舉類型( enum )是一個原始數(shù)據(jù)類型。(錯)
9. Java 中規(guī)定所有的方法都必須放到某個類中,不存在獨立于類的方法。(對)
10. 面向?qū)ο筌浖到y(tǒng)設計師們經(jīng)常用到的 UML 是一種編程語言。(錯)
二、簡答題(請將答案寫到答題紙上,注明題號。每題 4 分,共 40 分)
1. 現(xiàn)代編程語言有兩種主要的類型:一種是“編譯型 ”的,比如 C ,程序源碼必須經(jīng)過編譯才能運行;另一種是“解釋型 ”的,這種類型的語言(比如早期的 Basic )通常都擁有一個交互環(huán)境,用戶輸入一句代碼計算機就執(zhí)行一句代碼。
Java 屬于上述哪種類型?如果你認為 Java 不屬于上述任何一種類型,那么它是不是一種新的編程語言類型?
Java源程序需要編譯,但運行時需要即時“解釋”為本地CPU能執(zhí)行的機器指令,所以它不屬于“純”的編譯型或解釋型,而是一種混合類型。
有的同學很“絕”,他說:“Java是一種面向?qū)ο箢愋偷木幊陶Z言”。這句話還真是對的,我也給了分。
2. Java 中有兩個關鍵字: void 和 null ,它們有什么區(qū)別?
這題100%的學生都能答對,純粹是送分題。
3. 簡述“類(Class)”、“類庫(Class Library)”、“包(Package)”、“ Jar 文件”這四個概念間的聯(lián)系。
類庫其實是一個“統(tǒng)稱”,它是類的集合。包則是類庫的組織形式,它類似于C++中的namespace,可以解決類的同名問題。
Jar則是一個采用Zip格式壓縮的文件包 ,主要是為了方便Java組件的復用,簡化Java應用程序的部署和發(fā)布。Jar包中可以保存任意類型的多個文件和多級嵌套的
文件夾。比如JDK就包容了不少Jar壓縮包,你可以使用解壓縮工具(比如WinRAR)去查看它的內(nèi)容。可以把Jar文件看成是Java類庫的一個物理“載體”,之所以稱
其為“物理”的,是因為我們可以在計算機中直接“看見”并“操作”它。
在學習和探索知識的過程中,有的時候就必須注意清晰地分清各個似是而非的概念,這道題有好幾個同學就把這幾個概念間的關系弄亂了。
4. 面向?qū)ο蟮某绦蛟谶\行時會創(chuàng)建多個對象,這些對象之間通??梢韵嗷?“ 發(fā)送消息 ” ,談談你對 “ 對象之間發(fā)送消息 ” 這句話的理解,并編寫若干
句示例代碼展示對象之間發(fā)送消息的具體編程實現(xiàn)方法。
對象間的消息發(fā)送最基本的手段就是:一個對象執(zhí)有另一個對象的引用,然后,通這個對象引用調(diào)用對方的方法,存取對方的字段(或?qū)傩裕?
對象互發(fā)消息,其本質(zhì)目的就是為了交換信息。
除了上述這兩種直接方式之外,我們還可以通過一些第三方的媒價來實現(xiàn)對象間的信息交換:比如利用類的靜態(tài)字段,利用內(nèi)存映射文件,利用數(shù)據(jù)庫,利用
外部共享的“物理”文件等。
我在《.NET 4.0面向?qū)ο缶幊搪?》的第14章《對象間的協(xié)作與信息交換》中介紹了七八種單個、多個對象間消息發(fā)送和信息交換的方式,雖然是用C#實現(xiàn)
的,但其思想完全可用于Java中。
掌握這些編程技巧,對開發(fā)非常關鍵。
5. 加法運算符“+”可以施加于原始數(shù)值類型(比如 int )的變量,但我們發(fā)現(xiàn)一些對象類型(比如 Integer ) 的變量,也支持“+”運算:
Integer v1 = 100;
Integer v2 = 200;
System.out.println(v1+v2 ); //輸出: 300
這看上去好象 Integer 類型重載了 “ + ” 法運算符,一些編程語言比如 C ++可以為特定的類重載運算符,但 Java 本身并不支持運算符重載這一特性。依你的
理解或猜測, Java 是采用什么方法讓兩個 Integer 對象可以直接“相加”的?
上面代碼首先是調(diào)用Integer.valueOf方法將整數(shù)轉(zhuǎn)換為Integer對象,當兩個Integer對象相加時,其實是使用Integer.intValue方法取出其所“包裝”的整數(shù)值,相加之
后,再將結(jié)果輸出。
上述結(jié)論是通過分析javap反匯編示例代碼得到的。
諸如Java和C#之類的編程語言,許多現(xiàn)象已不僅僅是語法問題,編譯器在其中起了很重要的作用。我在課堂上已經(jīng)介紹過如何使用javap去反匯編.class文件,通
過閱讀Java編譯器生成的字節(jié)碼指令去弄明白java編譯器在后臺玩的把戲。
這道題主要是引導學生學編程語言不要僅學語法,要學會利用工具透過表面現(xiàn)象看本質(zhì)。
有的學生猜測Java可能是設計了另外的對象負責完成“+”運算,雖然與Java實際情況不符,但這個思路是可行的,我同樣給分。
6. 在一個很大的循環(huán)(比如循環(huán)10000000 次)中,如果需要進行字串的連接操作,通常我們者使用StringBuffer 取代String ,解釋這么做的理由。
絕大部分同學都答對了。但有的同學說:在大循環(huán)中使用String,會“浪費”大量的內(nèi)存,這句話是不準確的,因為Java有一個垃圾收集機制,在合適的時機會
出來回收不用的String對象,因此,這些內(nèi)存不能說是被“浪費”的,我們唯一可以說的是:
由于String對象是只讀的,使用它大量字串連接操作,將導致頻繁的內(nèi)存分配操作 ,這會嚴重地影響程序性能。
7. 現(xiàn)有兩個長度不同的數(shù)組:
int[] arr1 = new int[10];
int[] arr2 = new int[100];
那么以下語句能通過編譯嗎?
arr1 = arr2;
如果你認為可以通過編譯,得到這個結(jié)論的依據(jù)是什么?如果不能通過編譯,你認為其原因是什么?
可以通過編譯。此題考核學生知不知道 Java 中的數(shù)組屬于對象類型,知不知道對象變量相互賦值的含義。
8. 請看以下代碼 :
double d1=100.1;
double d2=1001/10;
System.out.println(d1==d2); // 輸出 : false
明明 d1 與 d2 是相等的 , 為什么程序運行時會輸出一個讓人意外的結(jié)果 : false ?
很多同學都指出1001/10 其實是“整除”,得到100 ,再轉(zhuǎn)為double ,所以d2=100.0 ,自然d1==d2 返回false 了。
由于我在課堂上曾展示過計算機難于精確表示雙精度數(shù),比較兩個double 變量是否相等應該檢測其差的絕對值是否在某個可以容忍的誤差范圍內(nèi),所以幾個同
學就往這個思路上去想了。
對這種情況,我沒扣分。
9. 當使用多個 catch 語句捕獲多個異常時, Java 規(guī)定捕獲 Exception 的 catch 語句必須排在最后,如下所示:
try { …… }
catch(ClassCastException ex){…… }
catch(NumberFormatException ex){…… }
catch(Exception ex){ …… } // 此句必須放在最后!
為什么會有這個限制?談談你是怎么理解的。
學生們幾乎 100% 答對此題,由于 Exception 是頂層類,放到前面會導致后面的 catch 語句不可能有機會運行。
10. 請看以下示例代碼:
String s1 = "Hello";
String s2 = "Hello";
System.out.println(s1 == s2); // 輸出: true
String s3 = new String("Hello");
String s4 = new String("Hello");
System.out.println(s3 == s4); // 輸出: false
請解釋一下為什么上述代碼中 “ System.out …” 兩句代碼輸出完全不同的結(jié)果 ?
這里面的關鍵在于 Java 常量池。 JVM 在裝載一個 .class 文件時,會在內(nèi)存中創(chuàng)建一個常量池。
“ Hello ”是字符串常量, Java 編譯器會將“ Hello ”放到常量池中,并給它一個索引:
const #28 = Asciz Hello;
以下兩句代碼:
String s1 = "Hello";
String s2 = "Hello";
將生成以下的字節(jié)碼指令:
0: ldc #2; //String Hello
2: astore_1
3: ldc #2; //String Hello
5: astore_2
上面的 #2 代表常量池中的第 2 項:
const #2 = String #28; // Hello
注意它引用常量池的第 28 項,前面已經(jīng)看到,第 28 項就是一個“ Hello ”字符串對象。
astore 指令將常量池中同一個“ Hello ”字符串對象的地址賦給了 s1 和 s2 ,所以, s1==s2 肯定返回 true 。
下面來看一下:
String s3 = new String("Hello");
所生成的字節(jié)碼指令:
// 創(chuàng)建 String 對象,對象引用被 Push 到操作數(shù)堆棧( operand stack )
// 常量池的第 5 項指向一個 CONSTANT_Class_info 類型的表項,這個表項將引用 String 類型
// 在程序運行時,會導致 JVM 裝載并連接 String 類型信息
22: new #5; //class java/lang/String
25: dup // 復制對象引用,再次壓入操作數(shù)堆棧,此復制的對象引用將用于調(diào)用構(gòu)造函數(shù)
26: ldc #2; //String Hello 裝載常量“ Hello ”
28: invokespecial #6;
//Methodjava/lang/String."<init>":(Ljava/lang/String;)V
// 調(diào)用 String 類的構(gòu)造函數(shù),它從操作數(shù)堆棧提取信息初始化 String 對象
31: astore_3 // 將創(chuàng)建好的對象引用保存到 s3 中
從上述分析可以清晰地看到, s3 與 s4 都引用不同的對象。所以, s3==s4 返回 fasle 。
現(xiàn)在,同學們對 JVM 的認識是不是更深入了一步?
現(xiàn)在 Java 程序員“遍地”都是,但其中高水平的不多,為什么?
一個很重要的原因就是淺嘗輒止,僅記住了一些語法結(jié)論,卻從不主動地去探索一下代碼背后的奧秘,怎會有提高?
我很早就在課堂上展示了 javap 的使用方法,并向同學們推薦了那本經(jīng)典的《 Inside the Java Virtual Machine 》,但我估計由于課業(yè)負擔重,沒幾個同學真的
去看了這本書,對此,我只能一聲嘆息。
多問幾個為什么,對事物刨根問底,這其實不是在學習,而是在探索了,這個過程中,你的能力會得到不斷地鍛煉和提高。
另外我要指出,同樣的學習方法可以直接用 .NET 領域,比如 .NET 有一個 ildasm 可以直接查看 .NET 程序集( .exe 和 .dll ,等價于 Java 中的 .class )中
的 IL 指令(對應于 Java 字節(jié)碼指令),有一個 Reflector 工具可以很方便地反匯編查看任意一個程序集的源碼,對應地, .NET 虛擬機—— CLR ,也與 JVM
有許多相似之處。
我在寫作《 .NET 4.0 面向?qū)ο缶幊搪劇窌r,就通過直接查看程序集的 IL 指令代碼,弄清楚了不少東西,也加深了對語言編譯器和虛擬機的認識。
象 Java 和 .NET 這種非常相近的平臺,下功夫弄清楚一個,你會發(fā)現(xiàn)學習與掌握另一個并不困難。計算機有很多東西是相通的。關鍵不在于學什么東西,
而是是否掌握了學習的科學方法,并且有一種不斷學習、勇于探索未知的精神。具備這種基本素質(zhì)的學生,我相信他日后的發(fā)展應該不會差的。
posted on 2011-02-19 16:39
鵬凌 閱讀(652)
評論(0) 編輯 收藏 所屬分類:
java