201521123063 《JAVA程序設計》 第5周學習總結

1. 本週學習總結

1.1 嘗試使用思惟導圖總結有關多態與接口的知識點。

1.2 可選:使用常規方法總結其餘上課內容。

  • 上週學習了繼承和多態,知足is-a條件,可是發現會致使繼承的濫用,若是隻是但以的想擁有某種行爲或變量,不須要必定要繼承才能實現,可使用接口html

  • Comparable和Comparator區別:
    Comparable接口只提供了int compareTo(T o)方法,而Comparator接口只提供了int compare(T o1,T o2)方法
    Comparator位於包java.util下,須要導入java.util.Comparator類,而Comparable位於包java.lang下,不須要導包
    排序方法:
    Collections.sort((List list, Comparator<? super T> c)
    Arrays.sort((List list, Comparable<? super T> c)
  • 接口與抽象類
    抽象類表示這個類是什麼,接口類表示這個類能作什麼
    抽象類和接口都不能直接實例化
    抽象類能夠有具體的方法 和屬性,接口只能有抽象方法和不可變常量
    一個類只能繼承一個抽象類,而一個類卻能夠實現多個接口
    接口和抽象類區別java

2. 書面做業

1. 代碼閱讀:Child壓縮包內源代碼

1.1 com.parent包中Child.java文件可否編譯經過?哪句會出現錯誤?試改正該錯誤。並分析輸出結果。git

在Child類中
 public void getParenti(){
        System.out.println(i);//此處報錯:i不可見
    }
分析:在Child的類中沒有i這個屬性,則morning會調用父類的i,可是i被private修飾,只容許本類訪問,可改成protected,這樣就能夠容許子類訪問了

輸出結果:
1
2
2
1
1
2
1
分析結果:
因爲子類Child類中沒有i,j屬性,那麼就會使用父類的屬性,因此那些輸出結果都是用父類的i和j

1.2 另一個包中的OutOfParentPackage.java,可否編譯經過?提示什麼錯誤?分析緣由。如何更改才能使之正常編譯?算法

public class OutOfParentPackage{
    public static void showParentj(Parent p){
        System.out.println(p.j);     //報錯
        System.out.println(p.geti());//報錯
        p.getj();                    //報錯
    }
}

答:不能經過編譯,根據eclipse提示能夠在Parent類中用getter和setter方法,或者將j的屬性改成public修飾的,可是不大安全就是了,同理,也將geti和getj方法改成public的編程

2. abstract進階:閱讀GuessGame抽象類的設計與使用源代碼

2.1 Guess改造前代碼很簡單,而改造後的代碼使用了抽象類、抽象方法看起來很複雜,那這樣的改造到底有什麼好處呢?數組

改造前:
import java.util.Scanner;

public class Guess {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int number = (int) (Math.random() * 10);
        int guess;
        
        do {
            System.out.print("猜數字(0 ~ 9):");
            guess = scanner.nextInt();
        } while(guess != number);
        
        System.out.println("猜中了...XD");
    }
}

改造以後:
public abstract class GuessGame {
    public void go() {
        int number = (int) (Math.random() * 10); 
        int guess;
        do {
            print("輸入數字");
            guess = nextInt();
        } while(guess != number);
        println("猜對了");
    }
    
    public abstract void print(String text);
    public abstract void println(String text);
    public abstract int nextInt();
}

分析:改造前的代碼比較中規中矩,但只能在控制檯輸入輸出,該造後,用abstract修飾輸出輸入的方法,使其抽象化,能夠在控制檯,圖形界面或者以其餘方式進行安全

2.2 若是想將該遊戲改形成圖形界面,應該進行一些什麼操做?框架

答:首先確定是要導入工具包,由於輸入輸出,還有獲取輸入都是用抽象方法,具體實現的內容是由繼承這些類的子類來重寫這些方法來實現

2.3 結合該例子,你以爲何時應該使用abstract?dom

答: 當一個類中沒有充足的信息來描述一個具體的對象時,能夠用abstract,以不變應萬變

2.4 重要:在這個例子中,變化的是什麼,不變的是什麼?嘗試結合abstract、繼承等概念進行說明。eclipse

答:能夠變化的是繼承GuessGame的子類中複寫父類的方法,即輸入輸出的方式;不變的是父類抽象類方法的定義,這些類不須要有具體的內容,畢竟不知道要幹啥,能夠隨機應變,由於任何繼承這個抽象類的子類都必須複寫父類的抽象方法,這樣想作什麼就讓子類來作就行了

3. Comparable與Comparator

3.1 描述Comparable接口的用途。爲何某個類實現了Comparable接口就能夠直接使用Arrays.sort對其進行排序?
在API中查找的結果:

public static void sort(Object[] a)根據元素的天然順序對指定對象數組按升序進行排序。數組中的全部元素都必須實現 Comparable 接口。此外,數組中的全部元素都必須是可相互比較的(也就是說,對於數組中的任何 e1 和 e2 元素而言,e1.compareTo(e2) 不得拋出 ClassCastException)。
保證此排序是穩定的:不會因調用 sort 方法而對相等的元素進行從新排序。

該排序算法是一個通過修改的合併排序算法(其中,若是低子列表中的最高元素小於高子列表中的最低元素,則忽略合併)。此算法提供可保證的 n*log(n) 性能。 


參數:
a - 要排序的數組 
拋出: 
ClassCastException - 若是數組包含不可相互比較的 的元素(例如,字符串和整數)。

簡要分析:comparable接口當中含有compareTo比較具體方法,可是隻能按一種方式比較

3.2 有了Comparable接口爲何還須要Comparator接口呢?

Arrays.sort(T[] a, Comparator<? super T> c) 
          根據指定比較器產生的順序對指定對象數組進行排序。
API文檔中查找的結果:
sort
public static <T> void sort(T[] a,
                            Comparator<? super T> c)根據指定比較器產生的順序對指定對象數組進行排序。數組中的全部元素都必須是經過指定比較器可相互比較的(也就是說,對於數組中的任何 e1 和 e2 元素而言,c.compare(e1, e2) 不得拋出 ClassCastException)。
保證此排序是穩定的:不會因調用 sort 方法而對相等的元素進行從新排序。

該排序算法是一個通過修改的合併排序算法(其中,若是低子列表中的最高元素小於高子列表中的最低元素,則忽略合併)。此算法提供可保證的 n*log(n) 性能。 

參數:
a - 要排序的數組
c - 肯定數組順序的比較器。null 值指示應該使用元素的天然順序。 
拋出: 
ClassCastException - 若是數組包含使用指定的比較器不可相互比較的 的元素。

簡要分析:有了Comparable接口,Arrays.sort實現比較算法進行排序,可是形式比較單一,有了Comparator接口,在集合外定義compare()的方法,能夠重寫compare方法。傳入了兩個參數,就能夠根據不一樣的排序要求做出排序,比較靈活,在書上284頁也有相應的例子

3.3 可選:使用匿名內部類、Lambda表達式實現PTA編程5-2。

匿名內部類:(主要代碼)

Comparator<PersonSortable2> n1 = new Comparator<PersonSortable2>() {      //按年齡升序,定義了匿名內部類
            public int compare(PersonSortable2 o1, PersonSortable2 o2) {

                return o1.getAge() - o2.getAge();
            }
        };                                                            //注意此處的分號
        Arrays.sort(p, n1);
        System.out.println("NameComparator:sort");
        for (int i = 0; i < n; i++) {
            System.out.println(p[i]);
        }
        Comparator<PersonSortable2> n2 = new Comparator<PersonSortable2>() {   //按姓名升序排序
            public int compare(PersonSortable2 o1, PersonSortable2 o2) {

                return o1.getName().compareTo(o2.getName());
            }
        };
        Arrays.sort(p, n2);
        System.out.println("AgeComparator:sort");
        for (int i = 0; i < n; i++) {
            System.out.println(p[i]);
        }
        System.out.println(Arrays.toString(n1.getClass().getInterfaces()));
        System.out.println(Arrays.toString(n2.getClass().getInterfaces()));
Lambda表達式:
    Comparator<PersonSortable2> n1 = (PersonSortable2 o1, PersonSortable2 o2) -> (o1.getName().compareTo(o2.getName()));  

        Comparator<PersonSortable2> n2 = (PersonSortable2 o1, PersonSortable2 o2) -> (o1.getAge() - o2.getAge());  

補充格式:
     參數 -> 表達式或程序塊{  }
     若是是表達式,則return該表達式的值(無需寫return語句)
     若是是程序塊{ },能夠包含多條語句

截圖:

4. 面向接口案例分析

閱讀Case-StudentDao.zip案例
4.1 畫出類關係圖,描述每一個類與接口的做用。

此圖由eclipse的UML自動生成


Student類當中只有name這個屬性,有有參的構造函數,還有其對應的setter和getter方法

StudentDao接口定義了讀寫學生信息和顯示所有學生信息的抽象方法,

StudenDaoListImpl類實現了StudentDao接口,用列表來存儲Student類的對象,readStudent方法是經過遍歷列表找到目標,writeStudent是直接經過add添加新的對象

StudentDaoArrayImpl類也實現了StudentDao接口,不過是默認存儲Student對象數組大小爲80,與StudenDaoListImpl類有點不一樣的是讀入信息是判斷數組元素是否爲空,才存入數組,其餘大同小異

Test類就是含有入口函數,測試用的

4.2 StudenDaoListImpl與StudentDaoArrayImpl有何區別?

答:顧名思義,前者是用List列表來存儲對象,後者是用數組來存儲對象,只是實現方式不同,結果是同樣的

5. 什麼是面向接口編程?面向接口編程的好處是什麼?

結合題目3與4中的Test.java的代碼討論分析。不要百度原封不動照搬!

答;面向接口編程就是在面向對象的前提下,因爲各個對象之間有可能存在協做關係,因此能夠採用接口來實現交互,題目3中的Comparable和Comparator接口一樣都是用來比較的,可是後者是能夠比較一個類生成的兩個對象之間屬性的比較,同爲比較,可是實現的方式不一樣,題目4的StudenDaoListImpl與StudentDaoArrayImpl一樣實現的結果是同樣的,面向接口編程,就是在實現的方式不清楚的狀況下,定義的一個接口,讓其餘類實現這個接口,再根據狀況來寫具體的內容,有了接口可變性比較強,可以解決需求變化。在書上202頁第一段就有提到:寫程序要有彈性,要有可維護性。

6. 結對編程:面向對象設計(大做業2-很是重要)

6.1內容:使用Java代碼完成上週作的面向對象設計大做業,須要有初步界面。實現的功能儘可能簡單,少而精,只包含必要的功能,不要追求高大全。
寫出:類圖(儘可能精簡,不用太多子類,兩個便可)、系統經常使用功能描述、關鍵代碼與界面
形式: 兩人依託碼雲合做完成。請在這裏貼出大家的學號、姓名與任務分工。
注意: 再過幾回課要講Java圖形界面編程,到時候要將該系統升級爲圖形界面。系統的業務邏輯部分應該變化不大,變化大的是輸入與輸出部分。因此編碼的時候,輸入(Scanner)與輸出(System.out)的代碼,請不要將其與某個業務處理函數綁死。
選作加分: 給出兩人在碼雲上同一項目的提交記錄截圖,額外加分。注:兩我的在碼雲上新建一個項目。
參考資料:
結對編程參考資料
可使用Processon畫圖

參考書面做業第三、4題的作法,使輸入輸出抽象化
類圖:

學生L 學生null 項目地址
https://q.cnblogs.com/u/lyq063/ https://git.oschina.net/jmulyq/ShoppingCart.git

6.2 經常使用功能描述框架圖

6.3 關鍵代碼

輸入輸出接口:
public interface shop {
    //輸入輸出方式抽象化
    public void print(String text);
    public abstract void println(String text);
    public abstract int nextInt();
    public abstract Double nextDouble();
    public abstract String next();
}

菜單類:
public class Menu implements shop{
    

    private Scanner scan = new Scanner(System.in);
    int k=0;
    
    public void showmenu(Cart cart){
        println("**********歡迎光臨**********");
        println("        1.瀏覽商品");
        println("        2.查找商品");
        println("        3.加入購物車");
        println("        4.個人購物車");
        println("        0.退出");
        println("請選擇:");
        int choice=nextInt();
        Iterm[] booklist=Iterm.allproduct();
        switch(choice){
            case 1:{
                for(Iterm i:booklist){
                    println(i.toString2());
                }
                break;
            }
            case 2:{
                boolean flag=false;
                String prudoct=next();
                for(k=0;k<booklist.length;k++){
                    if(booklist[k].getName().equals(prudoct)){
                        println(booklist[k].toString2());
                        flag=true;
                        break;
                    }   
                }
                if(!flag){
                    println("您所查找的商品未找到,請從新輸入");
                    k=-1;
                }else 
                    break;
                
            }
            case 3:{
                
                if(k>=0){
                    println("請輸入數量:");
                    int num=nextInt();
                    booklist[k].setNumber(num);
                    cart.addproduct(booklist[k]);
                    cart.cartmenu(booklist[k]);
                }
                else{
                    println("錯誤操做,還未選擇商品!");
                }
                break;
            }
            case 4:{
                cart.cartmenu(booklist[k]);
                                break;
            }
            case 0:return;
        }
        showmenu(cart);
    }

    @Override
    public void print(String text) {
        
        System.out.print(text);
        
    }
    
    @Override
    public void println(String text) {
        System.out.println(text);
        
    }

    @Override
    public int nextInt() {
        return scan.nextInt();
    }

    @Override
    public Double nextDouble() {
        return scan.nextDouble();
    }

    @Override
    public String next() {
        return scan.next();
    }
}

商品類:
public class Iterm{
    private String name;
    private double price;
    public int number;
        ...一堆setter、getter、toString方法(含有兩種格式,一種是不須要輸出數量的)

}

購物車類:
public class Cart implements shop {
    ArrayList<Iterm> iterm = new ArrayList<Iterm>();
    private Scanner scan = new Scanner(System.in);
    public  void cartmenu(Iterm i) {
        println("1.刪除商品");
        println("2.結算所有商品");
        println("3.清空購物車");
        println("4.顯示購物車中全部商品");
        println("0.返回菜單");
        println("請選擇:");
        int c = nextInt();
        switch (c) {
        case 1: {
            deleteproduct(i);
            break;
        }
        case 2: {
            System.out.println(allmoney());
            break;
        }
        case 3: {
            iterm.clear();
            break;
        }
        case 4:{
            for(Iterm i1:iterm){
                System.out.println(i1.toString());
                        break;
            }
        }
        case 0: {
            return;
        }
        }
    }

    public void addproduct(Iterm i) {
        if(iterm.contains(i)){
            iterm.get(iterm.indexOf(i)).number+=i.number;
        }
        else iterm.add(i);
    }

    public void deleteproduct(Iterm i) {
        iterm.remove(i);
    }

    public double allmoney() {
        double sum = 0;
        for (Iterm i : iterm) {
            sum += i.getPrice() * i.getNumber();
        }
        return sum;
    }

    public  void showcartproduct() {
        for (Iterm i : iterm) {
            println(i.toString());
        }
    }

    ...還有複寫接口輸入輸出的方法
}

測試類:
public class PersonTest {

    public static void main(String[] args) {
        Menu menu=new Menu();
                Cart cart=new Cart();
        menu.showmenu();

    }

}

6.4 運行界面
主菜單及全部商品:

在書列表中找不到的狀況:

加入購物車並結算:

刪除當前商品:

3. 碼雲上代碼提交記錄及PTA實驗總結

題目集:jmu-Java-04-面向對象2-進階-多態接口內部類

3.1. 碼雲代碼提交記錄

  • 在碼雲的項目中,依次選擇「統計-Commits歷史-設置時間段」, 而後搜索並截圖

3.2. PTA實驗

  • 繼續完成前面未完成的實驗面向對象1-基礎-封裝繼承
  • 函數(選作:4-1)、編程(5-1, 5-2)
  • 必定要有實驗總結

    實驗總結:

  • 4-1
    待續
  • 5-1
    這題編寫了PersonSortable類,實現了Comparable接口,根據題意來重寫compareTo和toString方法
    比較簡單,注意Comparable ,「< >」內要寫比較的對象

  • 5-2
    這題用的是比較器,須要import java.util.Comparator;,應爲這題要求是分別對姓名和年齡排序,因此能夠重寫compare方法,傳入兩個對象進行屬性之間的比較 注意最後排序時候要Arrays.sort(p,new一個對象)才行,根據要求來建立對象,實現不一樣的排序方法

相關文章
相關標籤/搜索