20155303 2016-2017-2 《Java程序設計》第六周學習總結


20155303 2016-2017-2 《Java程序設計》第六周學習總結

課堂筆記

  • 高效學習法推薦

看視頻學習(2h)→ 以代碼為中心看課本,思考運行結果並驗證(3h)→ 課后作業驗證(5h)→ 教材指導

【充分利用教材指導,積極思考遇到的問題,在實踐中學習,不要拘泥於記憶教材講解的知識點和概念。】

教材學習中的問題和解決過程

  • 『問題一』:以課本P306為例,args[0]args[1]代表什么?

『問題一解決』:java的主方法為:public static void main(String [] args)args[0]表示命令行輸入時傳的第一個參數,args[1]同理。例如執行以下程序:

運行java WhatIsArgs No1 No2命令可得到結果:No1No2

  • 『問題二』hasNextLine()nextLine()的用法?

『問題二解決』:查詢API文檔可知,hasNextLine()nextLine()均繼承自java.util.Scanner。它們的用法是,hasNextLine()用來判斷下一行是否存在,常用在while語句中,當且僅當下一行有輸入時返回true;而nextLine()返回值是當前行的剩余內容。

兩者具體使用方法可參考以下代碼:

  • 『問題三』:課本P316提到“如果在做對象串行化時,對象中某些數據成員不希望被寫出,則可以標上transient關鍵字”一句該如何理解?

『問題三解決』:一個對象只要實現了Serilizable接口,這個對象就可以被序列化,不過有些時候,一個類的有些屬性需要序列化,而其他屬性不需要被序列化。java的transient關鍵字為我們提供了便利,你只需要實現Serilizable接口,將不需要序列化的屬性前添加關鍵字transient,序列化對象的時候,這個屬性就不會序列化到指定的目的地中。

比如以下程序:

在上面的例子中,將屬性b前添加關鍵字transient,雖然我們序列化的對象b的屬性值為“Transient or not”,但是當我們反序列化之后發現這個屬性為空,說明這個屬性沒有進行序列化。

【關於什么是序列化,參考博客深入理解Java對象序列化

  • 『問題四』:守護線程與非守護線程

『問題四解決』:簡單來說,java可以創建兩種線程,即守護線程與非守護線程。非守護線程(User Thread用戶線程)就是平時創建的一般線程,而守護線程(Daemon Thread守護線程)是用來服務用戶線程的。

區分守護線程與非守護線程:當線程只剩下守護線程的時候,JVM就會退出.但是如果還有其他的任意一個用戶線程還在,JVM就不會退出。

setDaemon()與isDaemon()setDaemon方法用來設定一個線程。如果setDaemon(true)表示設定一個線程為Daemon線程。isDaemon則用來測試一個線程是否為守護線程。如果是,返回true。

  • 『問題五』:Thread常用方法以及狀態圖

『問題五解決』

常用方法:

start(); //啟動線程

getId(); //獲得線程ID

getName(); //獲得線程名字

getPriority(); //獲得優先權

isAlive(); //判斷線程是否活動

isDaemon(); //判斷是否守護線程

getState(); //獲得線程狀態

sleep(long mill); //休眠線程

join(); //等待線程結束

yield(); //放棄cpu使用權利

interrupt(); //中斷線程

currentThread(); //獲得正在執行的線程對象

Thread狀態圖:

  • 『問題六』:對於課本P334join()的介紹產生疑問:Thread B 什么時候加入主線程呢?是不是從join()方法出現的位置開始呢?

『問題六解決』:在不同位置調用join()方法,程序如下:

“嘗試一”運行結果:

“嘗試二”運行結果:

可以看出,程序啟動后主線程就開始了,調用join()之后把Thread B加入主線程流程中,執行完畢后再繼續執行原本的線程。

注:可以在join()指定時間,如join(1000)表示讓加入的線程執行1000毫秒,也就是1秒。1秒結束后線程可以繼續執行原本流程。

代碼調試中的問題和解決過程

本周跟視頻學習的過程中思考一個問題:字節流和字符流的優勢各在哪里呢?使用哪一個比較好呢?

答案是字節流。首先因為硬盤上的所有文件都是以字節的形式進行傳輸和保存的,包括圖片,mp3等等。但是字符只是在內存中才會形成,所以在開發過程中,字節流使用更加廣泛。

下面通過幾個例子總結了字節流的應用情況。

  • 『問題一』:向文件中寫入字符串

運行以下程序:

查看hello.txt會看到“你好”:

也可以向文件中一個字節一個字節地寫入字符串,運行結果同上:

  • 『問題二』:向文件中追加新內容

運行以下程序:

查看hello.txt會看到“你好DiWeijia”:

  • 『問題三』:讀取文件內容

運行以下程序,可以讀出hello.txt里的內容:

知識拓展

謝濤老師在之前的一篇博客中提出問題:如何把一個Java源文件里的注釋去掉(處理結果可以輸出到新的文件里),保證修改后源文件仍然能正常編譯,正確運行。得到婁老師的指點之后,明白這個問題的解決需要用到正則表達式

正則表通常被用來檢索、替換那些符合某個模式(規則)的文本。我們經常使用Windows/Dos下用於文件查找的通配符(wildcard),也就是* 和?。如果想查找某個目錄下所有的word文檔,我們會搜索 * .doc。在這里,* 會被解釋成任意的字符串。和通配符類似,正則表達式也是用來進行文本匹配的工具,只不過比起通配符,它能更精確地描述你的需求。

比如要求填寫5-12位的QQ號,就可以使用正則表達式:\d{5,12}$。表示匹配字符串的開始,$表示匹配字符串的結束,\d表示匹配數字,{5,12}表示數字為5-12位。這樣一來,如果用戶輸入能匹配這個表達式的話,就符合要求了。

像以上的“^”、“$”等都是正則表達式的元字符。元字符以及常用的正則表達式如下:(參考婁老師博客正則表達式入門

“去注釋”問題可以利用正則表達式的相關知識,結合之前學到的“轉義符”解決。基本思路是:對待分析的帶注釋段的字符串進行遍歷,聲明一個緩沖字符串變量來記錄非注釋的部分,最后返回這個緩沖字符串變量作為結果。這樣就能把去除注釋之后的文件保存下來了。可以從以下四個方面考慮:

1.考慮雙引號:雙引號中的注釋部分是不能去掉的,比如print("//Hello"World"/ * comment * /")。以下幾條都應在沒有雙引號的前提下。如果發現了開始雙引號,在匹配結束雙引號的時候要注意可能會遇到轉義雙引號,需要跳過以\開始的雙引號,從而匹配到正確的結束雙引號;

2.考慮 / * comment * / 形式的注釋 :當遇到 / * 部分便停止記錄,繼續往后遍歷到 * / 部分,實現跳過 / * * / 段;

3.考慮/ * comment / * inside * / out * /形式的嵌套注釋:聲明一個數字變量來記錄 / * 的開始的次數,遇到一個 / * 就+1,遇到一個 * / 就-1,實現嵌套匹配;

【注意】:注釋不能嵌套:/ * / * inside * / * /,所以這種情況不予考慮。感謝謝濤老師的指正:)

4.考慮雙斜杠注釋 發現 // 形式的字符串的時候表明遇到了雙斜杠注釋,這時候使用while循環繼續向后遍歷,直到發現一個換行符,從而跳過整個這一行;

正則表達式的應用領域非常廣,以上提到的這些只是一點皮毛。要想熟練掌握正則表達式的用法,還需要多動手多實踐。

代碼托管

上周考試錯題總結

  • 『問題一』

現有:

- list是一個合法的集合引用

- getCollection()返回一個合法集合的引用

哪個是合法的?

A.or(Object o ; list)

√B.for(Object o : getCollection())

C.for(Object o : list.iterator())

D.for(lterator i ; list.iterator() ; i.hasNext () )

√E.for(lterator i=list.iterator(); i.hasNext (); )

  • 『考點』

B選項是增強式for循環。增強式for循環能對數組和集合進行遍歷,使用上更加簡潔。D選項是普通循環,i操作了iterator()接口,如果沒有拋出異常,則i.hasNext()返回值為true。

  • 『問題二』

Which of the following methods will not compile? :

A.

private void method1(String name) {
if (name.equals("star"))
throw new IllegalArgumentException(name);
}

√B.

private void method2(int age) {
if (age > 30)
throw Exception();
}

C.

public double method5() throws Exception {
return 0.7;
}

√D.

protected double method4() throws Exception {
throw new Throwable();
}
  • 『考點』

B選項無法編譯,因為Exception是受檢異常,必須使用throws聲明此方法會拋出的異常類型或父類型。D選項無法編譯,因為子類不能拋出比父類更一般的異常。

  • 『問題三』

What is the output of the following code?

class EJava {
void method() {
try {
guru();
return;
} finally {
System.out.println("finally 1");
}
}
void guru() {
System.out.println("guru");
throw new StackOverflowError();
}
public static void main(String args[]) {
EJava var = new EJava();
var.method();
}
}

A.guru

finally 1

√B.guru

finally 1

Exception in thread "main" java.lang.StackOverflowError

C.guru

Exception in thread "main" java.lang.StackOverflowError

D.guru

E.The code fails to compile.

  • 『考點』

首先程序可以通過編譯。其次,StackOverflowError()是非受檢異常,方法guru()在try-catch塊中,異常會被捕捉。由於guru()本身沒有處理堆棧溢出錯誤,但method()定義了finally區塊,所以程序在執行完畢finally區塊之后將錯誤傳播至JVM,中斷程序。

結對及互評

本周結對學習情況

  • 結對同學學號20145202馬超

  • 結對學習內容:查看對方代碼,並對學習中遇到的疑問進行交流。解答對方博客中未解決的問題。

第六周博客互評情況

其他(感悟、思考等,可選)

  • 1、最近幾周的學習內容系統性和連貫性很強,所以要經常查詢API文檔,了解常用的類和方法以及其繼承架構。

  • 2、學習過程中應該把思考作為重中之重,這一點之前就領悟到了,不過在實踐之中經常被忽略。所以我們不應該單純地把代碼行數看做衡量自己學習情況的標准,理解得透徹了才能達到舉一反三的效果。按照這種方法學習不僅可以深刻理解所學知識,也提高了學習效率,減輕了學習負擔。

  • 3、不學則已,一學即專。心不能靜下來的時候寧可不看書。萬萬不可一邊打着學習的名義捧書研讀,一邊還在為其他事困擾,這樣只能欺騙自己“我真的學習了”,卻僅僅是耗費時間,而達不到理想的效果。

學習進度條

代碼行數(新增/累積) 博客量(新增/累積) 學習時間(新增/累積) 重要成長
目標 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

嘗試一下記錄「計划學習時間」和「實際學習時間」,到期末看看能不能改進自己的計划能力。這個工作學習中很重要,也很有用。
耗時估計的公式
:Y=X+X/N ,Y=X-X/N,訓練次數多了,X、Y就接近了。

參考:軟件工程軟件的估計為什么這么難軟件工程 估計方法

  • 計划學習時間:20小時

  • 實際學習時間:15小時

  • 改進情況:這周的效率跟之前比有了很大的提高,我想應該歸功於婁老師上節課提到的學習方法。以后的學習應該抓住重點,多思考,不要把時間浪費在照搬書上的代碼之類的無用功上。

(有空多看看現代軟件工程 課件
軟件工程師能力自我評價表
)

參考資料


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM