達拉草201771010105《面向物件程式設計(java)》第八週學習總結
達拉草201771010105《面向物件程式設計(java)》第八週學習總結
實驗六介面的定義與使用
實驗時間 2018-10-18
1、實驗目的與要求
(1) 掌握介面定義方法;
(2) 掌握實現介面類的定義要求;
(3) 掌握實現了介面類的使用要求;
(4) 掌握程式回撥設計模式;
(5) 掌握Comparator介面用法;
(6) 掌握物件淺層拷貝與深層拷貝方法;
(7) 掌握Lambda表示式語法;
(8) 瞭解內部類的用途及語法要求。
2、實驗內容和步驟
實驗1: 匯入第6章示例程式,測試程式並進行程式碼註釋。
測試程式1:
l 編輯、編譯、除錯執行閱讀教材214頁-215頁程式6-1、6-2,理解程式並分析程式執行結果;
l 在程式中相關程式碼處新增新知識的註釋。
l 掌握介面的實現用法;
l 掌握內建介面Compareable的用法。
1 package interfaces; 2 3 import java.util.*; 4 5 /** 6 * This program demonstrates the use of the Comparable interface. 7 * @version 1.30 2004-02-27 8 * @author Cay Horstmann 9 */ 10 public class EmployeeSortTest11 { 12 public static void main(String[] args) 13 { 14 Employee[] staff = new Employee[3];//建立一個數組 15 16 staff[0] = new Employee("Harry Hacker", 35000); 17 staff[1] = new Employee("Carl Cracker", 75000); 18 staff[2] = new Employee("Tony Tester", 38000); 19 //給三個陣列生成三個例項物件 20 21Arrays.sort(staff);//標準類名,用static方法修飾 22 23 // 輸出所有關於Employee物件的資訊 24 for (Employee e : staff) 25 System.out.println("name=" + e.getName() + ",salary=" + e.getSalary()); 26 } 27 }
1 package interfaces; 2 3 public class Employee implements Comparable<Employee>//建立一個泛型Comparable介面 4 5 { 6 private String name; 7 private double salary; 8 9 public Employee(String name, double salary)//構造方法 10 { 11 this.name = name; 12 this.salary = salary; 13 } 14 15 public String getName() 16 { 17 return name; 18 } 19 20 public double getSalary() 21 { 22 return salary; 23 } 24 25 public void raiseSalary(double byPercent) 26 { 27 double raise = salary * byPercent / 100; 28 salary += raise; 29 } 30 31 /** 32 * Compares employees by salary 33 * @param other another Employee object 34 * @return a negative value if this employee has a lower salary than 35 * otherObject, 0 if the salaries are the same, a positive value otherwise 36 */ 37 public int compareTo(Employee other) 38 { 39 return Double.compare(salary, other.salary);//呼叫Double包裝器類的compare方法 40 } 41 }
結果如下:
總結:
1. 在Java中一個類只能繼承一個直接的父類,但可以實現多個介面,間接的實現了多繼承。
2.若實現介面的類不是抽象類,則必須實現所有 介面的所有方法,即為所有的抽象方法定義方 法體。
3.一個類在實現某介面抽象方法時,必須使用完 全相同的方法名、引數列表和返回值型別。
4.介面抽象方法的訪問控制符已指定為public, 所以類在實現時,必須顯式地使用public修飾 符,否則被警告縮小了介面中定義的方法的訪 問控制範圍。
5.介面不能構造介面物件,但可以宣告介面變數以 指向一個實現了該介面的類物件。
5.可以用instanceof檢查物件是否實現了某個介面。
測試程式2:
l 編輯、編譯、除錯以下程式,結合程式執行結果理解程式;
interface A { double g=9.8; void show( ); } class C implements A { public void show( ) {System.out.println("g="+g);} }
class InterfaceTest { public static void main(String[ ] args) { A a=new C( ); a.show( ); System.out.println("g="+C.g); } } |
除錯結果如下:
1 package bjkn; 2 interface A 3 { 4 double g=9.8; 5 void show( ); 6 }
1 package bjkn; 2 3 class C implements A 4 { 5 public void show( ) 6 {System.out.println("g="+g);} 7 }
1 package bjkn; 2 3 class InterfaceTest 4 { 5 public static void main(String[ ] args) 6 { 7 A a=new C( ); 8 a.show( ); 9 System.out.println("g="+C.g); 10 } 11 }
執行結果如下:
測試程式3:
l 在elipse IDE中除錯執行教材223頁6-3,結合程式執行結果理解程式;
l 26行、36行程式碼參閱224頁,詳細內容涉及教材12章。
l 在程式中相關程式碼處新增新知識的註釋。
l 掌握回撥程式設計模式;
1 package timer; 2 3 /** 4 @version 1.01 2015-05-12 5 @author Cay Horstmann 6 */ 7 8 import java.awt.*; 9 import java.awt.event.*; 10 import java.util.*; 11 import javax.swing.*; 12 import javax.swing.Timer; 13 // to resolve conflict with java.util.Timer 14 15 public class TimerTest 16 { 17 public static void main(String[] args) 18 { 19 ActionListener listener = new TimePrinter(); 20 21 // 構造一個timer物件存放在變數裡,叫做listener 22 // 每次間隔10秒 23 Timer t = new Timer(10000, listener); 24 t.start(); 25 26 JOptionPane.showMessageDialog(null, "Quit program?"); 27 System.exit(0); 28 } 29 } 30 31 class TimePrinter implements ActionListener 32 { 33 public void actionPerformed(ActionEvent event) 34 { 35 System.out.println("At the tone, the time is " + new Date()); 36 Toolkit.getDefaultToolkit().beep(); 37 } 38 }
執行結果如下:
測試程式4:
l 除錯執行教材229頁-231頁程式6-4、6-5,結合程式執行結果理解程式;
l 在程式中相關程式碼處新增新知識的註釋。
l 掌握物件克隆實現技術;
l 掌握淺拷貝和深拷貝的差別。
1 package clone; 2 3 /** 4 * This program demonstrates cloning. 5 * @version 1.10 2002-07-01 6 * @author Cay Horstmann 7 */ 8 public class CloneTest 9 { 10 public static void main(String[] args) 11 { 12 try 13 { 14 Employee original = new Employee("John Q. Public", 50000); 15 original.setHireDay(2000, 1, 1); 16 Employee copy = original.clone(); 17 copy.raiseSalary(10); 18 copy.setHireDay(2002, 12, 31); 19 System.out.println("original=" + original); 20 System.out.println("copy=" + copy); 21 } 22 catch (CloneNotSupportedException e) 23 { 24 e.printStackTrace(); 25 } 26 } 27 }
1 package clone; 2 3 import java.util.Date; 4 import java.util.GregorianCalendar; 5 6 public class Employee implements Cloneable 7 { 8 private String name; 9 private double salary; 10 private Date hireDay; 11 12 public Employee(String name, double salary) 13 { 14 this.name = name; 15 this.salary = salary; 16 hireDay = new Date(); 17 } 18 19 public Employee clone() throws CloneNotSupportedException 20 { 21 // call Object.clone() 22 Employee cloned = (Employee) super.clone(); 23 24 // clone mutable fields 25 cloned.hireDay = (Date) hireDay.clone(); 26 27 return cloned; 28 } 29 30 /** 31 * Set the hire day to a given date. 32 * @param year the year of the hire day 33 * @param month the month of the hire day 34 * @param day the day of the hire day 35 */ 36 public void setHireDay(int year, int month, int day) 37 { 38 Date newHireDay = new GregorianCalendar(year, month - 1, day).getTime(); 39 40 // Example of instance field mutation 41 hireDay.setTime(newHireDay.getTime()); 42 } 43 44 public void raiseSalary(double byPercent) 45 { 46 double raise = salary * byPercent / 100; 47 salary += raise; 48 } 49 50 public String toString() 51 { 52 return "Employee[name=" + name + ",salary=" + salary + ",hireDay=" + hireDay + "]"; 53 } 54 }
執行結果如下:
總結:
1.當拷貝一個物件變數時,原始變數與拷貝變數 引用同一個物件。這樣,改變一個變數所引用 的物件會對另一個變數產生影響。
2.如果要建立一個物件新的copy,它的最初狀態與 original一樣,但以後可以各自改變狀態,就需 要使用Object類的clone方法。
3.淺層拷貝:被拷貝物件的所有常量成員和基本類 型屬性都有與原來物件相同的拷貝值,而若成員 域是一個物件,則被拷貝物件該物件域的物件引 用仍然指向原來的物件。
4.深層拷貝:被拷貝物件的所有成員域都含有與原 來物件相同的值,且物件域將指向被複制過的新對 象,而不是原有物件被引用的物件。換言之,深 層拷貝將拷貝物件內引用的物件也拷貝一遍。
實驗2: 匯入第6章示例程式6-6,學習Lambda表示式用法。
l 除錯執行教材233頁-234頁程式6-6,結合程式執行結果理解程式;
l 在程式中相關程式碼處新增新知識的註釋。
l 將27-29行程式碼與教材223頁程式對比,將27-29行程式碼與此程式對比,體會Lambda表示式的優點。
1 package lambda; 2 3 import java.util.*; 4 5 import javax.swing.*; 6 import javax.swing.Timer; 7 8 /** 9 * This program demonstrates the use of lambda expressions. 10 * @version 1.0 2015-05-12 11 * @author Cay Horstmann 12 */ 13 public class LambdaTest 14 { 15 public static void main(String[] args) 16 { 17 String[] planets = new String[] { "Mercury", "Venus", "Earth", "Mars", 18 "Jupiter", "Saturn", "Uranus", "Neptune" }; 19 System.out.println(Arrays.toString(planets)); 20 System.out.println("Sorted in dictionary order:"); 21 Arrays.sort(planets); 22 System.out.println(Arrays.toString(planets)); 23 System.out.println("Sorted by length:"); 24 Arrays.sort(planets, (first, second) -> first.length() - second.length()); 25 System.out.println(Arrays.toString(planets)); 26 27 Timer t = new Timer(1000, event -> 28 System.out.println("The time is " + new Date())/*lambda表示式*/); 29 t.start(); 30 31 // keep program running until user selects "Ok" 32 JOptionPane.showMessageDialog(null, "Quit program?"); 33 System.exit(0); 34 } 35 }
執行結果如下:
總結:
Java Lambda 表示式是Java 8 引入的一個新的功能,主 要用途是提供一個函式化的語法來簡化編碼。
實驗3: 程式設計練習
l 編制一個程式,將身份證號.txt 中的資訊讀入到記憶體中;
l 按姓名字典序輸出人員資訊;
l 查詢最大年齡的人員資訊;
l 查詢最小年齡人員資訊;
l 輸入你的年齡,查詢身份證號.txt中年齡與你最近人的姓名、身份證號、年齡、性別和出生地;
l 查詢人員中是否有你的同鄉。
實驗程式碼如下:
1 import java.io.BufferedReader; 2 import java.io.File; 3 import java.io.FileInputStream; 4 import java.io.FileNotFoundException; 5 import java.io.IOException; 6 import java.io.InputStreamReader; 7 import java.util.ArrayList; 8 import java.util.Arrays; 9 import java.util.Collections; 10 import java.util.Scanner; 11 12 public class Moom{ 13 private static ArrayList<Mest> studentlist; 14 public static void main(String[] args) { 15 studentlist = new ArrayList<>(); 16 Scanner scanner = new Scanner(System.in); 17 File file = new File("D:\\身份證號.txt"); 18 try { 19 FileInputStream fis = new FileInputStream(file); 20 BufferedReader in = new BufferedReader(new InputStreamReader(fis)); 21 String temp = null; 22 while ((temp = in.readLine()) != null) { 23 24 Scanner linescanner = new Scanner(temp); 25 26 linescanner.useDelimiter(" "); 27 String name = linescanner.next(); 28 String number = linescanner.next(); 29 String sex = linescanner.next(); 30 String age = linescanner.next(); 31 String province =linescanner.nextLine(); 32 Mest student = new Mest(); 33 student.setName(name); 34 student.setnumber(number); 35 student.setsex(sex); 36 int a = Integer.parseInt(age); 37 student.setage(a); 38 student.setprovince(province); 39 studentlist.add(student); 40 41 } 42 } catch (FileNotFoundException e) { 43 System.out.println("學生資訊檔案找不到"); 44 e.printStackTrace(); 45 } catch (IOException e) { 46 System.out.println("學生資訊檔案讀取錯誤"); 47 e.printStackTrace(); 48 } 49 boolean isTrue = true; 50 while (isTrue) { 51 52 System.out.println("1:字典排序"); 53 System.out.println("2:輸出年齡最大和年齡最小的人"); 54 System.out.println("3:尋找老鄉"); 55 System.out.println("4:尋找年齡相近的人"); 56 System.out.println("5:退出"); 57 String m = scanner.next(); 58 switch (m) { 59 case "1": 60 Collections.sort(studentlist); 61 System.out.println(studentlist.toString()); 62 break; 63 case "2": 64 int max=0,min=100; 65 int j,k1 = 0,k2=0; 66 for(int i=1;i<studentlist.size();i++) 67 { 68 j=studentlist.get(i).getage(); 69 if(j>max) 70 { 71 max=j; 72 k1=i; 73 } 74 if(j<min) 75 { 76 min=j; 77 k2=i; 78 } 79 80 } 81 System.out.println("年齡最大:"+studentlist.get(k1)); 82 System.out.println("年齡最小:"+studentlist.get(k2)); 83 break; 84 case "3": 85 System.out.println("家庭住址:"); 86 String find = scanner.next(); 87 String place=find.substring(0,3); 88 for (int i = 0; i <studentlist.size(); i++) 89 { 90 if(studentlist.get(i).getprovince().substring(1,4).equals(place)) 91 System.out.println("province"+studentlist.get(i)); 92 } 93 break; 94 95 case "4": 96 System.out.println("年齡:"); 97 int yourage = scanner.nextInt(); 98 int near=agematched(yourage); 99 int value=yourage-studentlist.get(near).getage(); 100 System.out.println(""+studentlist.get(near)); 101 break; 102 case "5": 103 isTrue = false; 104 System.out.println("退出程式!"); 105 break; 106 default: 107 System.out.println("輸入錯誤"); 108 109 } 110 } 111 } 112 public static int agematched(int age) { 113 int j=0,min=53,value=0,k=0; 114 for (int i = 0; i < studentlist.size(); i++) 115 { 116 value=studentlist.get(i).getage()-age; 117 if(value<0) value=-value; 118 if (value<min) 119 { 120 min=value; 121 k=i; 122 } 123 } 124 return k; 125 } 126 127 }
1 public class Mest implements Comparable<Mest> { 2 3 private String name; 4 private String number ; 5 private String sex ; 6 private int age; 7 private String province; 8 9 public String getName() { 10 return name; 11 } 12 public void setName(String name) { 13 this.name = name; 14 } 15 public String getnumber() { 16 return number; 17 } 18 public void setnumber(String number) { 19 this.number = number; 20 } 21 public String getsex() { 22 return sex ; 23 } 24 public void setsex(String sex ) { 25 this.sex =sex ; 26 } 27 public int getage() { 28 29 return age; 30 } 31 public void setage(int age) { 32 33 this.age= age; 34 } 35 36 public String getprovince() { 37 return province; 38 } 39 public void setprovince(String province) { 40 this.province=province ; 41 } 42 43 public int compareTo(Mest o) { 44 return this.name.compareTo(o.getName()); 45 } 46 47 public String toString() { 48 return name+"\t"+sex+"\t"+age+"\t"+number+"\t"+province+"\n"; 49 } 50 51 }
結果如下:
實驗程式3:
l 在elipse IDE中除錯執行教材257頁-258頁程式6-9,結合程式執行結果理解程式;
l 瞭解靜態內部類的用法。
1 package staticInnerClass; 2 3 /** 4 * This program demonstrates the use of static inner classes. 5 * @version 1.02 2015-05-12 6 * @author Cay Horstmann 7 */ 8 public class StaticInnerClassTest 9 { 10 public static void main(String[] args) 11 { 12 double[] d = new double[20]; 13 for (int i = 0; i < d.length; i++) 14 d[i] = 100 * Math.random(); 15 ArrayAlg.Pair p = ArrayAlg.minmax(d); 16 System.out.println("min = " + p.getFirst()); 17 System.out.println("max = " + p.getSecond()); 18 } 19 } 20 21 class ArrayAlg 22 { 23 /** 24 * A pair of floating-point numbers 25 */ 26 public static class Pair 27 { 28 private double first; 29 private double second; 30 31 /** 32 * Constructs a pair from two floating-point numbers 33 * @param f the first number 34 * @param s the second number 35 */ 36 public Pair(double f, double s) 37 { 38 first = f; 39 second = s; 40 } 41 42 /** 43 * Returns the first number of the pair 44 * @return the first number 45 */ 46 public double getFirst() 47 { 48 return first; 49 } 50 51 /** 52 * Returns the second number of the pair 53 * @return the second number 54 */ 55 public double getSecond() 56 { 57 return second; 58 } 59 } 60 61 /** 62 * Computes both the minimum and the maximum of an array 63 * @param values an array of floating-point numbers 64 * @return a pair whose first element is the minimum and whose second element 65 * is the maximum 66 */ 67 public static Pair minmax(double[] values) 68 { 69 double min = Double.POSITIVE_INFINITY; 70 double max = Double.NEGATIVE_INFINITY; 71 for (double v : values) 72 { 73 if (min > v) min = v; 74 if (max < v) max = v; 75 } 76 return new Pair(min, max); 77 } 78 }
總結:
1.如果用static修飾一個內部類,這個類就相當於是一個外部定義的類,所以static的內部類中可宣告static成員,但非static的內部類中的成員是不能宣告為static的。static的內部類不能再使用外部類的非static的成員變數。
2.靜態內部類可以建立靜態的成員,而非靜態的內部類不可以。
3.靜態內部類只可以訪問外部類中的靜態成員變數與成員方法,而非靜態的內部類即可以訪問所有的外部類成員方法與成員變數。
執行結果如下:
實驗總結:
通過這次的實驗我知道了在java中類與介面在用法上的一些區別, 在Java中一個類只能繼承一個直接的父類,但可以實現多個介面,間接的實現了多繼承。還有了解了深層拷貝與淺層拷貝,以及Comparator介面的用法,知道了lambda表示式。最後瞭解了靜態內部類的一些用法,靜態內部類可以建立靜態的成員,而非靜態的內部類不可以。靜態內部類只可以訪問外部類中的靜態成員變數與成員方法,而非靜態的內部類即可以訪問所有的外部類成員方法與成員變數。