20155303 2016-2017-2 《Java程序設計》第七周學習總結
教材學習中的問題和解決過程
- 『問題一』:
SimpleDateFormat中每個字符的含義都是什么?
『問題一解決』:API文檔中有詳細的說明:

比如以下程序,我定義的格式是 yyyy-ww-DD ,輸出結果表示當前日期是該年第14周,第97天。


- 『問題二』:課本P435提到
clone()復制對象的功能,這屬於創建對象的方式嗎?
『問題二解決』: clone() 復制對象與 new 都是創建對象的方式。之前課本上曾介紹過淺層復制(Shallow Copy)與深層復制(Deep Copy),這次借助 clone() 進一步學習。
【復制參考與復制對象】:回顧之前學過的“復制參考”,編寫以下程序:

當執行完Person p1 = p;之后真的創建了一個新對象嗎?我們來看一下打印結果:

可以看到打印的地址值是相同的。也就是說,這一步只實現了引用的復制,也就是p1與p指向了一個相同的對象“Person("Justin", 20150001)”。
而clone()能夠實現復制對象,而不僅僅是復制參考。以下面這個程序為例:

打印結果為:

可以看出,clone()重新分配內存,而不是把原對象的地址賦給了一個新的引用變量。
【淺拷貝與深拷貝】:繼續分析上例,ID是基本數據類型,直接將數值拷貝過來就行。但是name是String類型的,它只是一個引用,指向一個真正的String對象,那么對它的拷貝有兩種方式:
①直接將源對象中的name的引用值拷貝給新對象的name字段;
②根據原Person對象中的name指向的字符串對象創建一個新的相同的字符串對象,將這個新字符串對象的引用賦給新拷貝的Person對象的name字段。
這兩種拷貝方式分別叫做淺拷貝和深拷貝。
修改上面的代碼,如果name的地址值相同,說明兩個對象的name都指向同一個String對象,是淺拷貝;如果兩個對象的name的地址值不同,那么就說明指向不同的String對象,也就是在拷貝對象的時候,同時拷貝了name引用的String對象,也就是深拷貝。

運行結果如下:

name的地址值是相同的,所以這種拷貝方式是淺拷貝。
那么如何實現深拷貝呢?我們必須在類中實現Cloneable接口,並且重寫clone方法,創建一個拷貝類的對象,如下程序:


打印結果為:

可以看到,兩個對象的p指向的不是同一個對象,這就是深拷貝。
- 『問題三』:課本P435提到“想比較兩個Calendar”的時間日期先后,可以使用
after()或before()方法。那么,這兩個方法具體怎么使用呢?
『問題三解決』:查詢API文檔可知,after()返回值為布爾類型,其等價於compareTo(when)>0,為真返回true,否則返回false。before()同理,等價於compareTo(when)<0。

代碼調試中的問題和解決過程
- 『問題一』:運行課本P432
HowOld程序時,忽略了L類型轉換,得到了下面錯誤的結果(433歲!?):

在365*24*60*60*1000后面添加L或l得到正確輸出:

『問題一解決』:365*24*60*60*1000的計算結果是31536000000,超出了int范圍,在二進制中只保留后32位,為1471228928,因此會出現以上錯誤結果。使用計算器或許能更加清晰地展示出來:


- 『問題二』:關於
System.currentTimeMills()方法的使用問題。
『問題二解決』:查詢API文檔可知,currentTimeMills()返回值代表1970年1月1日0時0分0秒0毫秒至今經過的毫秒數。

考慮到這一點,可以調用該方法計算程序運行時間。以下面這個程序為例,在主線程開始和結束時分別調用currentTimeMills()方法,計算差值即為程序運行時間(單位:毫秒):

需要注意的是,同一程序程序運行時間也有可能不同,這與此時CPU狀態有關,所以此方法只能大致估計程序的運行時間。不過可作為程序優化的一點參考。
代碼托管


上周考試錯題總結
- 『題目一』:
下面哪條命令可以把 f1.txt 復制為 f2.txt ?(AC)
A .cp f1.txt f2.txt
B .copy f1.txt f2.txt
C .cat f1.txt > f2.tx
D .cp f1.txt | f2.tx
E .copy f1.txt | f2.tx
『考點』:copy是Windows下的命令。cat f1.txt > f2.tx 通過輸出重定向實現了復制。
- 『題目二』:
Given an instance of a Stream, s, and a Collection, c, which are valid ways of creating a parallel stream? (Choose all that apply.)
給定一個Stream的實例s, 一個Collection的實例c, 下面哪些選項可以創建一個並行流?(DF)
A .new ParallelStream(s)
B .c.parallel()
C .s.parallelStream()
D .c.parallelStream()
E .new ParallelStream(c)
F .s.parallel()
『考點』:Parallelstream()方法不存在,“P”不能大寫,所以A和E是不正確的。API中對parallel()的定義為:在Stream類中從現有流創建一個並行流,因此F是正確的,C是錯誤的。API中對parallelstream()的定義為:在Collection類中從一個集合創建一個並行流,因此D是正確的,B是錯誤的。
- 『題目三』:
Which of the following statements about the Callable call() and Runnable run() methods are correct? (Choose all that apply.) (ACDF)(My answer:CD)
A .Both can throw unchecked exceptions.
B .Callable takes a generic method argument.
C .Callable can throw a checked exception.
D .Both can be implemented with lambda expressions.
E .Runnable returns a generic type.
F .Callable returns a generic type.
G .Both methods return void
『考點』:查詢API文檔關於Callable接口的說明可以看到,Callable支持泛型,且Callable和Runable都能拋出非受檢異常,而能拋出受檢異常的只有Callable。

- 『題目四』:
What are some reasons to use a character stream, such as Reader/Writer, over a byte stream, such as InputStream/OutputStream? (Choose all that apply.)
在下列哪些情況下使用字符流(比如Reader/Writer)而不使用字節流(比如InputStream/OutputStream)?(AC)
A .More convenient code syntax when working with String data
B .Improved performance
C .Automatic character encoding
D .Built-in serialization and deserialization
E .Character streams are high-level streams
F .Multi-threading support
『考點』:
A:字符流包含能夠非常便利處理字符串數據的方法,所以A是正確的;C:字符流有其特有的編碼方式,能夠自動處理字符編碼問題,C也是正確的。
其他選項,如B:性能改進,D:內置的序列化和反序列化,E:字符流是更高級的流,F:字符流支持多線程等等,這些說法都是不相關,或是不正確的。
- 『題目五』:
Assuming / is the root directory, which of the following are true statements? (Choose all that apply.)(A)
A ./home/parrot is an absolute path.
B ./home/parrot is a directory.
C ./home/parrot is a relative path.
D .The path pointed to from a File object must exist.
E .The parent of the path pointed to by a File object must exist.
『考點』:
根目錄開始的路徑是絕對路徑,所以A是正確的,C是錯誤的。B是不正確的,因為路徑可能是文件系統中的文件(file)或目錄(directory)。文件對象可以指向文件系統中不存在的路徑,所以D和E是錯誤的。
- 『題目六』:
What is the result of executing the following code? (Choose all that apply.)(BDE)
String line;
Console c = System.console();
Writer w = c.writer();
if ((line = c.readLine()) != null)
w.append(line);
w.flush();
A .The code runs without error but prints nothing.
B .The code prints what was entered by the user.
C .An ArrayIndexOutOfBoundsException might be thrown.
D .A NullPointerException might be thrown.
E .An IOException might be thrown.
F .The code does not compile.
『考點』:這是從控制台讀取一行並將其寫入控制台的正確代碼,B正確;查詢API文檔可知,調用console()方法可能會拋出NullPointerException異常,D正確;調用append()方法可能會拋出IOException異常。


結對及互評
本周結對學習情況
-
結對同學學號20145202馬超
-
結對學習內容:查看代碼互相學習;另外非常感謝馬超同學針對實驗一我編寫的“學生成績管理系統”程序提出的建議!(詳見我的博客《Java程序設計》實驗一(Java開發環境的熟悉)實驗報告)對於我其他程序中存在的問題,也歡迎同學們指正~
第七周博客互評情況
(稍后更新)
其他(感悟、思考等,可選)
這周的考試再一次給我們敲響警鍾,只看不動手,只讀不思考,都無法真正掌握。比如題中出現了一部分異常處理的知識,如果只靠死記硬背而不查詢API文檔,費時費力還很難達到靈活應用。這周學習任務比較輕松,可以利用這個機會鞏固前面所學知識,夯實基礎。
學習進度條
| 代碼行數(新增/累積) | 博客量(新增/累積) | 學習時間(新增/累積) | 重要成長 | |
|---|---|---|---|---|
| 目標 | 5000行 | 30篇 | 400小時 | |
| 第一周 | 16/16 | 1/1 | 18/18 | 初步認識了Java |
| 第二周 | 219/235 | 1/2 | 28/46 | 學習了Java的基本語法知識 |
| 第三周 | 766/1001 | 1/3 | 23/69 | 了解對象與參考的關系,以及封裝的概念與實現 |
| 第四周 | 984/1985 | 1/4 | 18/87 | 學習了繼承與多態的關系,以及接口的多態操作 |
| 第五周 | 866/2851 | 1/5 | 12/99 | 學習了異常處理,學會使用Collection收集對象 |
| 第六周 | 664/3515 | 1/6 | 15/114 | 認識字節流和字符流的繼承架構,學習線程與並行API |
| 第七周 | 469/3984 | 1/7 | 13/127 | 認識Date與Calender |
嘗試一下記錄「計划學習時間」和「實際學習時間」,到期末看看能不能改進自己的計划能力。這個工作學習中很重要,也很有用。
耗時估計的公式
:Y=X+X/N ,Y=X-X/N,訓練次數多了,X、Y就接近了。
-
計划學習時間:10小時
-
實際學習時間:13小時
(有空多看看現代軟件工程課件:軟件工程師能力自我評價表)
