280 likes | 411 Views
物件導向程式設計 Object Oriented Programming. 8-1 列舉型態 ( Enumerated Type) 8-2 集合類別 (Collection Class) 8-3 對映類別 (Map Class) 8-4 泛型類別 (Generics Class) 8-5 套件 (Packages). 8-1 列舉型態 ( Enumerated Type). 8-1-1 列舉型態類別的定義 列舉型態是相關常數或常數物件集合組成的一種類別,用來規範常數使用的安全範圍。 列舉型態是常數的集合,定義的語法是:
E N D
物件導向程式設計Object Oriented Programming 8-1 列舉型態(Enumerated Type) 8-2 集合類別(Collection Class) 8-3 對映類別(Map Class) 8-4 泛型類別(Generics Class) 8-5 套件(Packages)
8-1 列舉型態(Enumerated Type) • 8-1-1列舉型態類別的定義 列舉型態是相關常數或常數物件集合組成的一種類別,用來規範常數使用的安全範圍。 • 列舉型態是常數的集合,定義的語法是: enum 類別名稱 {常數1, 常數2, …}; • 列舉型態是常數物件的集合,定義的語法是: enum 類別名稱 { 常數1(), 常數2(), … 變數1, 變數2, … 建構函數 自定函數1, 自定函數2, … };
8-1 列舉型態(Enumerated Type) • 列舉型態類別的使用 • 如將五個英文暱名Andy, Tony, Joe, Cathy, Sue實作成列舉型態類別nickname: enum nickname { Andy, Tony, Joe, Cathy, Sue }; • 使用列舉型態類別nickname內的常數: nickname name; name=nickname.Andy; System.out.print(name); • 如果使用的常數不在列舉型態類別nickname內,執行時會發生錯誤: name=nickname.Danny; // 不在列舉型態類別nickname內的常數 System.out.print(name);
8-1 列舉型態(Enumerated Type) • 8-1-2列舉型態類別的內建函數 • object array=values() 取列舉型態類別內所有常數並轉成列舉型態的陣列 • object=valueOf(String) 取列舉型態類別內某一常數物件 • int=ordinal() 取常數在列舉型態內的序號(第一個為0) • String=name() 取常數的名稱 • int=comapreTo(object) 比較兩個常數的前後順序(不是比較常數值大小) • boolean=equals(object) 比較兩個常數值是否相等 • object1== object2 比較兩個常數參考指向reference是否相等
8-1 列舉型態(Enumerated Type) • 8-1-3列舉型態類別的變數、建構函數及自定函數 • 如果我們想要取得常數所衍生的資料,可在列舉型態中定義常數類別,常數類別中可以定義變數、建構函數及自定函數。 • 如要將上例暱名的正式名字同時置入列舉型態內就要使用常數物件的列舉型態類別: enum nickname { Andy("Andrew"), Tony("Anthony"), Joe("Joseph"), Cathy("Catherine"), Sue("Susan"); private String name; // 變數,存暱名的正式英文名 nickname(String s) { // 建構函數 name=s; } String getname() { // 自定函數 return name; } };
8-1 列舉型態(Enumerated Type) public static void main(String[] args) { nickname array[] = nickname.values(); // *1 for(nickname item : array) System.out.println(item+" formal name is "+item.getname()); System.out.println("\nJoe formal name is " + nickname.Joe.getname()); // *2 } *1 執行value()函數時會針對每個常數實作nickname物件,產生物件後依序存到陣列。由於實作時執行了建構函數,所以在物件中的name變數就存放了正式英文名。 *2 列舉型態類別實作後每個常數會產生物件,如nickname.Andy、nickname.Tony等,每個常數物件都有各自的英文名name,可透過各物件的getname函數取得。
8-2集合類別Collection Class • 集合collection類別又稱容器container類別,它分為List子類別與Set子類別。 • List的物件排列以放置先後順序來排列,可以有重覆的物件,如ArrayList、LinkedList 及先前介紹過的Vector等類別。 • Set則有自己的一套排序規則(未必依大小排序),不能有重覆的物件,如TreeSet、EnumSet及HashSet等類別。 • 集合類別存於java.util.*套件中。
8-2集合類別Collection Class • 8-2-1 ArrayList 類別 • ArrayList使用陣列實作List介面,它可以加入(add)物件元素或隨機存取(Random Access)某個物件元素,但不可以移除和插入(insert)物件元素。宣告的語法是: ArrayList<類別名稱>物件名稱= new ArrayList<類別名稱>(); 如: ArrayList<String> mylist = new ArrayList<String>(); • ArrayList的函數有: add(obj) // 將物件加入ArrayList obj=get(int) // 自ArrayList取出物件 int=size() // 取的ArrayList大小(即元素個數) mylist.add(“Danny”);
8-2集合類別Collection Class • 8-2-2LinkedList類別 • LinkedList和ArrayList功能相似,不但可以隨機讀取某個物件元素,更可以移除和插入物件元素,如addFirst()、addLast()、getFirst()、getLast()、removeFirst( )、removeLast()、isEmpty()等函數。 • LinkedList宣告的語法是: LinkedList<類別名稱>物件名稱= new LinkedList<類別名稱>(); 如: LinkedList<String> mylist = new LinkedList<String>(); mylist.addLast(“Danny”);
8-2集合類別Collection Class • 8-2-3 HashSet類別 • Set是集合類別的子類別,HashSet是實作Set介面,不會對收集的物件進行排序,收集的物件重覆時會自動剔除。 • HashSett提供add(), remove(), 及contains()等處理函數。 • 宣告的語法是: HashSet <類別名稱>物件名稱= new HashSet <類別名稱>();
8-2集合類別Collection Class HashSet<Character> myHash = new HashSet<Character>(); myHash.add('A'); myHash.add('P'); myHash.add('P'); myHash.add('L'); myHash.add('E'); System.out.println(myHash); 結果顯示: [E, P, A, L]
8-2集合類別Collection Class • 8-2-4 TreeSet類別 • TreeSet實作Set介面與SortedSet介面,會對收集的物件進行排序,但物件不能有重覆的情形。 • TreeSet提供add(), remove(), 及contains()等處理函數。 • 宣告的語法是: TreeSet <類別名稱>物件名稱= new TreeSet <類別名稱>();
8-2集合類別Collection Class TreeSet<Character> myTree = new TreeSet<Character>(); myHash.add('A'); myHash.add('P'); myHash.add('P'); myHash.add('L'); myHash.add('E'); System.out.println(myHash); 結果顯示: [A, E, L, P]
8-2集合類別Collection Class • 8-2-5 EnumSet 類別 • EnumSet用來建立列舉值的集合,同HashSet一樣不會對收集的物件進行排序,Enum元素本來就不能重覆,所以收集的物件也不會有重覆的情形,它提供add(), remove(), contains()及complementOf等處理函數。宣告的語法是: • 有初始值的實作 EnumSet<列舉名稱>物件名稱=EnumSet.of(列舉元素一, 列舉元素二, ….); • 沒有初始值的實作 EnumSet<列舉名稱>物件名稱= EnumSet.noneOf(列舉名稱.class); 沒有初始值的實作需用add()函數將列舉元素加入EnumSet。
8-2集合類別Collection Class enum NickConstant {Andy, Tony, Joe, Cathy, Sue} EnumSet<NickConstant> enumSet = EnumSet.of(NickConstant.Andy, NickConstant.Tony); EnumSet<NickConstant> enumSet = numSet.noneOf(NickConstant.class); enumSet.add(NickConstant.Andy); enumSet.add(NickConstant.Tony);
8-3 對映類別Map Class • 對映類別和集合類別一樣都是容器類別Container class的一種,所不同的是對映類別的物件必須是一組組成對的存在,每組是兩個物件,一個是key,一個是value。 • 在物件存入對映類別時,需要配合一把key,當取回物件時要用相同的這把key,對映類別中的key是唯一的才不會錯取value,對映類別有自己的排序方法來達到快速以key取value的目的。 • Key和value不能是基本的資料型態primitive data types。
8-3 對映類別Map Class • 8-3-1 HashMap類別 • HashMap是實作Map介面,不會對收集的Key物件進行排序,但Key物件不能有重覆的情形, • HashMap提供put(), get()及value()等處理函數。 • 宣告的語法是: Map<key類別名稱, value類別名稱>物件名稱= new HashMap< key類別名稱, value類別名稱>(); Map<String, String> map = new HashMap<String, String>(); map.put("Andy", "Andrew"); System.out.println(map.get("Andy"));
8-3 對映類別Map Class • 8-3-2 TreeMap類別 • TreeMap實作Map介面與SortedMap介面,會對收集的key物件進行排序,但key物件不能有重覆的情形。 • TreeMapt提供put(), get()及value()等處理函數。 • 宣告的語法是: Map<key類別名稱, value類別名稱>物件名稱= new TreeMap< key類別名稱, value類別名稱>(); Map<String, String> map = new TreeMap<String, String>(); map.put("Andy", "Andrew");
8-3 對映類別Map Class • 8-3-3 EnumMap類別 • EnumMap用來建立列舉值的集合,同HashMap一樣不會對收集的key物件進行排序。 • EnumMap提供put(), get(), value()及containsKey()等處理函數。 • 宣告的語法是: Map<key類別名稱, value類別名稱>物件名稱= new EnumMap< key類別 名稱, value類別名稱>(列舉名稱.class); enum NickConstant {Andy, Tony, Joe, Cathy, Sue} Map<NickConstant, String> enumMap = new EnumMap< NickConstant, String >(NickConstant.class); enumMap.put(NickConstant.Tony, “Anthony”);
8-4 泛型類別 Generics Class • 8-4-1 何謂泛型Generics? • 我們經常碰到兩個或多個類別,其內部處理的邏輯完全一樣,只是變數的資料型態不同,而必須寫好幾套的版本。泛型是將這好幾套的版本設計成一個通用的類別,透過泛型的宣告,變數型態在類別使用時再自動調整。 • 譬如學生成績的類別記錄學生姓名及成績,如成績採百分計時,成績變數的資料型態是int,成績採等級式時,成績變數的資料型態是String,雖然彼此相似,但管理和維護非常麻煩,於是有泛型Generics應用的出現,以泛型方式設計的類別,變數的型態較有彈性,在引用時會自動調整,如上兩例的學生成績類別寫成泛型類別後就可共用了。
8-4 泛型類別 Generics Class public class Record1{ private String name; private int grade; Record1(String name, int grade) { : } : } public class Record2{ private String name; private String grade; Record2(String name, String grade) { : } : }
8-4 泛型類別 Generics Class • 8-4-2 泛型類別的定義 • 在類別名稱後面加上<T>,用來宣告一個型態持有者T,在類別裡就可以用T當做變數型態來宣告變數名稱,如學生成績類別改寫為泛型類別: public class Record<T> { private String name; private T grade; Record(String name, T grade) { : } : }
8-4 泛型類別 Generics Class • 泛型類別可以支援一個以上的泛型變數,如學生成績分數學和物理,且二者型態一致: public class Record<T>{ private String name; private T math; private T phy; Record(String name, T phy, T math) { • 如二者型態不一致: public class Record3<S, T>{ private String name; private T math; private S phy; Record3(String name, S phy, T math) {
8-5套件Packages • 8-5-1 何謂套件 Packages? • 套件是一個目錄 directory (或稱檔案夾 folder),用來存放一組相關的類別或介面,以方便使用者引用。套件也可稱為JAVA類別的封裝檔。 • JAVA系統提供了許多現成好用的類別,分門別類放在不同的套件裡,如API、IO等套件,稱為系統套件 System Packages。 • 另外我們在開發大型系統時也可以將類別或介面分門別類做成套件存放,以方便管理與使用,稱為局部套件 Local Packages 或稱自訂套件 user-defined packages。
8-5套件Packages • 8-5-2套件的使用 如果要引用套件裡的類別,必須使用類別的全名(即套件名稱加上類別名稱)。如: public class HelloWorld extends java.applet.Applet { public void paint(java.awt.Graphicsg) { 如果同一類別引用多次這種寫法寫來十分麻煩,我們可以使用import類別全名 指令來簡化。如在原始碼前面加上: import java.applet.Applet; import java.awt.Graphics; 如此引用類別時就只要給類別名稱即可,如: public class HelloWorld extends Applet { public void paint(Graphicsg) {
8-5套件Packages • 我們在套件名稱後面使用引申字元Wild Card符號 ”*” 就可以引用該套件裡所有的類別,如import java.awt.*;。這種寫法對於多次引用同一套件內不同類別時就相當方便。 • JAVA的import是編譯指導Compile Director指令,告訴編譯器把類別名稱加上什麼樣的套件名稱。 • 程式在編譯時會根據類別的全名去找該類別的class檔進行連結,如果所引用類別不是使用全名,編譯器會先在你程式所在的目錄去找,其次才到import指定的位置找。 • 套件名稱中間的點符號是分隔各路徑目錄,最後一個目錄是存放類別的資料目錄,之前的目錄是資料目錄的路徑。
8-5套件Packages • 8-5-3 如何自訂套件? • 在類別的原始碼最前面加一行 Package packagename; Package 是保留字,packagename是套件名稱,也是目錄名稱,目錄可以是層狀目錄,各層目錄名稱之間以點(.)隔開。如 mypackage.shape 表示 mypackage\shape 的意思: package mypackage.shape; // 注意裡面的一點 public class Point { 類別的原始碼 • 另一種不使用 Package 指令,而是由編譯指令指定套件目錄: javac –d <套件目錄> <程式名稱> 如 javac –d c:\jdk150\mypackage\shape Point.java
8-5套件Packages • 8-5-4自訂套件的使用 • 在程式碼前面以import 指令標示類別的全名mypackage.shape.Point或類別所在的目錄mypackage.shape.*: • 如果未有classpath之系統設定,假設使用Point類別的程式在d:\test目錄下,則程式編輯時會到d:\test\mypackage\shape\ 目錄下找Point.class。 • 若有系統設定set classpath=d:\jdk150,則程式編輯時在d:\jdk150\mypackage\shape\ 目錄下找Point.class。