201871010119-帖佼佼《面向對象程序設計(java)》第八週學習總結

博文正文開頭格式:(2分)html

項目java

內容express

這個做業屬於哪一個課程編程

 https://www.cnblogs.com/nwnu-daizh/設計模式

這個做業的要求在哪裏數組

   https://www.cnblogs.com/nwnu-daizh/p/11435127.htmldom

做業學習目標函數

  1. (1) 掌握接口定義方法;工具

    (2) 掌握實現接口類的定義要求;學習

    (3) 掌握實現了接口類的使用要求;

    (4) 掌握程序回調設計模式;

    (5) 掌握Comparator接口用法;

    (6) 掌握對象淺層拷貝與深層拷貝方法;

    (7) 掌握Lambda表達式語法;

    (8) 瞭解內部類的用途及語法要求。

第一部分:總結第五章理論知識(30分)

Java中類於類之間的關係以及代碼示例:
1、繼承關係

繼承指的是一個類(稱爲子類、子接口)繼承另外的一個類(稱爲父類、父接口)的功能,並能夠增長它本身的新功能的能力。在Java中繼承關係經過關鍵字extends明確標識,在設計時通常沒有爭議性。在UML類圖設計中,繼承用一條帶空心三角箭頭的實線表示,從子類指向父類,或者子接口指向父接口。
2、實現關係

實現指的是一個class類實現interface接口(能夠是多個)的功能,實現是類與接口之間最多見的關係。在Java中此類關係經過關鍵字implements明確標識,在設計時通常沒有爭議性。在UML類圖設計中,實現用一條帶空心三角箭頭的虛線表示,從類指向實現的接口。
3、依賴關係

簡單的理解,依賴就是一個類A使用到了另外一個類B,而這種使用關係是具備偶然性的、臨時性的、很是弱的,可是類B的變化會影響到類A。好比某人要過河,須要借用一條船,此時人與船之間的關係就是依賴。表如今代碼層面,爲類B做爲參數被類A在某個method方法中使用。在UML類圖設計中,依賴關係用由類A指向類B的帶箭頭虛線表示。
4、關聯關係

關聯體現的是兩個類之間語義級別的一種強依賴關係,好比我和個人朋友,這種關係比依賴更強、不存在依賴關係的偶然性、關係也不是臨時性的,通常是長期性的,並且雙方的關係通常是平等的。關聯能夠是單向、雙向的。表如今代碼層面,爲被關聯類B以類的屬性形式出如今關聯類A中,也多是關聯類A引用了一個類型爲被關聯類B的全局變量。在UML類圖設計中,關聯關係用由關聯類A指向被關聯類B的帶箭頭實線表示,在關聯的兩端能夠標註關聯雙方的角色和多重性標記。
5、聚合關係

聚合是關聯關係的一種特例,它體現的是總體與部分的關係,即has-a的關係。此時總體與部分之間是可分離的,它們能夠具備各自的生命週期,部分能夠屬於多個總體對象,也能夠爲多個總體對象共享。好比計算機與CPU、公司與員工的關係等,好比一個航母編隊包括海空母艦、驅護艦艇、艦載飛機及核動力攻擊潛艇等。表如今代碼層面,和關聯關係是一致的,只能從語義級別來區分。在UML類圖設計中,聚合關係以空心菱形加實線箭頭表示。
6、組合關係

組合也是關聯關係的一種特例,它體現的是一種contains-a的關係,這種關係比聚合更強,也稱爲強聚合。它一樣體現總體與部分間的關係,但此時總體與部分是不可分的,總體的生命週期結束也就意味着部分的生命週期結束,好比人和人的大腦。表如今代碼層面,和關聯關係是一致的,只能從語義級別來區分。在UML類圖設計中,組合關係以實心菱形加實線箭頭表示。
    注意: 繼承與實現是類於類,或者類與接口之間的一種縱向關係,其餘的四種關係體現的是類和類、或者類與接口間的引用、橫向關係,是比較難區分的,有不少事物間的關係要想準肯定位是很難的。前面也提到,這四種關係都是語義級別的,因此從代碼層面並不能徹底區分各類關係,但總的來講,後幾種關係所表現的強弱程度依次爲:組合>聚合>關聯>依賴。
一、接口:Java爲了克服單繼承的特色,Java使用了接口,一個類能夠實現一個或者多個接口;
二、在Java中,接口不是類,而是對類的一組需求描述 ,由常量和一組抽象方法組成;
三、接口中不包括變量和具體方法的實現;
四、只要類實現了接口,則該類要聽從接口描述的統一格式進行定義,而且能夠在任何須要接口的地方使用這個類得額對象;
五、接口的類型:
用戶自定義接口;
標準接口;
一、自定義接口的聲明:
(1)聲明方式: public interface 接口名
{······}
(2)接口體中包含常量定義和抽象方法的定義 ,接口中只進行方法的聲明,不提供實現的方法;
二、相似創建類的繼承關係,接口也能夠擴展;
三、接口的擴展技術使得從具備較高通用性的接口存在多條鏈延伸到具備較高專用性的接口;
四、擴展方法:
public interface 接口1 extends 接口2
{······ }
說明:(1)一般接口的名字以able或者ible結尾;
(2)能夠經過extends來繼承接口的常量和抽象方法,擴展造成新的接口;
(3)接口中的全部常量必須都是 public static final,方法必須是public abstract ,這是系統默認的,寫不寫修飾符都是同樣的;
五、接口的實現:
(1)在類聲明時用implements關鍵字來聲明使用一個或者多個接口
class Employee implements Printable
{······ }
(2)一個類使用了某個接口,那麼這個類必須實現該接口的全部方法,即爲這些方法提供方法體;
(3)一個類能夠實現多個接口,接口間應該用逗號隔開。
class Employee implements Cloneable , Comparable
說明:(1)若實現接口的類不是抽象類,則必須實現全部接口的全部方法,即爲全部的抽象方法定義方法體;
           (2)一個類在實現某接口方法時,必須使用徹底相同的方法名、參數列表和返回值類型;
           (3)接口抽象方法的訪問控制符已指定爲 public,因此類在實現時,必須顯示的使用public修飾符,不然被警告縮小了接口中定義的方法的訪問控制範圍;
六、接口的使用:
(1)接口不能構造接口對象,但能夠聲明接口變量以指向一個實現了該接口的類對象;
Comparable x = new Comparable(······ ) //錯誤
Comparable x = new Employee(······ ) //正確
(2)能夠用instanceof來檢查對象是否實現了某個接口
if (anObject instanceof Comparable)
{······ }
七、接口與抽象類:
(1)抽象類:用abstract來聲明,沒有具體實例對象的類,不能用new來建立對象。可包含常規類所包含的任何東西,抽象類必須由子類繼承,若是abstract類的子類不是抽象類,那麼子類必須重寫父類中的全部的abstract方法;
(2)接口:用interface來聲明,是抽象方法和常量值構成的集合。從本質上來說,接口是一種特殊的抽象類,這種抽象類中只包含常量和抽象方法的定義,而沒有變量和方法的定義,接口中只能定義抽象方法,並且這些方法默認爲public的,只要類實現了接口,就能夠在任何須要該接口的地方使用這個類的對象。此外,一個類能夠實現多個接口。
八、接口與抽象類的區別:
(1)接口不能實現任何方法,而抽象類能夠;
(2)類能夠實現不少接口,但只有一個父類;
(3)接口不是一個類分級結構中的一部分,無任何聯繫的類能夠實現相同的接口。
6.2 接口示例
接口與回調
(1)回調:(callback):一種程序設計模式,在這種模式中,可指出某個特定事件發生時,程序應該採起的動做;
(2)在Java.Swing包中有一個Timer類,可使用它在到達給定的時間間隔時觸發的一個事件。
Comparable接口:
用途(1):處理字符串按長度進行排序的操做;
對象克隆:
一、object類當中 的clone方法:
(1)當拷貝一個對象變量時,原始變量與拷貝變量引用同一個對象,這樣,改變一個變量所引用的對象會對另外一個變量產生影響;
(2)若是要建立一個對象新的copy,它的最初狀態與original同樣,但之後能夠各自改變狀態,就須要使用clone方法;
(3)object類中的clone()方法是一個native方法;
(4)object類中的clone()方法被protected修飾符修飾,着覺得着在用戶編寫的代碼中不能直接調用它。若是要直接應用clone()方法,就須要覆蓋clone()方法,並要把clone()方法的屬性設置爲public;
(5)object類中的clone()方法返回一個object對象,必須進行強制轉換類型才能獲得須要的類型;
二、淺層拷貝和深層拷貝
(1)淺層拷貝:被拷貝對象的全部常量成員和基本類型屬性都有與原來對象相同的拷貝值,而若成員域是一個對象,則被拷貝對象該對象魚的對象引用仍然指向原來的對象;
(2)深層拷貝:被拷貝對象的全部成員域都含有與原來對象相同的拷貝值,且對象域將指向被複制過的新對象,而不是原來對象被引用的而對象。
想要實現深層拷貝,必須克隆類中全部的對象的實例域。
三、Java中克隆對象的實現:
對象克隆要點:
(1)在子類中實現Cloneable接口;
(2)爲了獲取對象的一份拷貝,能夠利用Object類的clone方法;
(3)在子類中覆蓋超類的clone方法,聲明爲public;
(4)在子類的clone方法中,調用super.clone();
四、public interface Cloneable{
}
能夠看到,這個內置接口Cloneable是空的,它僅僅是一個標誌,這樣的接口稱爲標誌接口,且這個接口只針對Object類的clone()方法;
若是一個類沒有實現Cloneable接口,且調用了Object類的clone()方法(即調用了super.clone()方法),那麼Object類的clone方法就會拋出CloneNotSupportedException 異常。
接口學習中的幾個問題:
一、精簡程序結構,免除代碼的重複使用;
(1)若是有兩個及以上的類擁有相同的方法,可是實現功能不同,就能夠定義一個接口(抽象類),將這個方法提煉出來,在須要使用該方法的類中去實現,就免除了多個類定義系統方法的麻煩;
(2)因爲Java只支持單繼承,若是被提煉的方法定義爲抽象類,若某個類要擴展兩個以上這樣的抽象類就會被限制,則這時就能夠定義爲接口。
6·三、Lambda表達式:主要是提供一個函數化的語法來簡化編碼。
(1)Lambda表達式本質上是一個匿名方法。
  public int add(int x, int y){
  return x + y;} 將其轉成Lambda表達式爲: (int x , int y) -> x + y;
參數類型能夠省略,Java編譯器會根據上下文推斷出來:
(x, y)-> x + y; //返回兩數之和
(x, y)->{return x + y;} //顯式指明返回值
(2)Lambda表達式的語法基本結構: (arguments)-> body
有以下幾種狀況:
a、參數類型可推導時,不須要指定類型;eg: (a)->System.out.println(a)
b、只有一個參數且類型可推導時,不強制寫(), eg:a->System.out.println(a)
c、參數指定類型時,必須有括號, eg:(int a) -> System.out.println(a)
d、參數能夠爲空,eg:()-> System.out.println("Hello")
e、body須要用{}包含語句,當只有一條語句時{}能夠省略。
(3)函數式接口Functionalinterface
a、Java Lambda表達式以函數式接口爲應用基礎;
b、函數式接口,只有一個方法的接口,這類接口的目的是爲了一個單一的操做;
c、函數式接口用做表示Lambda表達式的類型。
(4)建立函數式接口:
有時候須要自定義一個函數式接口,作法也很簡單,首先此接口只能有一個函數操做,而後在接口操做類型上標註註解@Functionalinterface便可
6·4 內部類
(1)內部類(inner class )是定義在一個類內部的類;
(2)外層的類稱爲外部類(outer class);
(3)內部類主要用於處理事件;
(4)使用內部類的緣由:
a、內部類方法能夠訪問該類定義所在的做用域中的數據,包括私有數據;
b、內部類可以隱藏起來,不爲同一包中的其餘類可見;
c、想要定義一個回調函數且不想編寫大量的代碼時,使用匿名內部類比較便捷;
(5)內部類的聲明:
class outerClass{
【修飾符】class inner Class{
...........
}
...........
}
內部類能夠直接訪問外部類的成員,包括private成員,可是內部類的成員卻不能被外部類直接訪問;

二、實驗內容和步驟

實驗1: 導入第6章示例程序,測試程序並進行代碼註釋。

測試程序1:

l  編輯、編譯、調試運行閱讀教材214頁-215頁程序6-一、6-2,理解程序並分析程序運行結果;

l  在程序中相關代碼處添加新知識的註釋。

l  掌握接口的實現用法;

l  掌握內置接口Compareable的用法。

實驗代碼以下:

package interfaces;

public class Employee implements Comparable<Employee>   //接口的定義,Comparable是內置接口
{
   private String name;     //私有變量的定義
   private double salary; 

   public Employee(String name, double salary)    //Employee構造器
   {
      this.name = name;
      this.salary = salary;
   }

   public String getName()      //getName方法訪問器
   {
      return name;
   }

   public double getSalary()     //getSalary方法訪問器
   {
      return salary;
   }

   public void raiseSalary(double byPercent)     //聲明方法
   {
      double raise = salary * byPercent / 100;
      salary += raise;
   }

   /**
    * Compares employees by salary
    * @param other another Employee object
    * @return a negative value if this employee has a lower salary than
    * otherObject, 0 if the salaries are the same, a positive value otherwise
    */
   public int compareTo(Employee other)    //按工資輸出
   { 
      return Double.compare(salary, other.salary);     
   }
}

  

package interfaces;

import java.util.*;

/**
 * This program demonstrates the use of the Comparable interface.
 * @version 1.30 2004-02-27
 * @author Cay Horstmann
 */
public class EmployeeSortTest    //EmployeeSortTest類
{
   public static void main(String[] args)
   {
	  Employee[] staff = new Employee[3];   //Employee對象數組的建立   

      staff[0] = new Employee("Harry Hacker", 35000);
      staff[1] = new Employee("Carl Cracker", 75000);
      staff[2] = new Employee("Tony Tester", 38000);

      Arrays.sort(staff);    //數組排序方法

      // print out information about all Employee objects
      for (Employee e : staff)     //調用getNname()方法以及getSalary()方法輸出全部僱員的信息
         System.out.println("name=" + e.getName() + ",salary=" + e.getSalary());
   }
}

  運行結果以下:

測試程序2:

l  編輯、編譯、調試如下程序,結合程序運行結果理解程序;

  代碼以下:

interface  A    //A接口
{
  double g=9.8;    
  void show( );    
}
class C implements A       //定義C繼承接口A
{
  public void show( )
  {
	  System.out.println("g="+g);    //將g的值輸出在控制檯上
  }
}

class InterfaceTest     //InterfaceTest類的定義
{
  public static void main(String[ ] args)
  {
       A a=new C( );   
       a.show( );
       System.out.println("g="+C.g);    //輸出g的值在控制檯上
  }
}

運行結果以下:

l  在elipse IDE中調試運行教材223頁6-3,結合程序運行結果理解程序;測試程序3:

實驗代碼以下:

package timer;     

/**
   @version 1.02 2017-12-14
   @author Cay Horstmann
*/

import java.awt.*;
import java.awt.event.*;
import java.time.*;
import javax.swing.*;

public class TimerTest
{  
   public static void main(String[] args)
   {  
      ActionListener listener = new TimePrinter();    //構造這個類的一個對象,並將它傳遞給Timer構造器
      //ActionListener接口對象,建立實現類接口的對象
      // construct a timer that calls the listener
      // once every second
      Timer timer = new Timer(1000, listener);    //建立定時器類對象timer
      timer.start();      //啓動定時器

      // keep program running until the user selects "OK"
      JOptionPane.showMessageDialog(null, "Quit program?");    //啓動程序後,將會當即彈出一個包含"Quit program?"字樣的對話框
      System.exit(0);
   }
}

class TimePrinter implements ActionListener   //接口
{  
   public void actionPerformed(ActionEvent event)   //actionPerformed方法的ActionEvent參數,提供了事件的相關信息
   {  
      System.out.println("At the tone, the time is " 
         + Instant.ofEpochMilli(event.getWhen()));    //每隔10秒,這條信息就會輸出一次,而後響一聲鈴
      Toolkit.getDefaultToolkit().beep();    //返回Toolkit,調用getDefaultToolkit()方法,得到默認的工具箱
   }
}

  運行結果以下:

l  26行、36行代碼參閱224頁,詳細內容涉及教材12章。

l  在程序中相關代碼處添加新知識的註釋。

l  掌握回調程序設計模式;

測試程序4:

l  調試運行教材229頁-231頁程序6-四、6-5,結合程序運行結果理解程序;

l  在程序中相關代碼處添加新知識的註釋。

l  掌握對象克隆實現技術;

l  掌握淺拷貝和深拷貝的差異。

實驗代碼以下:

package clone;

import java.util.Date;
import java.util.GregorianCalendar;

public class Employee implements  Cloneable    //淺層拷貝和會深層拷貝的使用
{
   private String name;     //三個私有變量的定義
   private double salary;
   private Date hireDay;

   public Employee(String name, double salary)    //Employee構造器
   {
      this.name = name;
      this.salary = salary;
      hireDay = new Date();
   }

   public Employee clone() throws CloneNotSupportedException   
   //聲明異常,在一個對象上調用clone,但這個 對象的類並無實現Cloneable的接口,而後Object類的clone方法就會拋出一個 CloneNotSupportedException。
   {
      // call Object.clone()
      Employee cloned = (Employee) super.clone();

      // clone mutable fields
      cloned.hireDay = (Date) hireDay.clone();

      return cloned;
   }

   /**
    * Set the hire day to a given date. 
    * @param year the year of the hire day
    * @param month the month of the hire day
    * @param day the day of the hire day
    */
   public void setHireDay(int year, int month, int day)      //
   {
      Date newHireDay = new GregorianCalendar(year, month - 1, day).getTime();
      
      // example of instance field mutation
      hireDay.setTime(newHireDay.getTime());
   }

   public void raiseSalary(double byPercent)       
   {
      double raise = salary * byPercent / 100;
      salary += raise;
   }

   public String toString()
   {
      return "Employee[name=" + name + ",salary=" + salary + ",hireDay=" + hireDay + "]";
   }
}

  

package clone;

/**
 * This program demonstrates cloning.
 * @version 1.11 2018-03-16
 * @author Cay Horstmann
 */
public class CloneTest
{
   public static void main(String[] args) throws CloneNotSupportedException
   {
      Employee original = new Employee("John Q. Public", 50000);
      original.setHireDay(2000, 1, 1);
      Employee copy = original.clone();     
      //原始變量與拷貝變量引用統一個對象,這樣,使用Object類的Clone對象,改變一個對象所引用的對象就不會影響另外一個對象
      copy.raiseSalary(10);     //copy會增加10%的薪資,可是original不會變
      copy.setHireDay(2002, 12, 31);
      System.out.println("original=" + original);
      System.out.println("copy=" + copy);
   }
}

  運行結果以下:

淺層拷貝和深層拷貝的差異:

(1)淺層拷貝:被拷貝對象的全部常量成員和基本類型屬性都有與原來對象相同的拷貝值,而若成員域是一個對象,則被拷貝對象該對象魚的對象引用仍然指向原來的對象;

(2)深層拷貝:被拷貝對象的全部成員域都含有與原來對象相同的拷貝值,且對象域將指向被複制過的新對象,而不是原來對象被引用的而對象。
想要實現深層拷貝,必須克隆類中全部的對象的實例域。

實驗2: 導入第6章示例程序6-6,學習Lambda表達式用法。

l  調試運行教材233頁-234頁程序6-6,結合程序運行結果理解程序;

l  在程序中相關代碼處添加新知識的註釋。

l  將27-29行代碼與教材223頁程序對比,將27-29行代碼與此程序對比,體會Lambda表達式的優勢。

實驗代碼以下:

 

package lambda;

import java.util.*;

import javax.swing.*;
import javax.swing.Timer;

/**
 * This program demonstrates the use of lambda expressions.
 * @version 1.0 2015-05-12
 * @author Cay Horstmann
 */
public class LambdaTest    //LambdaTest類
{
   public static void main(String[] args)
   {
      String[] planets = new String[] { "Mercury", "Venus", "Earth", "Mars", 
         "Jupiter", "Saturn", "Uranus", "Neptune" };    //建立一個String類數組對象
      System.out.println(Arrays.toString(planets));         //調用Arrays的toString方法,而後將planets輸出在控制檯上
      System.out.println("Sorted in dictionary order:");
      Arrays.sort(planets);				//數組排序
      System.out.println(Arrays.toString(planets));
      System.out.println("Sorted by length:");
      Arrays.sort(planets, (first, second) -> first.length() - second.length()); //能夠推導出first以及second的類型
      System.out.println(Arrays.toString(planets));
            
      Timer timer = new Timer(1000, event ->       //若是方法只有一個參數,則這個參數的類型能夠推導出
         System.out.println("The time is " + new Date()));
      timer.start();   //計時器開始
         
      // keep program running until user selects "OK"
      JOptionPane.showMessageDialog(null, "Quit program?");
      System.exit(0);         
   }
}

  運行結果以下:

實驗2:內部類語法驗證明驗

實驗程序1:

l  編輯、調試運行教材246頁-247頁程序6-7,結合程序運行結果理解程序;

l  瞭解內部類的基本用法。

實驗代碼以下:

package innerClass;

import java.awt.*;
import java.awt.event.*;
import java.time.*;

import javax.swing.*;

/**
 * This program demonstrates the use of inner classes.
 * @version 1.11 2017-12-14
 * @author Cay Horstmann
 */
public class InnerClassTest
{
   public static void main(String[] args)
   {
      TalkingClock clock = new TalkingClock(1000, true);      //建立TalkingClock對象,
      clock.start();         

      // keep program running until the user selects "OK"
      JOptionPane.showMessageDialog(null, "Quit program?");     //當程序開始運行的時候當即出現寫有「Quit program」的對話框
      System.exit(0);
   }
}

/**
 * A clock that prints the time in regular intervals.
 */
class TalkingClock           //抽象一個TalkingClock類
{
   private int interval;       //構造語音時鐘時所須要的兩個參數:發佈通告的間隔以及開關鈴聲的標誌
   private boolean beep;

   /**
    * Constructs a talking clock
    * @param interval the interval between messages (in milliseconds)
    * @param beep true if the clock should beep
    */
   public TalkingClock(int interval, boolean beep)             //TalkingClock構造器
   {
      this.interval = interval;
      this.beep = beep;
   }

   /**
    * Starts the clock.
    */
   public void start()     //方法聲明
   {
      TimePrinter listener = new TimePrinter();           //建立一個TimePrinter對象,其在TalkingClock的內部
      Timer timer = new Timer(interval, listener);
      timer.start();      //啓動
   }

   public class TimePrinter implements ActionListener     //將TimePrinter類聲明爲實現ActionListener接口
   {
      public void actionPerformed(ActionEvent event)      //actionPerformed方法在發出鈴聲以前檢查了beep標誌
      {
         System.out.println("At the tone, the time is " 
            + Instant.ofEpochMilli(event.getWhen()));
         if (beep) Toolkit.getDefaultToolkit().beep();
      }
   }
}

  運行結過以下:

實驗程序2:

l  編輯、調試運行教材254頁程序6-8,結合程序運行結果理解程序;

l  掌握匿名內部類的用法。

實驗代碼以下:

package anonymousInnerClass;

import java.awt.*;
import java.awt.event.*;
import java.time.*;

import javax.swing.*;

/**
 * This program demonstrates anonymous inner classes.
 * @version 1.12 2017-12-14
 * @author Cay Horstmann
 */
public class AnonymousInnerClassTest
{
   public static void main(String[] args)
   {
      TalkingClock clock = new TalkingClock();           //建立一個TalkingClock對象
      clock.start(1000, true);     

      // keep program running until the user selects "OK"
      JOptionPane.showMessageDialog(null, "Quit program?");
      System.exit(0);
   }
}

/**
 * A clock that prints the time in regular intervals.
 */
class TalkingClock           //抽象一個TalkingClock類
{
   /**
    * Starts the clock.
    * @param interval the interval between messages (in milliseconds)
    * @param beep true if the clock should beep
    */
   public void start(int interval, boolean beep)    //方法聲明
   {
      ActionListener listener = new ActionListener()    //建立一個實現ActionListener接口的類的新對象,
         {
            public void actionPerformed(ActionEvent event)  //須要實現的方法定義在ActionListener括號{}內 
            {
               System.out.println("At the tone, the time is " 
                  + Instant.ofEpochMilli(event.getWhen()));
               if (beep) Toolkit.getDefaultToolkit().beep();    //在響鈴以前actionPerformed檢查了beep
            }
         };
      Timer timer = new Timer(interval, listener);            //建立一個Timer類對象
      timer.start();        //啓動計時器
   }
}

  運行結果以下:

實驗程序3:

l  在elipse IDE中調試運行教材257頁-258頁程序6-9,結合程序運行結果理解程序;

l  瞭解靜態內部類的用法。

實驗代碼以下:

package staticInnerClass;

/**
 * This program demonstrates the use of static inner classes.
 * @version 1.02 2015-05-12
 * @author Cay Horstmann
 */
public class StaticInnerClassTest
{
   public static void main(String[] args)
   {
      double[] values = new double[20];    //定義一個double對象數組
      for (int i = 0; i < values.length; i++)
         values[i] = 100 * Math.random();
      ArrayAlg.Pair p = ArrayAlg.minmax(values);   
      System.out.println("min = " + p.getFirst());   //這個方法的調用者可使用getFirst和getSecond方法得到答案
      System.out.println("max = " + p.getSecond());
   }
}

class ArrayAlg    //抽象一個ArrayAlg類
{
   /**
    * A pair of floating-point numbers
    */
   public static class Pair     //在Pair對象中不須要引用任何其餘的對象,因此將這個內部類聲明爲static
   {
      private double first;    //定義兩個私有變量
      private double second;

      /**
       * Constructs a pair from two floating-point numbers
       * @param f the first number
       * @param s the second number
       */
      public Pair(double f, double s)       //Pair構造器
      {
         first = f;
         second = s;
      }

      /**
       * Returns the first number of the pair
       * @return the first number
       */
      public double getFirst()  //getFirst方法聲明
      {
         return first;
      }

      /**
       * Returns the second number of the pair
       * @return the second number
       */
      public double getSecond()       //getSecond方法聲明
      {
         return second;
      }
   }

   /**
    * Computes both the minimum and the maximum of an array
    * @param values an array of floating-point numbers
    * @return a pair whose first element is the minimum and whose second element
    * is the maximum
    */
   public static Pair minmax(double[] values) 
   //必須使用靜態內部類,由於內部類對象是在靜態方法中定義的,若是沒有將Pair聲明爲static,編譯器會報錯,沒有可用的隱式ArrayAlg類型對象初始化內部對象    
   {
      double min = Double.POSITIVE_INFINITY;
      double max = Double.NEGATIVE_INFINITY;
      for (double v : values)
      {
         if (min > v) min = v;
         if (max < v) max = v;
      }
      return new Pair(min, max);   //minmax必須返回返回一個Pair類型的對象
   }
}

  運行結過以下:

實驗3: 編程練習

l  編制一個程序,將身份證號.txt 中的信息讀入到內存中;

l  按姓名字典序輸出人員信息;

l  查詢最大年齡的人員信息;

l  查詢最小年齡人員信息;

l  輸入你的年齡,查詢身份證號.txt中年齡與你最近人的姓名、身份證號、年齡、性別和出生地;

l  查詢人員中是否有你的同鄉。

實驗代碼以下:

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 IDTest{
    private static ArrayList<Student> studentlist;     
    public static void main(String[] args) {
        studentlist = new ArrayList<>();
        Scanner scanner = new Scanner(System.in);
        File file = new File("D:\\java\\身份證號.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();
        }
        boolean isTrue = true;
        while (isTrue) {
        	System.out.println("1:按姓名字典序輸出人員信息;");
            System.out.println("2:查詢最大年齡與最小年齡人員信息;");
            System.out.println("3.輸入你的年齡,查詢身份證號.txt中年齡與你最近人的姓名、身份證號、年齡、性別和出生地");
            System.out.println("4:按省份找你的同鄉;");
            System.out.println("5:退出");
            String m = scanner.next();
            switch (m) {
            case "1":
                Collections.sort(studentlist);  
                System.out.println("排序後的結果爲:" + "\n");
                System.out.println(studentlist.toString());
                break;
            case "2":
                 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("Max  age:"+studentlist.get(k1));
                 System.out.println("Min  age:"+studentlist.get(k2));
                break;
            case "3":
                System.out.println("age:");
                int yourage = scanner.nextInt();
                int near=agenear(yourage);
                int value=yourage-studentlist.get(near).getage();
                System.out.println("年齡與你最近的人的姓名、身份證號、年齡、性別和出生地爲:" + "\n");
                System.out.println(""+studentlist.get(near));
                break;
            case "4":
                System.out.println(" Which province were you born in?");
                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("查找到的老鄉有:" + "\n" +studentlist.get(i));
                }             
                break;
                
            case "5":
                isTrue = false;
                System.out.println("退出程序!!!!");
                break;
                default:
                System.out.println("信息輸入有誤!!!");

            }
        }
    }
        public static int agenear(int age) {      
        int j=0,min=53,value=0,k=0;
         for (int i = 0; i < studentlist.size(); i++)
         {
             value=studentlist.get(i).getage()-age;
             if(value<0) value=-value; 
             if (value<min) 
             {
                min=value;
                k=i;
             } 
          }    
         return k;         
      }

}

  

public class Student implements Comparable<Student> {    //定義實現Comparable<Student>接口的類Student

    private String name;          //私有變量的定義
    private String number ;
    private String sex ;
    private int age;
    private String province;
   
    public String getName() {          //構造器
        return name;      
    }
    public void setName(String name) {    //訪問器
        this.name = name;
    }
    public String getnumber() {
        return number;
    }
    public void setnumber(String number) {   
        this.number = number;
    }
    public String getsex() {
        return sex ;
    }
    public void setsex(String sex ) {
        this.sex =sex ;
    }
    public int getage() {

        return age;
        }
    public void setage(int age) {
        this.age= age;
        }

    public String getprovince() {
        return province;
    }
    public void setprovince(String province) {
        this.province=province ;
    }

    public int compareTo(Student o) {		//compareTo方法將會返回一個整型數值
       return this.name.compareTo(o.getName());
    }

    public String toString() {
        return  name+"\t"+sex+"\t"+age+"\t"+number+"\t"+province+"\n";
    }    
}

  運行結果以下:

 實驗總結:(10分)

            經過這一週的學習,我大體掌握了接口的概念和實現方法,可以理解助教對接口這一部分知識的總結,也學會了使用接口編寫簡單的例子,會使用comparable接口裏的CompareTo和Comparator方法,接口和繼承在某些方面比較類似,可是接口相較繼承克服了java單繼承的缺點。以及初步的瞭解了克隆的概念。在實驗的過程當中,加深了對接口的定義以及其方法的實現的理解。雖然講的感受都理解了,可是在本身編寫相關代碼的過程當中,本身仍是不能獨立完成,在借鑑以後才勉強完成了本次博客園做業。本週的Java內容還有好多感受沒有學會,在課下我會好好完成不懂內容的學習。

相關文章
相關標籤/搜索