博文正文開頭格式:(2分)html
項目java |
內容算法 |
這個做業屬於哪一個課程編程 |
https://www.cnblogs.com/nwnu-daizh/數組 |
這個做業的要求在哪裏安全 |
https://www.cnblogs.com/nwnu-daizh/p/11435127.htmlide |
做業學習目標函數 |
|
第一部分:總結第五章理論知識(30分)工具
一、類、超類和子類學習
(1)繼承:用已有類來構建新類的一種機制。當定義了一個新類繼承了一個類時,一個新類就繼承了這個類的方法和域,同時在新類中添加新的方法和域以適應新環境。
(2)繼承是Java程序設計中的一項核心技術,也是面向對象特徵之一。
(3)繼承的特色:具備層次結構;子類繼承父類的方法和域。
(4)繼承的優勢:代碼可重用性;父類的域和方法可用於子類;設計應用程序變得更加簡單;能夠輕鬆定義子類。
類繼承的格式:
class 新類名 extends 已有類名
(1)已有類成爲: 超類(superclass),基類(base class)或父類(parent class);
————來自系統類庫;
————用戶自定義類;
(2)新類稱做:子類(subclass)、派生類(derived class)或孩子類(child class);
(3)通常來講,子類比超類擁有的功能更加豐富。
注意:
(1)因爲子類的構造器不能直接訪問超類的私有域,必須調用超類構造器,並且必須是第一條語句;
(2)子類不能直接訪問超類的構造器,必須和其餘方法同樣————使用公共接口;
(3)父類對象能夠引用子類對象;
(4)多態性質。
1)經過擴展超類定義子類時,僅須要指出子類和超類的不一樣之處。在子類中能夠增長域,增長方法或覆蓋(override)超類的方法,但絕對不能刪除超類的任何域和方法;
2)super是一個指示編譯器調用超類方法的特有關鍵字,它不是一個對象的引用,不能將super賦值給另外一個對象變量。
suer關鍵字有兩個特殊的用途:
(1)調用超類的方法,(格式: super. 方法名() );
(2)調用超類的構造器(格式: super());
3)若子類的構造器沒有顯示地調用 超類的構造器,則將自動的調用超類默認構造器,若子類構造器沒有顯示地調用超類的構造器,則Java報告器將報告錯誤。
子類不繼承超類的構造方法;
方法覆蓋只能在不一樣的類中完成;
二、繼承層次:
(1)從一個超類擴展而來的類集合稱爲層次繼承。在繼承層次中,從某個類到繼承祖先的路徑被稱爲該類的繼承鏈。
(2)Java不支持多繼承:即一個超類能夠有多個子類,但一個子類只能有一個超類(父類)。
三、多態性:
(1)多態性的概念:多態性泛指在程序中同一個符號在不一樣狀況下具備不一樣解釋的現象;
(2)超類中定義的域或方法,被子類繼承以後,能夠具備不一樣的數據類型或表現出不一樣的行爲;
(3)這使得在超類及其子類中同名的域或方法具備相同的語義;
(4)超類中的方法在子類中可方法重寫。
(5)Java中,對象變量是多態的;
(6)不能把對超類的對象引用賦給子類對象變量;
(7)注意子類數組和超類數組的關係;
(8)繼承層次結構中,每一個子類對象也可視做是超類對象,所以,能夠將子類對象賦給超類對象。
四、抽象類:
(1)觀察類的層次結構,位於上層的類更具通用性,甚至更加抽象。從某種角度看,祖先類更加通用,人們只將它做爲派生其餘類的基類(超類),而不做爲特定的實例類。
(2)抽象類的定義:
abstract class Person
{
public abstract String getDescription();
...... ↓
} abstract 方法:只能聲明,不能實現;
注意:
(1)爲了提升程序的清晰度,包含一個或多個抽象方法的類自己必須被聲明爲抽象類。除了抽象方法以外,抽象類還能夠包含具體數據和具體方法;
(2)抽象方法充當着佔位的角色,它們的具體實如今子類中。擴展抽象類能夠用兩種選擇:一種是在子類中實現部分抽象方法,這樣就必須將子類也標記爲抽象類;另外一種方法是實現所有抽象方法,這樣子類就能夠不是抽象類。此外,類即便不含抽象方法,也能夠將類聲明爲抽象類。
(3)抽象類不能被實例化,即不能建立對象,只能產生子類。能夠建立抽象類的對象變量,只是這個變量必須指向它的非抽象子類的對象。
五、動態綁定:
動態綁定的概念:又稱爲運行時綁定。即程序在運行時會自動選擇調用哪一個方法。
調用對象方法的執行過程:
(1)首先,編譯器檢查對象的聲明類型和方法名,搜索相應類(Son)及其父類(Father)「方法表」,找出全部訪問屬性爲public的method方法。
(2)接下來,編譯器檢查方法調用中提供的參數類型,找出一個徹底匹配的方法,這個過程稱爲重載解析。
(3)若是方法是private、static、final修飾的,或者是構造器,那麼編譯器能準確地判斷應該調用哪一個方法,這稱爲靜態綁定。
(4)程序運行時,若是子類SSon中定義了mothod()方法,則直接調用子類中的相應方法;若是子類Son中沒有定義相應的方法,則在其父類中尋找method()的方法;
(5)動態綁定中每一次調用方法都要進行搜索,時間開銷至關大。所以虛擬機預先爲每一個類建立了一個方法表,其中列出了全部方法的簽名和實際調用的方法;
(6)方法的名稱和參數列表稱爲方法的簽名。
六、阻止繼承:final類和方法
不容許繼承的類稱爲final類,在類的定義中用final修飾符來加以說明;
類中的方法可定義爲final的。這時子類就不能覆蓋該方法;
若是一個類聲明爲final,屬於它的方法會被自動設爲final,但不包括域(若是域定義爲final,在對象構造之後,final域就不能在更改了)。
private final int Max = 100;
String類是final類的一個例子,不能擴展該類。
七、強制類型轉換:
(1)若是要把一個超類對象賦給一個子類對象變量,就必須進行強制類型轉換。其格式爲:
子類 對象= (子類) (超類對象)
(2)類型轉換必須在繼承層次內進行;並且在超類轉換爲子類以前,應先使用instanceof操做符進行繼承鏈檢查。
(3)注意:應該儘可能減小類型轉換和instanceof運算符的使用。
八、繼承小結
(1)封裝、繼承你和多態性是面向對象的主要特徵;
(2)繼承可提升代碼的重用性,用extends關鍵字來實現。除構造方法以外,父類的全部方法和屬性都被子類繼承;
(3)繼承創建了類與類之間的關係,同時也是多態特徵的前提;
(4)Java只支持單繼承,不直接支持多繼承(避免兩個父類出現同名方法的調用選擇困難);
(5)abstract修飾符的抽象類不能被實例化爲對象,只能擴展子類;抽象類中的抽象方法充當着佔位的角色,它們的具體實如今子類中;
(6)final類不容許被繼承;類中final 方法不容許被子類重寫。
九、受保護訪問:
若是但願超類的某些方法或域容許被子類直接訪問,就須要在超類定義時,將這些方法或域聲明爲protected。
十、Java的四個訪問權限修飾符:
(1)private(只有該類能夠訪問)、protected(該類及其子類的成員能夠訪問,同一個包中的類也能夠訪問)、public(該類或非該類的均可以訪問)和默認(相同包中的類都可以訪問);
(2)使用訪問修飾符的緣由:實現受限信息隱藏;
(3)信息隱藏目的:
——對類中任何實現細節的更改不會影響使用該類的代碼;
——防止用戶意外刪除數據;
——易於使用類;
十一、全部類的超類:
Object 類是Java中全部類的祖先——每個類都由它擴展而來。在不給出超累的狀況下,Java會自動把Object做爲要定義的超類;
可使用類型爲Object的變量指向任意類型的對象。但要對它們進行專門的操做,都要進行強制類型轉換。
十二、equals方法:
Object類中的equals方法用於檢測某個對象是否同另外一個對象相等。它在Object類中的實現是判斷兩個對象是否相等的引用。若是兩個對象具備相同的引用,它們必定是相等的;
若是須要檢測兩個對象狀態的相等性,就須要在新類的定義中須要覆蓋equals方法;
定義子類的equals方法時,可調用超累的equals方法;
super. equals (otherObjecct)
1三、hashCode方法:
Object類中的哈hashCode方法導出某個對象的散列碼。散列碼時任意整數,表示dui過的存儲地址;
兩個相等對象的散列碼相等。
1四、toString方法:
Object類中的toString方法返回一個表明該類對象域值的字符串;
定義子類的toString方法時,可先調用超類的toString方法;
super.toString()
toString方法是很是重要的調試工具。標準類庫中,多數類定義了toString方法,以便用戶得到對象狀態的必要信息。
1五、泛型數組列表:
Java中,利用ArrayList類,可容許程序在運行時肯定數組的大小;
ArrayList是一個採用類型參數的泛型類。爲指定數組列表保存元素的對象類型,須要用一對尖括號將數組元素的對象類名括起來加在後面;
沒有<>的ArrayList類將被認爲是一個刪去了類型參數的「原始」類型。
1六、數組列表的操做:
ArrayList的定義:ArrayList<T> 對象 = new ArrayList<T>();
API:
(1)ArrayList的構造器
——ArrayList<T>()構造一個空數組列表
——ArrayList<T>(int initialCapacity)構造一個具備指定容量的空數組列表;
(2)添加新元素:
API:boolean add(T obj)把元素obj追加到數組列表的結尾;
(3)統計個數:
API:int size() 返回數組列表中當前元素的個數;
(4)調整大小:
API:void trimToSize() 把數組列表的存儲空間調整到當前的大小;
(5)訪問:
API:void Set(int index, T obj) 將obj放入到數組列表index的位置,將覆蓋這個位置原來的內容;
API:T get(int index) 將得到指定位置index的元素值;
(6)增長與刪除:
API:boolean add(T obj) 向後移動元素,在第n個位置插入obj;
API:T remove(int index) 將第n個位置存放的對象刪除,並將後面的元素向前移動;
1七、對象包裝器與自動打包:
全部基本數據類型都有與之對應的預約義類,它們被稱爲對象包裝器。
對象包裝器類是不可變的,即一旦構造了包裝器,就不容許更改包裝在其中的值。且對象包裝器類仍是final,所以不能定義它們的子類;
使用對象包裝器的好處:(1)基本類型轉換爲對象;
(2)定義一些有用的基本方法(static方法)
將基本數據類型轉換爲包裝器類對象,將這種變換稱爲自動打包;
當將一個包裝器類的對象進行賦值或算法運算時,將會自動的拆包,打包和拆包時編譯器承認的;
1八、參數數量可變的方法:
用戶本身能夠定義可變參數的方法,並將參數指定爲任意類型,甚至是基本類型;
1九、枚舉類:
(1)聲明枚舉類:public enum Grade{A、B、C、D、E};
(2)它包括一個關鍵字enum,一個新枚舉類型的名字Grade定義的一組值,這裏的值既不是整型,也不是字符型;
(3)枚舉類說明:
1)枚舉類是一個類,它的隱含超類是Java.lang.Enum。
2)枚舉值並非整型或其餘類型,是被聲明的枚舉類自己實例;
3)枚舉類不能有public 修飾的構造函數,構造函數都是隱含private,編譯器自動處理;
4)枚舉值隱含都是由public、static、final修飾的,無需本身添加這些修飾符;
5)在比較兩個枚舉類型的值時,永遠不須要調用 equals方法,直接使用「==」進行比較;
(4)爲枚舉類添加構造函數
(5)Enum類的API:
20、繼承設計的技巧:
(1)將公共操做和域放在超類;
(2)不要使用受保護的域;
(3)使用繼承實現「is-a」關係;
(4)除非全部繼承的方法都有意義,不然就不要使用繼承;
(5)在覆蓋方法時,不要改變預期的行爲;
(6)使用多態,而非類型信息。
第二的部分:實驗部分
一、實驗目的與要求
(1) 理解繼承的定義;
(2) 掌握子類的定義要求
(3) 掌握多態性的概念及用法;
(4) 掌握抽象類的定義及用途。
二、實驗內容和步驟
實驗1:測試程序1(10分)
代碼以下:
package inheritance; import java.time.*; 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; } }
package inheritance; public class Manager extends Employee //Manager類繼承Employee類 { private double bonus; /** * @param name the employee's name * @param salary the salary * @param year the hire year * @param month the hire month * @param day the hire day */ public Manager(String name, double salary, int year, int month, int day) //Manager構造器 //子類構造器,與類名同名 { super(name, salary, year, month, day); //調用父類構造器 bonus = 0; } public double getSalary() //訪問器 { double baseSalary = super.getSalary(); //基本工資由父類getSalary得到 return baseSalary + bonus; } public void setBonus(double b) //更改器 { bonus = b; } }
package inheritance; /** * This program demonstrates inheritance. * @version 1.21 2004-02-21 * @author Cay Horstmann */ public class ManagerTest { public static void main(String[] args) //構造器,構造管理者對象 { // construct a Manager object Manager boss = new Manager("Carl Cracker", 80000, 1987, 12, 15); //建立Manger類對象,對象名爲boss,引用數組建立,anager信息 boss.setBonus(5000); Employee[] staff = new Employee[3]; // fill the staff array with Manager and Employee objects //將僱員和經理全填充在數組中 staff[0] = boss; //父類對象變量能夠引用子類對象 staff[1] = new Employee("Harry Hacker", 50000, 1989, 10, 1); staff[2] = new Employee("Tommy Tester", 40000, 1990, 3, 15); // print out information about all Employee objects for (Employee e : staff) //輸出僱員對象的信息 System.out.println("name=" + e.getName() + ",salary=" + e.getSalary()); } }
運行結果以下:
實驗1:測試程序2(10分)
代碼以下:
package abstractClasses; import java.time.*; //爲第15行LocalDate方法提供服務 public class Employee extends Person { private double salary; //private:僅對本類有用 private LocalDate hireDay; public Employee(String name, double salary, int year, int month, int day) //構造器 { super(name); //建立一個超類 this.salary = salary; hireDay = LocalDate.of(year, month, day); } public double getSalary() { return salary; } public LocalDate getHireDay() { return hireDay; } public String getDescription() //建立僱員類型的方法 { return String.format("an employee with a salary of $%.2f", salary); //String.format() : 用於建立格式化的字符串以及鏈接多個字符串對象 } public void raiseSalary(double byPercent) { double raise = salary * byPercent / 100; salary += raise; } }
package abstractClasses; public abstract class Person //爲了提升程序的清晰度,包含一個或多個抽象方法的類必須被聲明爲抽象的 { public abstract String getDescription(); //abstract方法,只能聲明,不能實現 private String name; public Person(String name) //構造器。爲子類構造器提供服務 { this.name = name; } public String getName() { return name; } }
package abstractClasses; /** * This program demonstrates abstract classes. * @version 1.01 2004-02-21 * @author Cay Horstmann */ public class PersonTest { public static void main(String[] args) { Person[] people = new Person[2]; // fill the people array with Student and Employee objects people[0] = new Employee("Harry Hacker", 50000, 1989, 10, 1);//填充僱員和學生類對象數組中的信息 people[1] = new Student("Maria Morris", "computer science"); // print out names and descriptions of all Person objects for (Person p : people) //輸出學生的姓名 System.out.println(p.getName() + ", " + p.getDescription()); // p.getDescription() 因爲不能構造抽象類Person的對象,因此變量p永遠不會引用Person對象,而Employee或Student這樣的具體子類對象中都定義了getDescription方法 } }
package abstractClasses; //定義一個擴展抽象類Person的具體子類Student,這個類不是抽象類 public class Student extends Person//繼承 { private String major; /** * @param nama the student's name * @param major the student's major */ public Student(String name, String major) { // pass n to superclass constructor super(name); //建立一個超類 this.major = major; //this指代當前對象,指向當前對象的父類調用父類成員 } public String getDescription() { return "a student majoring in " + major; } }
運行結果以下:
實驗1:測試程序3(11分)
代碼以下:
package equals; import java.time.*; import java.util.Objects; 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指代當前對象 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) //Objects類中的equals方法用於檢測一個對象是否等於另一個對象 { // a quick test to see if the objects are identical if (this == otherObject) return true; // must return false if the explicit parameter is null if (otherObject == null) return false; //若是顯示參數爲空,則返回false // if the classes don't match, they can't be equal //若是不是相同類型的對象,則返回false if (getClass() != otherObject.getClass()) return false; //getClass方法將返回一個對象所屬的類 // now we know otherObject is a non-null Employee Employee other = (Employee) otherObject; // test whether the fields have identical values return Objects.equals(name, other.name) && salary == other.salary && Objects.equals(hireDay, other.hireDay); } //測試字段是否有相同的值,是否在該域中 public int hashCode() { return Objects.hash(name, salary, hireDay); //Objects.hash() 這個類用於操做對象的靜態實用方法這些工具包括用於計算對象的哈希代碼的空安全或空容錯方法,返回一個對象的字符串,並比較兩個對象 //Object類中的hashCode方法導出某個對象的散列碼。散列碼世人以整數,表示對象的存儲地址 //兩個相等對象的散列碼相等 } public String toString() //方法返回一個表明該對象域值的字符串 //toString() { return getClass().getName() + "[name=" + name + ",salary=" + salary + ",hireDay=" + hireDay + "]"; } }
package equals; /** * This program demonstrates the equals method. * @version 1.12 2012-01-26 * @author Cay Horstmann */ public class EqualsTest { public static void main(String[] args) { Employee alice1 = new Employee("Alice Adams", 75000, 1987, 12, 15); //添加各僱員對象的信息 Employee alice2 = alice1; Employee alice3 = new Employee("Alice Adams", 75000, 1987, 12, 15); Employee bob = new Employee("Bob Brandson", 50000, 1989, 10, 1); //返回僱員信息 System.out.println("alice1 == alice2: " + (alice1 == alice2)); System.out.println("alice1 == alice3: " + (alice1 == alice3)); System.out.println("alice1.equals(alice3): " + alice1.equals(alice3)); System.out.println("alice1.equals(bob): " + alice1.equals(bob)); System.out.println("bob.toString(): " + bob); //添加Manager的信息 Manager carl = new Manager("Carl Cracker", 80000, 1987, 12, 15); Manager boss = new Manager("Carl Cracker", 80000, 1987, 12, 15); boss.setBonus(5000); System.out.println("boss.toString(): " + boss); System.out.println("carl.equals(boss): " + carl.equals(boss)); System.out.println("alice1.hashCode(): " + alice1.hashCode()); System.out.println("alice3.hashCode(): " + alice3.hashCode()); System.out.println("bob.hashCode(): " + bob.hashCode()); System.out.println("carl.hashCode(): " + carl.hashCode()); } }
package equals; public class Manager extends Employee //Manager類繼承Employee類 { private double bonus; //私有域定義 public Manager(String name, double salary, int year, int month, int day) //構造器 { super(name, salary, year, month, day); bonus = 0; } public double getSalary() { double baseSalary = super.getSalary(); return baseSalary + bonus; } public void setBonus(double bonus) { this.bonus = bonus; } public boolean equals(Object otherObject) { if (!super.equals(otherObject)) return false; //檢查超類是否與此類相等 //在子類中定義equals 方法時,首先調用超類的equals,若是檢測失敗,對象就不可能像等,若是超類中的域都相等,就須要比較子類中的實例域 Manager other = (Manager) otherObject; // super.equals checked that this and other belong to the same class return bonus == other.bonus; } public int hashCode() { return java.util.Objects.hash(super.hashCode(), bonus); } public String toString() { return super.toString() + "[bonus=" + bonus + "]"; } }
運行結果以下:
實驗2:編程練習(20分)
定義抽象類Shape:
屬性:不可變常量double PI,值爲3.14;
方法:public double getPerimeter();public double getArea())。
讓Rectangle與Circle繼承自Shape類。
編寫double sumAllArea方法輸出形狀數組中的面積和和double sumAllPerimeter方法輸出形狀數組中的周長和。
main方法中
1)輸入整型值n,而後創建n個不一樣的形狀。若是輸入rect,則再輸入長和寬。若是輸入cir,則再輸入半徑。
2) 而後輸出全部的形狀的周長之和,面積之和。並將全部的形狀信息以樣例的格式輸出。
3) 最後輸出每一個形狀的類型與父類型,使用相似shape.getClass()(得到類型),shape.getClass().getSuperclass()(得到父類型);
思考sumAllArea和sumAllPerimeter方法放在哪一個類中更合適?
輸入樣例:
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
import java.util.Scanner; public class calculate { public static void main(String[] args) { int r; int x; int y; int i; int a=100; Scanner num; num = new Scanner(System.in); //System.out.println("Input the num"); i = num.nextInt(); for(i=0;i<a;i++) { Scanner kind; kind = new Scanner(System.in); // System.out.println("Input the shape"); String rect="rect"; String cir="cir"; String input=kind.next(); if(input.equals(rect)) { Scanner sc; sc = new Scanner(System.in); //System.out.println("Input the Rectangle length:"); x = sc.nextInt(); //System.out.println("Input the Rectangle width:"); y = sc.nextInt(); System.out.println("Rectangle:"+"\n\n" +"\t"+"Perimeter:"+rectangle.getPerimeter(x,y)+"\n\n"+"\t"+"Area:"+rectangle.getArea(x,y)+"\n"); } if(input.equals(cir)) { Scanner sc; sc = new Scanner(System.in); //System.out.println("Input the Circle radius:"); r = sc.nextInt(); System.out.println("Circlr:"+"\n\n"+"\t"+"Perimeter:"+circle.getPerimeter(r)+"\n\n"+"\t"+"Area"+circle.getArea(r)+"\n"); } } } } class rectangle extends Shape {//子類繼承父類 public static double getArea(double width, double height) { return width*height; } public static double getPerimeter(double width, double height) { return 2*(width+height); } } class circle extends Shape {//子類繼承父類 public static double getArea(int radius) { return radius*radius*pi; } public static double getPerimeter(int radius) { int pi = 0; return 2*pi*radius; } } class Shape {//父類 private static String rect; private static String cir; public double width;//成員變量 public double length; public double area; public double Perimeter; final static double pi=3.1415926; final static String n=rect; final static String m=cir; public double getArea() { return area; //成員方法15 } public double getPerimeter() { return Perimeter; } }
運行結果以下:
3. 實驗總結:(10分)
經過本週實驗課以及老師課堂上編程習題的訓練,對基本知識有了較好的掌握。經過選擇填空對程序的運行結果或者程序的內容進行完善,不斷提高本身對繼承的方法的使用。可是在實驗課上,並無達到老師的要求, 完成背錄代碼的任務。在課下,完成做業的過程當中,經過看書上對程序的分析,更進一步的掌握了對繼承方法的定義與使用。