隨筆 - 64  文章 - 9  trackbacks - 0
          <2011年2月>
          303112345
          6789101112
          13141516171819
          20212223242526
          272812345
          6789101112

          常用鏈接

          留言簿(6)

          我參與的團隊

          隨筆分類(88)

          隨筆檔案(92)

          文章分類(142)

          文章檔案(182)

          天基成員

          學習園

          我的海角

          搜索

          •  

          積分與排名

          • 積分 - 183393
          • 排名 - 319

          最新評論

           

          一、判斷題(正確的描述打鉤,錯誤的打叉,每題 1 分,共 10 分)
          1.        一個 Java 源文件中只能定義一個公有類,并且類名必須與文件名一致。(對)

          2.        通過在程序中引入“ import javax.swing.*; ”語句,就可以使用 javax.swing 包中的所有類(包括其嵌套的子包中的類)。   (錯)

                 要使用嵌套子包中的類,必須再次添加 import 子句

          3.        J2SE 的功能是 J 2 ME 的一個子集。(錯)

          4.   Java 字節碼只有被裝入到內存中之后,才能被執行。(對)

              在當前計算機體系結構之下,CPU無法直接讀取保存于磁盤上的程序文件,這些文件所包容的指令必須被裝入到內存之后,CPU才能讀取。

          5.   Swing是一套GUI組件,采用了新的思路設計Java應用程序的界面,它完全地替換掉了原有的AWT。(錯)

              Swing仍然使用AWT的事件模型,并非完全拋棄。

             值得注意的NetBeans 6.9.1完成最新的更新組件后,創建Java桌面應用程序時,有了一個新的提示消息框:

           


           

              看來Oracle也知道Java在桌面上沒戲,干脆放棄了對Swing框架的進一步開發。已經存在這么多年的Swing框架被“新主人”拋棄,真不知道該說什么。

          6.   在編程時編寫過多的注釋,會使編譯之后生成的程序文件變大。(錯)

              放心, 編譯器會刪除所有的注釋。所以,哪怕你在程序中寫了一部長篇小說,也不會拖慢程序的運行速度。

          7.   Java Applet 可運行于瀏覽器中,這意味著瀏覽器本身就可以直接執行 Applet 程序。(錯)

              瀏覽器本身只認識HTML,它對其他類型信息的支持,比如Flash,Applet,Silverlight應用程序等都是通過啟動本地計算機安裝的附加插件來實現的。

          8.   JDK 5.0新增的枚舉類型( enum )是一個原始數據類型。(錯)

          9.   Java 中規定所有的方法都必須放到某個類中,不存在獨立于類的方法。(對)

          10.      面向對象軟件系統設計師們經常用到的 UML 是一種編程語言。(錯)

           


          二、簡答題(請將答案寫到答題紙上,注明題號。每題 4 分,共 40 分)
           

          1.   現代編程語言有兩種主要的類型:一種是“編譯型 ”的,比如 C ,程序源碼必須經過編譯才能運行;另一種是“解釋型 ”的,這種類型的語言(比如早期的 Basic )通常都擁有一個交互環境,用戶輸入一句代碼計算機就執行一句代碼。

              Java 屬于上述哪種類型?如果你認為 Java 不屬于上述任何一種類型,那么它是不是一種新的編程語言類型?

              Java源程序需要編譯,但運行時需要即時“解釋”為本地CPU能執行的機器指令,所以它不屬于“純”的編譯型或解釋型,而是一種混合類型。

              有的同學很“絕”,他說:“Java是一種面向對象類型的編程語言”。這句話還真是對的,我也給了分。

          2.   Java 中有兩個關鍵字: void 和 null ,它們有什么區別?

              這題100%的學生都能答對,純粹是送分題。

          3.   簡述“類(Class)”、“類庫(Class Library)”、“包(Package)”、“ Jar 文件”這四個概念間的聯系。

              類庫其實是一個“統稱”,它是類的集合。包則是類庫的組織形式,它類似于C++中的namespace,可以解決類的同名問題。

              Jar則是一個采用Zip格式壓縮的文件包 ,主要是為了方便Java組件的復用,簡化Java應用程序的部署和發布。Jar包中可以保存任意類型的多個文件和多級嵌套的

          文件夾。比如JDK就包容了不少Jar壓縮包,你可以使用解壓縮工具(比如WinRAR)去查看它的內容。可以把Jar文件看成是Java類庫的一個物理“載體”,之所以稱

          其為“物理”的,是因為我們可以在計算機中直接“看見”并“操作”它。

              在學習和探索知識的過程中,有的時候就必須注意清晰地分清各個似是而非的概念,這道題有好幾個同學就把這幾個概念間的關系弄亂了。

          4.   面向對象的程序在運行時會創建多個對象,這些對象之間通常可以相互 “ 發送消息 ” ,談談你對 “ 對象之間發送消息 ” 這句話的理解,并編寫若干

          句示例代碼展示對象之間發送消息的具體編程實現方法。

              對象間的消息發送最基本的手段就是:一個對象執有另一個對象的引用,然后,通這個對象引用調用對方的方法,存取對方的字段(或屬性)。

              對象互發消息,其本質目的就是為了交換信息。

              除了上述這兩種直接方式之外,我們還可以通過一些第三方的媒價來實現對象間的信息交換:比如利用類的靜態字段,利用內存映射文件,利用數據庫,利用

          外部共享的“物理”文件等。

              我在《.NET 4.0面向對象編程漫談 》的第14章《對象間的協作與信息交換》中介紹了七八種單個、多個對象間消息發送和信息交換的方式,雖然是用C#實現

          的,但其思想完全可用于Java中。

              掌握這些編程技巧,對開發非常關鍵。

          5.   加法運算符“+”可以施加于原始數值類型(比如 int )的變量,但我們發現一些對象類型(比如 Integer ) 的變量,也支持“+”運算:

           

              Integer v1 = 100;

              Integer v2 = 200;

              System.out.println(v1+v2 );  //輸出: 300

            這看上去好象 Integer 類型重載了 “ + ” 法運算符,一些編程語言比如 C ++可以為特定的類重載運算符,但 Java 本身并不支持運算符重載這一特性。依你的

          理解或猜測, Java 是采用什么方法讓兩個 Integer 對象可以直接“相加”的?

           

              上面代碼首先是調用Integer.valueOf方法將整數轉換為Integer對象,當兩個Integer對象相加時,其實是使用Integer.intValue方法取出其所“包裝”的整數值,相加之

          后,再將結果輸出。

              上述結論是通過分析javap反匯編示例代碼得到的。

              諸如Java和C#之類的編程語言,許多現象已不僅僅是語法問題,編譯器在其中起了很重要的作用。我在課堂上已經介紹過如何使用javap去反匯編.class文件,通

          過閱讀Java編譯器生成的字節碼指令去弄明白java編譯器在后臺玩的把戲。

              這道題主要是引導學生學編程語言不要僅學語法,要學會利用工具透過表面現象看本質。

              有的學生猜測Java可能是設計了另外的對象負責完成“+”運算,雖然與Java實際情況不符,但這個思路是可行的,我同樣給分。

           

          6.   在一個很大的循環(比如循環10000000 次)中,如果需要進行字串的連接操作,通常我們者使用StringBuffer 取代String ,解釋這么做的理由。

              絕大部分同學都答對了。但有的同學說:在大循環中使用String,會“浪費”大量的內存,這句話是不準確的,因為Java有一個垃圾收集機制,在合適的時機會

          出來回收不用的String對象,因此,這些內存不能說是被“浪費”的,我們唯一可以說的是:

              由于String對象是只讀的,使用它大量字串連接操作,將導致頻繁的內存分配操作 ,這會嚴重地影響程序性能。

           

          7.   現有兩個長度不同的數組:

           

              int[] arr1 = new int[10];

              int[] arr2 = new int[100];

             

              那么以下語句能通過編譯嗎?

           

              arr1 = arr2;

           

              如果你認為可以通過編譯,得到這個結論的依據是什么?如果不能通過編譯,你認為其原因是什么?

           

                 可以通過編譯。此題考核學生知不知道 Java 中的數組屬于對象類型,知不知道對象變量相互賦值的含義。

           

          8.   請看以下代碼 :

           

              double d1=100.1;

              double d2=1001/10;

              System.out.println(d1==d2);  // 輸出 : false

           

          明明 d1 與 d2 是相等的 , 為什么程序運行時會輸出一個讓人意外的結果 : false ?

              很多同學都指出1001/10 其實是“整除”,得到100 ,再轉為double ,所以d2=100.0 ,自然d1==d2 返回false 了。

              由于我在課堂上曾展示過計算機難于精確表示雙精度數,比較兩個double 變量是否相等應該檢測其差的絕對值是否在某個可以容忍的誤差范圍內,所以幾個同

          學就往這個思路上去想了。

              對這種情況,我沒扣分。

          9.   當使用多個 catch 語句捕獲多個異常時, Java 規定捕獲 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 …” 兩句代碼輸出完全不同的結果 ?

           

                   這里面的關鍵在于 Java 常量池。 JVM 在裝載一個 .class 文件時,會在內存中創建一個常量池。

                   “ Hello ”是字符串常量, Java 編譯器會將“ Hello ”放到常量池中,并給它一個索引:

           

              const #28 = Asciz       Hello;

           

                   以下兩句代碼:

           

              String s1 = "Hello";

              String s2 = "Hello";

           

          將生成以下的字節碼指令:

           

             0:   ldc     #2; //String Hello

             2:   astore_1

             3:   ldc #2; //String Hello

             5:   astore_2

           

                   上面的 #2 代表常量池中的第 2 項:

           

              const #2 = String       #28;    //  Hello

           

                   注意它引用常量池的第 28 項,前面已經看到,第 28 項就是一個“ Hello ”字符串對象。

                   astore 指令將常量池中同一個“ Hello ”字符串對象的地址賦給了 s1 和 s2 ,所以, s1==s2 肯定返回 true 。

                   下面來看一下:

                  String s3 = new String("Hello");

           

          所生成的字節碼指令:

           

              // 創建 String 對象,對象引用被 Push 到操作數堆棧( operand stack )

              // 常量池的第 5 項指向一個 CONSTANT_Class_info 類型的表項,這個表項將引用 String 類型

              // 在程序運行時,會導致 JVM 裝載并連接 String 類型信息

             22:  new     #5; //class java/lang/String        

              25:  dup   // 復制對象引用,再次壓入操作數堆棧,此復制的對象引用將用于調用構造函數

             26:  ldc     #2; //String Hello    裝載常量“ Hello ”

             28:  invokespecial   #6;  

              //Methodjava/lang/String."<init>":(Ljava/lang/String;)V

              // 調用 String 類的構造函數,它從操作數堆棧提取信息初始化 String 對象

             31:  astore_3  // 將創建好的對象引用保存到 s3 中

           

                   從上述分析可以清晰地看到, s3 與 s4 都引用不同的對象。所以, s3==s4 返回 fasle 。

                   現在,同學們對 JVM 的認識是不是更深入了一步?

                   現在 Java 程序員“遍地”都是,但其中高水平的不多,為什么?

                   一個很重要的原因就是淺嘗輒止,僅記住了一些語法結論,卻從不主動地去探索一下代碼背后的奧秘,怎會有提高?

                   我很早就在課堂上展示了 javap 的使用方法,并向同學們推薦了那本經典的《 Inside the Java Virtual Machine 》,但我估計由于課業負擔重,沒幾個同學真的

          去看了這本書,對此,我只能一聲嘆息。

                   多問幾個為什么,對事物刨根問底,這其實不是在學習,而是在探索了,這個過程中,你的能力會得到不斷地鍛煉和提高。

                   另外我要指出,同樣的學習方法可以直接用 .NET 領域,比如 .NET 有一個 ildasm 可以直接查看 .NET 程序集( .exe 和 .dll ,等價于 Java 中的 .class )中

          的 IL 指令(對應于 Java 字節碼指令),有一個 Reflector 工具可以很方便地反匯編查看任意一個程序集的源碼,對應地, .NET 虛擬機—— CLR ,也與 JVM

          有許多相似之處。

                   我在寫作《 .NET 4.0 面向對象編程漫談》時,就通過直接查看程序集的 IL 指令代碼,弄清楚了不少東西,也加深了對語言編譯器和虛擬機的認識。

                   象 Java 和 .NET 這種非常相近的平臺,下功夫弄清楚一個,你會發現學習與掌握另一個并不困難。計算機有很多東西是相通的。關鍵不在于學什么東西,

          而是是否掌握了學習的科學方法,并且有一種不斷學習、勇于探索未知的精神。具備這種基本素質的學生,我相信他日后的發展應該不會差的。

           

           

           

          posted on 2011-02-19 16:39 鵬凌 閱讀(655) 評論(0)  編輯  收藏 所屬分類: java
          主站蜘蛛池模板: 鸡东县| 南汇区| 东乌| 怀集县| 清苑县| 马龙县| 丰城市| 德兴市| 安吉县| 平陆县| 黄冈市| 岳普湖县| 隆回县| 和静县| 军事| 宿迁市| 乡城县| 阿拉善左旗| 台东市| 香港 | 安仁县| 琼海市| 和静县| 东乡| 华蓥市| 巫山县| 平安县| 靖边县| 亳州市| 舒城县| 武强县| 黑河市| 浑源县| 平舆县| 尤溪县| 乳源| 阳春市| 北安市| 德州市| 聂拉木县| 上思县|