1. 程式人生 > >201771010143 張雲飛《面向對象程序設計(java)》第六章學習總結

201771010143 張雲飛《面向對象程序設計(java)》第六章學習總結

ktr 升級 讀取文件 設計 via over core desktop 簡化

實驗六繼承定義與使用

實驗時間2018-9-28

1、實驗目的與要求

(1) 理解繼承的定義

特殊類的對象擁有一般類的全部屬性與行為,稱為特殊類對一般類的繼承。一個類可以是多個一般類的特殊類,也可以從多個一般類中繼承屬性與行為,但在java語言中,不允許一個類從多個一般類中繼承屬性與行為,即在java語言中,只支持單繼承。

  在軟件開發中,通過繼承機制,可以利用已有的數據類型來定義新的數據類型。所定義的新的數據類型不僅擁有新定義的成員,而且還同時擁有舊的成員。因此,類的繼承性使所建立的軟件具有開放性開放性、可擴充性,這是信息組織與分類的行之有效的方法,通過類的繼承關系,使公共的特性能夠共享,簡化了對象、類的創建工作量,增加了代碼的可重用性。

掌握子類的定義要求

第一種
super.xxx;(xxx為變量名或對象名)
這種方法意義為,獲取父類中的名字為xxx的變量或方法引用。
使用這種方法可以直接訪問父類中的變量或對象,進行修改賦值等操作
第二種
super.xxx();(xxx為方法名)
這種方法意義為,直接訪問並調用父類中的方法。
第三種
super();
這種方法意義為,調用父類的初始化方法,其實就是調用父類中的public xxx()方法

掌握多態性的概念及用法

運行時多態性是面向對象程序設計代碼重用的一個最強大機制,Java多態性的概念也可以被說成“一個接口,多個方法”。Java實現運行時多態性的基礎是動態方法調度,它是一種在運行時而不是在編譯期調用重載方法的機制。

方法的重寫Overriding和重載OverloadingJava多態性的不同表現。重寫Overriding是父類與子類之間多態性的一種表現,重載Overloading是一個類中多態性的一種表現。如果在子類中定義某方法與其父類有相同的名稱和參數,我們說該方法被重寫(Overriding)。子類的對象使用這個方法時,將調用子類中的定義,對它而言,父類中的定義如同被“屏蔽”了。如果在一個類中定義了多個同名的方法,它們或有不同的參數個數或有不同的參數類型,則稱為方法的重載(Overloading)Overloaded的方法是可以改變返回值的類型。方法的重寫Overriding和重載Overloading

Java多態性的不同表現。當超類對象引用變量引用子類對象時,被引用對象的類型而不是引用變量的類型決定了調用誰的成員方法,但是這個被調用的方法必須是在超類中定義過的,也就是說被子類覆蓋的方法。 (但是如果強制把超類轉換成子類的話,就可以調用子類中新添加而超類沒有的方法了。

(4) 掌握抽象類的定義及用途

抽象類就是不能使用new方法進行實例化的類(不能被實例化,可以有多個抽象方法),即沒有具體實例對象的類,抽象類有點類似於“模板”的作用,目的是根據其格式來創建和修改新的類,對象不能由抽象類直接創建,只可以通過抽象類派生出新的子類,再由其子類來創建對象,當一個類被聲明為抽象類時,要在這個類前面加上修飾符abstract,在抽象類中的成員方法可以包括一般方法和抽象方法

(5) 掌握類中4個成員訪問權限修飾符的用途;

public修飾的類可以在其他任意包訪問
protect修飾的類可以在同包內訪問
default修飾的類可以在本類和同包中訪問
private是私有的意思只能在本類中訪問

(6) 掌握抽象類的定義方法及用途

抽象類的特點:
1,抽象方法一定在抽象類中。
2,抽象方法和抽象類都必須被abstract關鍵字修飾。
3,抽象類不可以用new創建和實例化對象。因為抽象類本身就是不完整的。
4,抽象類中的抽象方法要被使用,必須由子類復寫所有的抽象方法後,建立子類對象調用。

(7)掌握Object用途及常用API

所有的類都是Object的子類 ,所以所有的對象都能用Object接住 , 所有的對象都可以使用Object中的方法

(8) 掌握ArrayList類的定義方法及用法

ArrayList就是傳說中的動態數組,用MSDN中的說法,就是Array的復雜版本,它提供了如下一些好處:
動態的增加和減少元素
實現了ICollectionIList接口
靈活的設置數組的大小

掌握枚舉類定義方法及用途。

枚舉是一種特殊的數據類型,之所以特殊是因為它既是一種類(class)類型卻又比類型多了些特殊的約束,但是這些約束的存在也造就了枚舉類型的簡潔,安全性以及便捷性。創建枚舉類型要使用enum關鍵字,隱含了所創建的類型都是java.lang.Enum類的子類(java.lang.Enum是一個抽象類)。枚舉類型符合通用模式Class Enum<E extends Enum<E>>,而E表示枚舉類型的名稱。枚舉類型的每一個值都映射到protected Enum(String name,int ordinal)構造函數中,在這裏,每個值的名稱都轉換成一個字符串,並且序數設置表示了此設置被創建的順序。

2、實驗內容和步驟

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

測試程序1

? 在elipse IDE中編輯、調試、運行程序5-1 (教材152頁-153

? 掌握子類的定義及用法;

? 結合程序運行結果,理解並總結OO風格程序構造特點,理解Employee和Manager類的關系子類的用途,並在代碼中添加註釋。

public class ManagerTest

{

public static void main(String[] args)

{

// 構造一個mananger對象

Manager boss = new Manager("Carl Cracker", 80000, 1987, 12, 15);

boss.setBonus(5000);

Employee[] staff = new Employee[3];

// 使用employee 和mananger對象填補staff數組

staff[0] = boss;

staff[1] = new Employee("Harry Hacker", 50000, 1989, 10, 1);

staff[2] = new Employee("Tommy Tester", 40000, 1990, 3, 15);

// 顯示所有employee對象的所有信息

for (Employee e : staff)

System.out.println("name=" + e.getName() + ",salary=" + e.getSalary());

}

}

測試結果;

技術分享圖片

測試程序2:

? 編輯、編譯、調試運行教材PersonTest程序(教材163頁-165頁);

? 掌握超類的定義及其使用要求;

? 掌握利用超類擴展子類的要求;

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

public class PersonTest

{

public static void main(String[] args)

{

Person[] people = new Person[2];

// 以employ和student對象填充people數組

people[0] = new Employee("Harry Hacker", 50000, 1989, 10, 1);

people[1] = new Student("Maria Morris", "computer science");

// 顯示所有Person對象的姓名和描述

for (Person p : people)

System.out.println(p.getName() + ", " + p.getDescription());

}

}

測試結果:

技術分享圖片

測試程序3:

? 編輯、編譯、調試運行教材程序5-8、5-9、5-10,結合程序運行結果理解程序(教材174頁-177頁);

? 掌握Object類的定義及用法;

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

public class Employee

{

private String name;

private double salary;

private LocalDate hireDay;

public Employee(String name, double salary, int year, int month, int day)

{

this.name = name;

this.salary = salary;

hireDay = LocalDate.of(year, month, day);

}

public String getName()

{

return name;

}

public double getSalary()

{

return salary;

}

public LocalDate getHireDay()

{

return hireDay;

}

public void raiseSalary(double byPercent)

{

double raise = salary * byPercent / 100;

salary += raise;

}

public boolean equals(Object otherObject)

{

// 快速測試以查看對象是否相同

if (this == otherObject) return true;

// 如果explicit的參數為null,必須返回false

if (otherObject == null) return false;

// 如果類不匹配,那麽他們不能相等

if (getClass() != otherObject.getClass()) return false;

// 現在我們知道otherObject是一個非null的Employee類

Employee other = (Employee) otherObject;

// 測試字段是否具有相同的值

return Objects.equals(name, other.name) && salary == other.salary && Objects.equals(hireDay, other.hireDay);

}

public int hashCode()

{

return Objects.hash(name, salary, hireDay);

}

public String toString()

{

return getClass().getName() + "[name=" + name + ",salary=" + salary + ",hireDay=" + hireDay

+ "]";

}

}

測試結果;

技術分享圖片

測試程序4

? 在elipse IDE中調試運行程序5-11(教材182頁),結合程序運行結果理解程序;

? 掌握ArrayList類的定義及用法;

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

public class ArrayListTest

{

public static void main(String[] args)

{

// 用三個Employee對象填補staff數組列表

ArrayList<Employee> staff = new ArrayList<>();

staff.add(new Employee("Carl Cracker", 75000, 1987, 12, 15));

staff.add(new Employee("Harry Hacker", 50000, 1989, 10, 1));

staff.add(new Employee("Tony Tester", 40000, 1990, 3, 15));

// 將每個人的工資提升5%

for (Employee e : staff)

e.raiseSalary(5);

//顯示employ對象的所有信息

for (Employee e : staff)

System.out.println("name=" + e.getName() + ",salary=" + e.getSalary() + ",hireDay="

+ e.getHireDay());

}

}

測試結果:

技術分享圖片

?

測試程序5:

? 編輯、編譯、調試運行程序5-12(教材189頁),結合運行結果理解程序;

? 掌握枚舉類的定義及用法;

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

package enums;

import java.util.*;

/**
 * This program demonstrates enumerated types.
 * @version 1.0 2004-05-24
 * @author Cay Horstmann
 */
public class EnumTest
{  
   public static void main(String[] args)
   {  
      Scanner in = new Scanner(System.in);
      System.out.print("Enter a size: (SMALL, MEDIUM, LARGE, EXTRA_LARGE) ");
      String input = in.next().toUpperCase();
      Size size = Enum.valueOf(Size.class, input);
      System.out.println("size=" + size);
      System.out.println("abbreviation=" + size.getAbbreviation());
      if (size == Size.EXTRA_LARGE)//判斷語句
         System.out.println("Good job--you paid attention to the _.");      
   }
}

enum Size
{
   SMALL("S"), MEDIUM("M"), LARGE("L"), EXTRA_LARGE("XL");

   private Size(String abbreviation) { this.abbreviation = abbreviation; }
   public String getAbbreviation() { return abbreviation; }

   private String abbreviation;
}
測試結果:
技術分享圖片

 

實驗2編程練習1

? 定義抽象類Shape:

屬性不可變常量double PI,值為3.14

方法:public double getPerimeter();public double getArea())。

? RectangleCircle繼承自Shape類。

? 編寫double sumAllArea方法輸出形狀數組中的面積和和double sumAllPerimeter方法輸出形狀數組中的周長和。

? main方法中

1輸入整型值n,然後建立n個不同的形狀。如果輸入rect,則再輸入長和寬。如果輸入cir,則再輸入半徑。
2) 然後輸出所有的形狀的周長之和,面積之和。並將所有的形狀信息以樣例的格式輸出。
3) 最後輸出每個形狀的類型與父類型使用類似shape.getClass()(獲得類型),shape.getClass().getSuperclass()(獲得父類型);

思考sumAllAreasumAllPerimeter方法放在哪個類中更合適?

輸入樣例:

3

rect

1 1

rect

2 2

cir

1

輸出樣例:

18.28

8.14

[Rectangle [width=1, length=1], Rectangle [width=2, length=2], Circle [radius=1]]

class Rectangle,class Shape

class Rectangle,class Shape

class Circle,class Shape

package 兩個圖形的;

import java.util.Scanner;

public class cirec {

double PI=3.14;

public double AllArea(Shape score[])

{

double sum=0;

for(int i=0;i<score.length;i++)

sum+= score[i].getArea();

return sum;

}

public double AllPerimeter(Shape score[])

{

double sum=0;

for(int i=0;i<score.length;i++)

sum+= score[i].getPerimeter();

return sum;

}

public static void main(String[] args) {

Scanner in = new Scanner(System.in);

System.out.println("請輸入創建圖形的個數");

int a = in.nextInt();

System.out.println("請輸入圖形種類(選擇輸入cir或rect)");

String rect="rect";

String cir="cir";

Shape[] num=new Shape[a];

for(int i=0;i<a;i++){

String input=in.next();

if(input.equals(rect)) {

System.out.println("請輸入長和寬");

int width = in.nextInt();

int length = in.nextInt();

num[i]=new 長方形(width,length);

System.out.println("長方形["+"長方形的長為:"+length+" 長方形的寬為:"+width+"]");

}

if(input.equals(cir)) {

System.out.println("輸入所創建的圓的半徑");

int r = in.nextInt();

num[i]=new 圓形(r);

System.out.println("圓["+"圓的半徑為:"+r+"]");

}

}

cirec c=new cirec();

System.out.println("求所有圖形的面積和:");

System.out.println(c.AllPerimeter(num));

System.out.println("求所有圖形的周長和:");

System.out.println(c.AllArea(num));

for(Shape s:num) {

System.out.println(s.getClass()+","+s.getClass().getSuperclass());

}

}

}

package 兩個圖形的;

abstract class Shape {

abstract double getPerimeter();

abstract double getArea();

}

class 圓形extends Shape{

private double PI=3.14;

private int r;

public 圓形(int r) {

this.r = r;

}

double getPerimeter(){

return 2 * PI * r;

}

double getArea(){

return r * r*PI;

}

}

class 長方形extends Shape{

private int width;

private int length;

public 長方形(int length, int width) {

this.width = width;

this.length = length;

}

double getPerimeter(){

return 2*(length+width);

}

double getArea(){

return length*width;

}

}

運行結果:

技術分享圖片

實驗3 編程練習2

編制一個程序,將身份證號.txt 中的信息讀入到內存中,輸入一個身份證號或姓名,查詢顯示查詢對象的姓名、身份證號、年齡、性別和出生地。

public class people {

private String name;

private String number;

private String age;

private String sex;

private String address;

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 getage()

{

return age;

}

public void setage(String age )

{

this.age = age;

}

public String getsex()

{

return sex;

}

public void setsex(String sex )

{

this.sex = sex;

}

public String getaddress()

{

return address;

}

public void setaddress(String address)

{

this.address = address;

}

}

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.Scanner;

public class Demo3 {

// 創建一個泛型列表來保存人員身份信息

private static ArrayList<people> peoplelist;

public static void main(String[] args) {

peoplelist = new ArrayList<>();

Scanner scanner = new Scanner(System.in);

// 拿到人員身份信息文件

File file = new File("/Users/eleanorliu/Desktop/學習/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 id = linescanner.next();

String sex = linescanner.next();

String age = linescanner.next();

String address = linescanner.nextLine();

People people = new People();

people.setName(name);

people.setid(id);

people.setage(age);

people.setsex(sex);

people.setaddress(address);

peoplelist.add(people);

}

// 讀取文件裏面的學生信息

} catch (FileNotFoundException e) {

// TODO Auto-generated catch block

// 程序異常時在這裏處理

System.out.println("身份信息文件找不到");

e.printStackTrace();

} catch (IOException e) {

// TODO Auto-generated catch block

System.out.println("身份信息文件讀取錯誤");

e.printStackTrace();

}

// 通過選擇語句做一個提示界面

boolean isTrue = true;

while (isTrue) {

System.out.println("歡迎來到人員身份信息查詢系統,請選擇你的操作");

System.out.println("1.按姓名查詢");

System.out.println("2.身份證號碼查詢");

System.out.println("3.退出");

int nextInt = scanner.nextInt();

switch (nextInt) {

case 1:

System.out.println("請輸入姓名");

String peoplename = scanner.next();

int nameint = findPeopleByname(peoplename);

if (nameint != -1) {

// 存在這個人

System.out.println(" 姓名:"+ people.getName() +

" 身份證號:"+ people.getnumber() +

" 年齡:"+ people.getage()+

" 性別:"+ people.getsex()+

" 地址:"+ people.getplace()

);

} else {

System.out.println("不存在該人信息");

}

break;

case 2:

System.out.println("請輸入學號");

String studentid = scanner.next();

int idint = findPeopleByid(studentid);

if (idint != -1) {

// 存在這個學生

System.out.println(" 姓名:"+ people.getName() +

" 身份證號:"+ people.getnumber() +

" 年齡:"+ people.getage()+

" 性別:"+ people.getsex()+

" 地址:"+ people.getplace()

);

} else {

System.out.println("不存在該人信息");

}

break;

case 3:

isTrue = false;

System.out.println("程序已退出!");

break;

default:

System.out.println("輸入有誤");

}

}

}

/*

* 新建一個方法來通過姓名查找

*/

public static int findPeopleByname(String name) {

int flag = -1;

// 比對姓名

for (int i = 0; i < peoplelist.size(); i++) {

if (peoplelist.get(i).getName().equals(name)) {

flag = i;

}

}

return flag;

}

/*

* 新建一個方法來通過身份證號查找

*/

public static int findPeopleByid(String id) {

int flag = -1;

// 比對身份證號

for (int i = 0; i < peoplelist.size(); i++) {

if (peoplelist.get(i).getId().equals(id)) {

flag = i;

}

}

return flag;

}

}

運行結果:

由於系統兼容性的問題,漢字沒能正常顯示。

技術分享圖片

第六周學習總結:本周學習的繼承,可以利用已有的數據類型來定義新的數據類型。所定義的新的數據類型不僅擁有新定義的成員,而且還同時擁有舊的成員。一開始導入示例程序寫備註的時候還覺得自己大概已經理解了繼承的使用方法。但是在寫第一個實驗程序的時候就出現了很多問題,比如如何在抽象類中封裝好算法,然後在從主類中將其調用等等。第二個程序感覺是上一次那個studentfile 的升級版,有一點難度,但是對照學長上一次的示例程序也勉強完成了。這一階段的學習感覺到了明顯的難度,還需要繼續努力。

201771010143 張雲飛《面向對象程序設計(java)》第六章學習總結