201771010125王瑜《面向物件程式設計(Java)》第十週學習總結
實驗十 泛型程式設計技術
一 理論部分
1.泛型:引數化型別,在定義類、介面、方法時通過型別引數指示將要處理的物件型別
2.泛型程式設計意味著編寫的程式碼可以被許多不同型別的物件所重用
3.定義簡單泛型類:
(1)一個泛型類就是具有一個或多個型別變數的類,即建立用型別作為引數的類
(2)以Pair類為例:public class Pair<T>
{
......
}
Pair類引入了一個型別變數T,用尖括號(<>)括起來,並放在類名的後面
(3)泛型類可以有多個型別變數。例如,可以定義Pair類,其中第一個域和第二個域使用不同的型別:public class Pair<T,U> { ... }
(4)類定義中的型別變數指定方法的返回型別以及域和區域性變數的型別
(5)例項化泛型物件時,一定要在類名後面指定型別引數的值,一共要有兩次書寫,例如:TestGeneric<String,String> t=new TestGeneric<String,String>();
4.泛型方法:
(1)定義泛型方法時注意,型別變數放在修飾符(public static)的後面,返回型別的前面
(2)泛型方法可以定義在普通類中,也可以定義在泛型類中
(3)當呼叫一個泛型方法時,在方法名前的尖括號中放入具體的型別
5.泛型介面的定義與實現:
(1)定義:public interface IPool<T>
{
T get();
int add(T t);
}
(2)實現:public class GenericPool<T> implements IPool<T> { ... }
public class GenericPool implements IPool<Account> { ... }
6.型別變數的限定:
(1)定義泛型變數的上界(用extends)
<T extends BoundingType>表示T是繫結型別的子型別。T和繫結型別可以是類,也可以是介面
一個型別變數或萬用字元可以有多個限定,例如:T extends Comparable & Serializable(限定型別用“&”分隔)
(2)定義泛型變數的下界(用super) 例如:<? super T>
7.泛型類的約束與侷限:
(1)不能用基本型別例項化型別引數
(2)執行時型別查詢只適用於原始型別
(3)不能丟擲也不能捕獲泛型類例項
(4)引數化型別的陣列不合法
(5)不能例項化型別變數
(6)泛型類的靜態上下文中型別變數無效
(7)注意擦除後的衝突
8.泛型型別的繼承規則:Java中的陣列是協變的,但泛型類不是協變的
9.萬用字元型別:(?,任何型別;T,某一種型別)
(1)單獨的?,用於表示任何型別
(2)?extends type,表示帶有上界
(3)? super type,表示帶有下界
10.(1)萬用字元的型別限定: Pair<? extends Employee>
Pair<? super Manager>
(2)無限定萬用字元:Pair<?>(Pair<?>與Pair的不同在於:可以用任意Object物件呼叫原始的Pair類的setObject方法)
二 實驗部分
1、實驗目的與要求:
(1) 理解泛型概念;
(2) 掌握泛型類的定義與使用;
(3) 掌握泛型方法的宣告與使用;
(4) 掌握泛型介面的定義與實現;
(5)瞭解泛型程式設計,理解其用途。
2、實驗內容和步驟
實驗1: 匯入第8章示例程式,測試程式並進行程式碼註釋。
測試程式1:
l 編輯、除錯、執行教材311、312頁 程式碼,結合程式執行結果理解程式;
l 在泛型類定義及使用程式碼處添加註釋;
l 掌握泛型類的定義及使用。
package pair1;
/**
* @version 1.00 2004-05-10 * @author Cay Horstmann */ public class Pair<T> //引入型別變數T { private T first; private T second; public Pair() { first = null; second = null; } public Pair(T first, T second) { this.first = first; this.second = second; } public T getFirst() { return first; } public T getSecond() { return second; } public void setFirst(T newValue) { first = newValue; } public void setSecond(T newValue) { second = newValue; } }
package pair1;
/**
* @version 1.01 2012-01-26 * @author Cay Horstmann */ public class PairTest1 { public static void main(String[] args) { String[] words = { "Mary", "had", "a", "little", "lamb" }; Pair<String> mm = ArrayAlg.minmax(words); System.out.println("min = " + mm.getFirst()); System.out.println("max = " + mm.getSecond()); } } class ArrayAlg//泛型方法 { /** * Gets the minimum and maximum of an array of strings. * @param a an array of strings * @return a pair with the min and max value, or null if a is null or empty */ public static Pair<String> minmax(String[] a) { if (a == null || a.length == 0) return null; String min = a[0]; String max = a[0]; for (int i = 1; i < a.length; i++) { if (min.compareTo(a[i]) > 0) min = a[i]; if (max.compareTo(a[i]) < 0) max = a[i]; } return new Pair<>(min, max); } }
測試程式2:
l 編輯、除錯執行教材315頁 PairTest2,結合程式執行結果理解程式;
l 在泛型程式設計程式碼處新增相關注釋;
l 掌握泛型方法、泛型變數限定的定義及用途。
package pair2;
import java.time.*;
/**
* @version 1.02 2015-06-21
* @author Cay Horstmann
*/
public class PairTest2
{
public static void main(String[] args)
{
LocalDate[] birthdays =
{
LocalDate.of(1906, 12, 9), // G. Hopper
LocalDate.of(1815, 12, 10), // A. Lovelace
LocalDate.of(1903, 12, 3), // J. von Neumann
LocalDate.of(1910, 6, 22), // K. Zuse
};
Pair<LocalDate> mm = ArrayAlg.minmax(birthdays);
System.out.println("min = " + mm.getFirst());
System.out.println("max = " + mm.getSecond());
}
}
class ArrayAlg
{
/**
Gets the minimum and maximum of an array of objects of type T.
@param a an array of objects of type T
@return a pair with the min and max value, or null if a is
null or empty
*/
public static <T extends Comparable> Pair<T> minmax(T[] a) //泛型方法,有上界約束
{
if (a == null || a.length == 0) return null;
T min = a[0];
T max = a[0];
for (int i = 1; i < a.length; i++)
{
if (min.compareTo(a[i]) > 0) min = a[i];
if (max.compareTo(a[i]) < 0) max = a[i];
}
return new Pair<>(min, max);
}
}
測試程式3:
l 用除錯執行教材335頁 PairTest3,結合程式執行結果理解程式;
l 瞭解萬用字元型別的定義及用途。
package pair3;
/**
* @version 1.01 2012-01-26
* @author Cay Horstmann
*/
public class PairTest3
{
public static void main(String[] args)
{
Manager ceo = new Manager("Gus Greedy", 800000, 2003, 12, 15);
Manager cfo = new Manager("Sid Sneaky", 600000, 2003, 12, 15);
Pair<Manager> buddies = new Pair<>(ceo, cfo); //型別變數
printBuddies(buddies);
ceo.setBonus(1000000);
cfo.setBonus(500000);
Manager[] managers = { ceo, cfo };
Pair<Employee> result = new Pair<>();//也可以用Manager
minmaxBonus(managers, result);
System.out.println("first: " + result.getFirst().getName()
+ ", second: " + result.getSecond().getName());
maxminBonus(managers, result);
System.out.println("first: " + result.getFirst().getName()
+ ", second: " + result.getSecond().getName());
}
public static void printBuddies(Pair<? extends Employee> p)//上界約束
{
Employee first = p.getFirst();
Employee second = p.getSecond();
System.out.println(first.getName() + " and " + second.getName() + " are buddies.");
}
public static void minmaxBonus(Manager[] a, Pair<? super Manager> result)//採用萬用字元來定義第二個型別變數result
{
if (a.length == 0) return;
Manager min = a[0];
Manager max = a[0];
for (int i = 1; i < a.length; i++)
{
if (min.getBonus() > a[i].getBonus()) min = a[i];
if (max.getBonus() < a[i].getBonus()) max = a[i];
}
result.setFirst(min);
result.setSecond(max);
}
public static void maxminBonus(Manager[] a, Pair<? super Manager> result)
{
minmaxBonus(a, result);
PairAlg.swapHelper(result); // OK--swapHelper captures wildcard type
}
// Can't write public static <T super manager> ...
}
class PairAlg
{
public static boolean hasNulls(Pair<?> p)//?型別變數的萬用字元,單獨的?表示任何一種型別,T表示一種未知型別
//將hasNulls轉換成泛型方法
//測試一個pair是否包含一個null引用
{
return p.getFirst() == null || p.getSecond() == null;
}
//編寫一個交換成對元素的方法
public static void swap(Pair<?> p) { swapHelper(p); }
public static <T> void swapHelper(Pair<T> p)//泛型方法
{
T t = p.getFirst();//儲存第一個元素
p.setFirst(p.getSecond());
p.setSecond(t);
}
}
實驗2:程式設計練習:
程式設計練習1:實驗九程式設計題總結
l 實驗九程式設計練習1總結(從程式總體結構說明、模組說明,目前程式設計存在的困難與問題三個方面闡述)。
總體結構說明:
主類main,子類card
模組說明:
main
package shen;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Scanner;
public class Main {
/** * 1.檔案讀取模組 利用ArrayList構造studentlist存放檔案內容2. 建立檔案字元流,分類讀取檔案內容 3.try/catch語句捕獲異常 */ private static ArrayList<Student> studentlist; public static void main(String[] args) { studentlist = new ArrayList<>(); Scanner scanner = new Scanner(System.in); File file = new File("C:\\Users\\ASUS\\Desktop\\新建資料夾\\身份證號.txt"); try { FileInputStream fis = new FileInputStream(file); BufferedReader in = new BufferedReader(new InputStreamReader(fis)); String temp = null; while ((temp = in.readLine()) != null) { Scanner linescanner = new Scanner(temp); linescanner.useDelimiter(" "); String name = linescanner.next(); String number = linescanner.next(); String sex = linescanner.next(); String age = linescanner.next(); String province = linescanner.nextLine(); Student student = new Student(); student.setName(name); student.setnumber(number); student.setsex(sex); int a = Integer.parseInt(age); student.setage(a); student.setprovince(province); studentlist.add(student); } } catch (FileNotFoundException e) { System.out.println("學生資訊檔案找不到"); e.printStackTrace(); // 加入的捕獲異常程式碼 } catch (IOException e) { System.out.println("學生資訊檔案讀取錯誤"); e.printStackTrace(); // 加入的捕獲異常程式碼 } /* * 1.根據實驗要求,選擇具體操作的模組 2.利用switch語句選擇具體的操作 */ boolean isTrue = true; while (isTrue) { System.out.println("選擇你的操作,輸入正確格式的選項"); System.out.println("A.字典排序"); System.out.println("B.輸出年齡最大和年齡最小的人"); System.out.println("C.尋找老鄉"); System.out.println("D.尋找年齡相近的人"); System.out.println("F.退出"); String m = scanner.next(); switch (m) { case "A": Collections.sort(studentlist); System.out.println(studentlist.toString()); break; case "B": int max = 0, min = 100; int j, k1 = 0, k2 = 0; for (int i = 1; i < studentlist.size(); i++) { j = studentlist.get(i).getage(); if (j > max) { max = j; k1 = i; } if (j < min) { min = j; k2 = i; } } System.out.println("年齡最大:" + studentlist.get(k1)); System.out.println("年齡最小:" + studentlist.get(k2)); break; case "C": System.out.println("老家?"); String find = scanner.next(); String place = find.substring(0, 3); for (int i = 0; i < studentlist.size(); i++) { if (studentlist.get(i).getprovince().substring(1, 4).equals(place)) System.out.println("老鄉" + studentlist.get(i)); } break; case "D": System.out.println("年齡:"); int yourage = scanner.nextInt(); int near = agenear(yourage); int value = yourage - studentlist.get(near).getage(); System.out.println("" + studentlist.get(near)); break; case "F": isTrue = false; System.out.println("退出程式!"); break; default: System.out.println("輸入有誤"); } } } /* * 對年齡資料進行相應的處理 */ public static int agenear(int age) { int j =