20145207 《Java程序设计》第5周学习总结
前言:先聊兩句,上午電路實習,剛開始沒多久就讓電烙鐵燙了,倒霉催的~晚上來這里接著弄代碼,透心涼心飛揚~
教材學習內容總結
一、異常處理
1.語法與繼承結構
使用try、catch: Java中所有錯誤都會被包裝成對象,可以嘗試(try)執行程序并捕捉(catch)代表錯誤的對象后做一些處理。使用了try、catch語法,JVM會嘗試執行try區塊中的程序代碼,如果發生錯誤,執行程序會跳離錯誤發生點,然后比對catch括號中聲明的類型,是否符合被拋出的錯誤對象類型,如果是就執行catch中的程序代碼。
程序中總有一些意想不到的狀況所引發的錯誤,Java中的錯誤也以對象方式呈現為java.lang.Throwable的各種子類實例。只要能捕捉包裝錯誤的對象,就可以針對該錯誤做一些處理。
在這里舉一個書上的列子關于使用try和catch的例子。
package ch08;
?
import java.util.Scanner;
public class Average {
??? public static void main(String[] args) {
??????? Scanner console = new Scanner(System.in);
??????? double sum = 0;
??????? int count = 0;
??????? while (true) {
??????????? int number = console.nextInt();
??????????? if (number == 0) {
??????????????? break;
??????????? }
??????????? sum += number;
??????????? count++;
??????? }
??????? System.out.printf("平均 %.2f%n", sum / count);
??? }
}
在這個程序中,輸入正確的數字,會計算出平均數,結果如下:
?????
?
?????????
但是,若是不小心輸入了并非int的值,就會出現如下的情況:
?
這是另一個關于輸入錯誤的代碼,對其一部分進行了判斷并糾正
package ch08;
?
import java.util.Scanner;
public class Average {
??? public static void main(String[] args) {
??????? Scanner console = new Scanner(System.in);
??????? double sum = 0;
??????? int count = 0;
??????? while (true) {
??????????? int number = console.nextInt();
??????????? if (number == 0) {
??????????????? break;
??????????? }
??????????? sum += number;
??????????? count++;
??????? }
??????? System.out.printf("平均 %.2f%n", sum / count);
??? }
}
若是輸入錯誤,就會出現以下的結果:
?
2.異常繼承結構
錯誤會被包裝為對象,這些對象均可拋出,因此設計錯誤對象都繼承自java.lang.Throwable類,Throwable定義了取得錯誤信息、堆棧追蹤(Stack Trace)等方法,它有兩個子類:java.lang.Error與java.lang.Exception。在此簡述一下Error類與Exception類的區別,在Java中對于比較嚴重的問題,是通過Error類來進行描述的,而對于非嚴重的問題,則是通過Exception類來進行描述的。對于Error,一般不編寫針對性的代碼對其進行處理,因為此時已經超出了JVM的運行能力范圍之外了。
單就語法與繼承架構上來說,如果某個方法聲明會拋出Throwable或子類實例,只要不是屬于Error或java.lang.RuntimeException或其子類實例,就必須明確使用try、catch語法加以處理,或者在方法中用throws聲明這個方法會拋出異常,否則會編譯失敗,throws的使用也提高了代碼的安全性。
Exception中有一個特殊的子類異常叫RuntimeException異常,就是運行時異常,它的特點是如果在函數內容拋出該異常,函數上可以不用聲明,編譯一樣通過,如果在函數上聲明了該異常,調用者可以不用進行處理,編譯一樣通過。Exception或其子對象,但非屬于RuntimeException或其子類對象,稱為受檢異常(Checked Exception),屬于RuntimeException衍生出來的類實例亦稱為非受檢異常(Unchecked Exception),受檢異常存在的目的,在于API設計者實現某方法時,某些條件成立時會引發錯誤,而且認為調用方法的客戶端有能力處理錯誤,要求編譯程序提醒客戶端必須明確處理錯誤,不然不可通過編譯,API客戶端無權選擇要不要處理。
如果父類異常對象在子類異常對象前被捕捉,則catch子類異常對象將永遠不會被執行,編譯程序會檢查出這個錯誤。從JDK7開始,可以使用多重捕捉語法,不過仍需注意異常的繼承,catch括號中列出的異常不得有繼承關系,否則會發生編譯錯誤。
在catch區塊進行完部分錯誤處理之后,可以使用throw將異常再度拋出,這里將throw和throws要區分開,throws使用在函數上,后面跟的是異常類,可以跟多個,用逗號隔開,而throw是使用在函數內,后面跟的是異常對象。
若想得知異常發生的根源,以及多重方法調用下異常的堆棧傳播,可以利用異常對象自動收集的堆棧追蹤來取得相關信息,例如調用異常對象的printStackTrace()、getStackTrace()等方法。要善于堆棧追蹤,前提是程序代碼中不可有私吞異常的行為、對異常做了不適當的處理,或顯示了不正確信息。在使用throw重拋異常時,異常的追蹤堆棧起點,仍是異常的發生根源,而不是重拋異常的地方。如果想要讓異常堆棧起點為重拋異常的地方,可以使用fillInStackTrace(),這個方法會重新裝填異常堆棧,將起點設為重拋異常的地方,并返回Throwable對象。
3.異常與資源管理
程序中因錯誤而拋出異常時,原本的執行流程就會中斷,拋出異常處之后的程序代碼就不會被執行,如果程序開啟了相關資源,是否在使用完畢后被關閉了呢?
finally區塊
最后一定要執行關閉資源的動作,try、catch語法還可以搭配finally,無論try區塊中有無發生異常,若撰寫finally區塊,則finally區塊一定會被執行。舉一個例子:
package ch08;
?
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Scanner;
?
public class FileUtil {
??? public static String readFile(String name) throws FileNotFoundException {
??????? StringBuilder text = new StringBuilder();
??????? try {
??????????? Scanner console = new Scanner(new FileInputStream(name));
??????????? while (console.hasNext()) {
??????????????? text.append(console.nextLine()).append('\n');
??????????? }
??????? } catch (FileNotFoundException ex) {
??????????? ex.printStackTrace();
??????????? throw ex;
??????? }
??????? return text.toString();
??? }
}
由于finally區塊一定會被執行,在這個范例中scanner原先是null,若FileInputStream創建失敗,則scanner就有可能還是null,因此在finally區塊中必須先檢查scanner是否有參考對象,有的話才進一步調用close()方法,否則scanner參考至null又打算調用close()方法,反而會拋出NullPointerException。
想要嘗試關閉資源(Try-With-Resources)的對象,是撰寫在try之后的括號中,如果無須catch處理任何異常,可以不用撰寫,也不要撰寫finally。嘗試關閉資源語法可套用的對象,必須操作java.lang.AutoCloseable接口,該語法也可以同時關閉兩個以上的對象資源,只要中間以分號隔開。在try的括號中,越后面撰寫的對象資源會越早被關閉。
二、Collection與Map
1.認識Collection架構
JavaSE提供了滿足各種需求的API,在使用這些API前,建議先了解其繼承與接口的操作架構,才能了解何時該采用哪個類,以及類之間如何彼此合作,而不會淪為死背API或抄寫范例的境界。
收集對象的行為,像是新增對象的add()方法、移除對象的remove()方法等,都是定義在java.util.Collection中。既然可以收集對象,也要能逐一取得對象,這就是java.lang.Iterable定義的行為,它定義了iterable()方法返回java.util.Iterator操作對象,可以讓你逐一取得收集的對象。Collection接口中有三個子接口,分別是List、Set和Queue。如果希望收集時記錄記錄每個對象的索引順序,并可依索引取回對象,可以使用java.util.List接口,如果希望收集的對象不重復,具有集合的行為,可以使用java.util.Set接口,如果希望收集對象時以隊列方式,收集的對象假如至尾端,取得對象時從前端,則可以使用java.util.Queue接口,如果希望對Queue的兩端進行加入、移除等操作,則可以使用java.util.Deque。
2.鍵值對應的Map
就如同網絡搜素,根據關鍵字可找到對應的數據,程序設計中也常有這類的需求,根據某個鍵來取得對應的值。可以事先利用java.util.Map接口操作對象來建立鍵值對應數據,之后若要取得值,只要用對應的鍵,只要用對應的鍵就可以迅速取得。
常用Map操作類有HashMap、TreeMap和Properties。HashMap的特點是線程不安全,速度快,允許存放null 鍵,null值,TreeMap會對鍵進行排序,條件是作為鍵的對象必須操作Comparable接口,或者是在創建TreeMap時指定操作Comparable接口的對象,Properties的setProperty()可以指定字符串類型的鍵值,getProperty()可以指定字符串類型的鍵,取回字符串類型的值,通常稱為屬性名稱與屬性值。
教材學習中的問題和解決過程
書中P295 MapKeyValue.java運行結果與書中采用HashMap顯示不同
import java.util.*;
import static java.lang.System.out;
?
public class MapKeyValue {
public static void main(String[] args) {
??? Map<String, String> map = new HashMap<>();
??? map.put("one", "一");
??? map.put("two", "二");
??? map.put("three", "三");
???
??? out.println("顯示鍵");
??? // keySet()返回set
??? map.keySet().forEach(key -> out.println(key));
???
??? out.println("顯示值");
??? // values()返回Collection
??? map.values().forEach(key -> out.println(key));
}
}
代碼調試中的問題和解決過程
在這兩章中我發現了有些東西按照書上來的話,是沒有辦法編譯通過的,還有就是例如266頁的代碼,他也是前后使用的變量名不一樣,前面定義的是object o,后面就拉過來一個elem,我覺得書上有錯誤是正常的,剛好可以順便檢測我們對于書上以前的內容是否真的了解,以及是否看懂了這段代碼。附上266頁的代碼:
package ch08;
?
public class SimpleLinkedList {
??? private class Node {
??????? Node(Object o) {
??????????? this.o = o;
??????? }
??????? Object o;
??????? Node next;
??? }
??? private Node first;
?
??? public void add(Object o) {
??????? Node node = new Node(o);
??????? if (first == null) {
??????????? first = node;
??????? } else {
??????????? append(node);
??????? }
??? }
?
??? private void append(Node node) {
??????? Node last = first;
??????? while (last.next != null) {
??????????? last = last.next;
??????? }
??????? last.next = node;
??? }
?
??? public int size() {
??????? int count = 0;
??????? Node last = first;
??????? while (last != null) {
??????????? last = last.next;
??????????? count++;
??????? }
??????? return count;
??? }
?
??? public Object get(int index) {
??????? checkSize(index);
??????? return findElemOf(index);
??? }
?
??? private void checkSize(int index) throws IndexOutOfBoundsException {
??????? int size = size();
??????? if (index >= size) {
??????????? throw new IndexOutOfBoundsException(
??????????????????? String.format("Index: %d,Size: %d", index, size));
??????? }
??? }
?
??? private Object findElemOf(int index) {
??????? int count = 0;
??????? Node last = first;
??????? while (count < index) {
??????????? last = last.next;
??????????? count++;
??????? }
??????? return last.o;
??? }
?
?
}
在收集對象之后,對對象進行排序是常用的動作,你不用親自操作排序算法,java.util.Collections提供有sort()方法。由于必須有索引才能進行排序,因此Collections的sort()方法接受List操作對象。
import java.util.*;
public class Sort {
??? public static void main(String[] args) {
??????? List numbers = Arrays.asList(10,2,3,1,9,15,4);
??????? Collections.sort(numbers);
??????? System.out.println(numbers);
??? }
}
心得與體會
心得:實習好無聊~體會:實習完敲代碼好累…
轉載于:https://www.cnblogs.com/20145207lza/p/5819427.html
總結
以上是生活随笔為你收集整理的20145207 《Java程序设计》第5周学习总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux定时任务Crontab学习笔记
- 下一篇: 回到学校的第三天