面向對象先導學習筆記
面向對象先導學習筆記
經過了Python、C語言和數據結構的學習,感覺對於Java這門新學習的語言上手速度明顯快了許多。在學習Java的過程中,個人覺得Java的語法規則在很大程度上與C類似,但是在設計程序和具體實現的過程中,更偏向於Python的思路,尤其是對於方法的調用和自帶數據結構的使用方面。
數據類型的Java實現
Java自帶了大量的數據類型,在完成作業的過程中,個人嘗試通過手寫二叉樹完成問題,但是與Java自帶的數據結構相比,無論是在穩定性和運行速度方面都有所欠缺。但是通過自己的摸索和嘗試,在一定程度上加深了對於數據結構本身和Java語法的了解。
例如,以二叉樹為例,C語言的二叉樹構造方法如下:
1 typedef struct Btree 2 { 3 int n; 4 struct Btree *lnode, *rnode; 5 }btree;
在C語言中,左右子樹是依靠指針,將地址存儲在節點中,而在Java中沒有指針的概念,但是可以在類中包含同一個類的數據,在C語言中,在 struct 中包含同一個 struct 類型的數據是不被允許的。Java實現二叉樹時,直接在節點中存儲左右節點本身,使用層層嵌套的方式實現二叉樹。
1 public class Node 2 { 3 int n; 4 Node lnode; 5 Node rnode;6 public Node() 7 { 8 this.n = 0; 9 this.lnode = null; 10 this.rnode = null; 11 } 12 }
以二叉樹為例,其它數據類型的構造方法與此類似,涉及到的算法大同小異,下面是Java構造的BST樹及其在進行插入、查找和遍歷等操作時的算法:
1 import java.util.Vector; 2 3 public class Node 4 { 5 int n; 6 Node lnode; 7 Node rnode;8 public Node() 9 { 10 this.n = 0; 11 this.lnode = null; 12 this.rnode = null; 13 } 14 15 public int cmp(int s) 16 { 17 if (n < s) 18 return -1; 19 else if (n == s) 20 return 0; 21 else 22 return 1; 23 } 24 25 public Node getLnode() 26 { 27 return this.lnode; 28 } 29 30 public Node getRnode() 31 { 32 return this.rnode; 33 } 34 35 public Node setLnode(Node s) 36 { 37 this.lnode = s; 38 return this.lnode; 39 } 40 41 public Node setRnode(Node s) 42 { 43 this.rnode = s; 44 return this.rnode; 45 } 46 47 } 48 49 50 public class BST 51 { 52 Node root; 53 54 public BST() 55 { 56 this.root = null; 57 } 58 59 public BST(Node r) 60 { 61 this.root = r; 62 } 63 64 public void insert(Node p, int i) 65 { 66 if (this.root == null) 67 { 68 this.root = new Node(i); 69 return; 70 } 71 else 72 { 73 int result = p.cmp(i); 74 if (result > 0) 75 { 76 if (p.getLnode() == null) 77 { 78 Node r = new Node(i); 79 p.setLnode(r); 80 return; 81 } 82 else 83 insert(p.getLnode(), i); 84 } 85 else 86 { 87 if (p.getRnode() == null) 88 { 89 Node r = new Node(i); 90 p.setRnode(r); 91 return; 92 } 93 else 94 insert(p.getRnode(), i); 95 } 96 } 97 } 98 99 public void printTree(Node p) 100 { 101 if (p.getLnode() != null) 102 { 103 printTree(p.getLnode()); 104 } 105 p.print();//打印該節點數據 106 if (p.getRnode() != null) 107 { 108 printTree(p.getRnode()); 109 } 110 return; 111 } 112 113 public void search(Node p, String s) 114 { 115 if (p == null) 116 { 117 return; 118 } 119 else 120 { 121 if (p.cmp(s) > 0) 122 { 123 // 查左子樹 124 search(p.getLnode(), s); 125 } 126 else if (p.cmp(s) < 0) 127 { 128 // 查右子樹 129 search(p.getRnode(), s); 130 } 131 else 132 { 133 // 找到該值 134 p.print(); 135 return; 136 } 137 } 138 } 139 140 }
Java的鍵盤/文件輸入
在完成課上和課下作業的過程中,Java的文件輸入和控制臺輸入同樣是一個新接觸到的內容,與C和Python相比較為繁瑣,經過搜索和學習,以 Scanner 為例的輸入實現方法如下: 在使用 Scanner 進行文件輸入之前,需要 import 以下三個包:
1 import java.io.FileInputStream; 2 import java.io.FileNotFoundException; 3 import java.util.Scanner;
第二個用於處理異常,同時需要在進行文件輸入操作的方法後添加異常情況處理,例如:
1 public static void main(String args[]) throws FileNotFoundException{...}
在執行操作時按照以下語法:
1 String name = "FILENAME"; 2 FileInputStream inputStream = new FileInputStream(name); 3 Scanner scan = new Scanner(inputStream, "ASCII"/*"UTF-8"*/);
對於鍵盤輸入,只需 import Scanner 即可,創建 Scanner 的用法如下:
1 Scanner wordScanner = new Scanner(System.in);
在學習Java和完成作業的過程中,個人認為主要的難點在於從C語言到Java語言程序設計思路的轉換,在使用C語言進行程序設計時,完全是依靠自己的思路,自底向上實現程序的每一個部分,而使用Java時,更多的要關註自己的想法與Java的內嵌數據類型和方法的契合度,並適當做出改變以更好的利用已有的方法。在完成最初一兩次的作業時,很少使用Java自帶的方法,在逐漸熟悉之後才開始較為熟練的查找方法和使用。
例如在完成第四次作業時使用的 HashMap ,與最初的構想並不完全相同,最終使用了嵌套的方式,將首單詞、末單詞和詞頻三個數據進行了存儲。
第四次作業中使用了 HashMap 這一數據類型,與第三次手寫的BST樹相比,無論是運行的速度和程序的穩定性方面都有所提高,而且大大簡化了程序設計的步驟。在對 HashMap 按 key 進行遍歷時,可以按以下方法:
1 for(String key: this.node.keySet()) {...}
除此之外,在完成作業的過程中,Java對於數組長度的限制與C相比更為嚴格,如果數組容量過小,可能會導致數組越界的問題,如果過大也有可能導致爆內存,同時,Java沒有C語言的內存分配。Java在實現動態數組時,可以使用 Vector 容器類。 使用時,需要首先進行 import :
1 import java.util.Vector;
Vector 內容納的應該為 class 對象,因此需要創建整數數組時,應該創建 Vector<Integer> ,如下所示:
1 Vector<Integer> v; 2 v = new Vector<Integer>();
在學習的過程中,另一個比較難以理解的地方是接口,利用接口,可以間接實現Java本身所不支持的多重繼承,此外也可以簡化代碼,體現了面向對象特性中的抽象。
接口的聲明語法格式如下:
1 [可見度] interface 接口名稱 [extends 其他的類名] 2 { 3 // 聲明變量 4 // 抽象方法 5 }
當類實現接口的時候,類要實現接口中所有的方法。否則,類必須聲明為抽象的類。
類使用 implements 關鍵字實現接口。在類聲明中, Implements 關鍵字放在 class 聲明後面。
實現一個接口的語法,可以使用這個公式:
1 ...implements 接口名稱[, 其他接口, 其他接口..., ...] ...
對於實現同一個接口的不同類,如果給同一個方法傳遞的數據類型不同,可以統一使用所有類型的父類: Object ,然後在方法內部具體判斷是哪一種類型。
之前在學習Python的過程中便已經對面向對象有了初步的了解,但是更多的還是使用Python面向過程的部分來完成作業,對於面向對象的理解並不深。通過本門課程的學習,以Java這門完全面向對象的語言為工具,在學習了一門新語言的基礎上,進一步加深了對於面向對象的理解,能夠較為準確的完成作業,對於面向對象的特征:繼承,封裝和多態有了一些理解和體會。
繼承
使用繼承,子類就不會存在與父類重復的代碼,維護性也提高,代碼也更加簡潔,提高代碼的復用性。
多態
在完成作業的過程中,對於多態的涉及較少,對於多態的三種實現方法,重寫/重載、接口、抽象類和抽象方法,所使用的幾乎都是重寫(Override)與重載(Overload)。 在涉及到重寫時,應當適當利用 super 和 this 關鍵詞,以防止調用與設想中不同的方法,減少錯誤的出現。
封裝
在這一部分,主要的內容是利用 public , protected 和 private 三種關鍵字,對數據和方法進行隱藏,以提高程序的安全性。
private 只能在其自己的定義類中使用,而 public 可以在所有的類中使用。 protected 能夠在自已的定義類以及其子類中使用。
意見和建議
- 在最初一節課上,首要的感覺就是懵,不明白需要做什麽,不明白布置的要求如何完成。在完成壞境的配置後,經過一些講解,直接要求完成一些任務,但是此時之前並沒有接觸過任何Java語法的我感覺無從下手,前兩個任務在助教的幫助下才能完成,而後面的任務,更多的涉及到Java的方法等,當時完全沒有了解,完全不能跟上進度。希望在下次開課時,能夠強化對於基礎語法的講解,在開始完成任務前的講解的課件中能夠提供示例程序。在完成一個任務後,提供相應的標程以作參考。
- 在課後完成作業時,感覺主要的問題就是作業要求的不明確,難以上手,以及作業要求的朝令夕改。
通過本次課程的學習,我初步掌握了Java的語法,能夠完成一些較為初步的工程任務,加深了對於面向對象的了解,相信對於大二下學期面向對象的學習都將有所幫助。
面向對象先導學習筆記