201521123091 《Java程序设计》第4周学习总结
Java 第二周總結
第四周的作業。
目錄
1.本章學習總結
2.Java Q&A
3.使用碼云管理Java代碼
4.PTA實驗
1.本章學習總結
1.1 嘗試使用思維導圖總結有關繼承的知識點。
1.2 使用常規方法總結其他上課內容。
多態在這邊介紹一下:
- 多態就是相同的形態,不同的行為。這樣去理解,在面向對象的編程語言中,多態就是不同類型的對象通過相同的接口去實現不同的方法。那么我們可以通過類繼承機制或者是接口來實現動態綁定,進而實現多態。
- instanceof 測試一個對象是否是某個類的實例,即使左邊是右邊類的子類的實例對象,也會返回true。
- 我們可以通過使用類型指派來完成子類所特有的某些方法。但是不能隨便進行類型指派,否則會出現ClassCastException異常。要謹慎使用類型指派,所以經常會通過instanceof來檢查。
2.Java Q&A
1.注釋的應用:使用類的注釋與方法的注釋為前面編寫的類與方法進行注釋,并在Eclipse中查看。(截圖)
首先上我們的注釋過后的類的文檔:
package ex3;/*** 照著String的文檔,寫一點點,英語不好,權且用中文吧。這個類呢,大概是用來描述公司里面的一個雇員。* 下面就不一一介紹這些成員變量了,因為意思很清晰,我沒有隨便命名變量。* 為了穩妥起見,我指定程序代碼最早使用的版本為JDK5.0。主要沒有好好研究下,是不是里面用了一些新版本的新特性。* <p>下面只是簡單地試一些標簽* <p>“@see”這個標簽可以允許我們引用其他類的文檔,生成HTML文件會生成超鏈接* <p>“@author”這個標簽就是指明作者,LJL36就是我了* <p>“@return”用來描述返回值的含義* <p>“@param”用來描述參數列表中的標識符* @see java.lang.Object#toString()* @see java.lang.String* @author LJL36* @since JDK5.0*/class Person {private String name;private boolean gender;private int age;private int id;/*** 這是一個無參構造器,會輸出一個語句,然后將未初始化的默認成員變量值打印出來*/public Person() {// TODO Auto-generated constructor stubSystem.out.println("This is constructor");System.out.println(name + "," + age + "," + gender + "," + id);}/*** 這是一個最常見的有參的構造器,就是把傳進來的參數來初始化對象,* 不過這邊沒有初始化id這個變量,所以會默認是0* @param name* 名字* * @param age* 年齡* * @param gender* 性別*/public Person(String name, int age, boolean gender) {this.name = name;this.gender = gender;this.age = age;}/*** 這邊重寫了一個toString方法,是用eclipse自動生成的* @return Person類的字符串表示*/@Overridepublic String toString() {// TODO Auto-generated method stubreturn "Person [name=" + name + ", age=" + age + ", gender=" + gender + ", id=" + id + "]";}public String getName() {return name;}public void setName(String name) {this.name = name;}public boolean isGender() {return gender;}public void setGender(boolean gender) {this.gender = gender;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public int getId() {return id;}public void setId(int id) {this.id = id;} } 類的注釋是用中文寫的,因為英語不大好,用中文會流暢很多。類文檔一上來應該簡要的概括一下這個類。我測試的這個類非常的簡單orz。所以也沒什么太多的話說。所以我嘗試加入一些參數的使用,具體的意思上面也都說了。最常用的幾個就像@see,@author,@since這些了。
有參構造器的注釋:
無參構造器的注釋:
toString方法的注釋:
(當然一般在輸出一個類的時候,如果已經寫好了toString方法的話,就不需要顯示加上,這邊只是為了看看toString方法的注釋而已)
2.面向對象設計(大作業1,非常重要)
2.1 將在網上商城購物或者在班級博客進行學習這一過程,描述成一個故事。(不得少于50字)
實變函數學十遍、學習泛函心犯寒
最近要學習一下復變分析,據說Elias M. Stein寫的Complex Analysis寫的不錯。于是先輸入賬戶,密碼和驗證碼登錄了某購物網站:
顯示登陸成功!
然后在搜索框中輸入我要買的這本書“Complex Analysis”:
下面出現了很多搜索結果,第一本就是我要的
進入看詳細信息,除了外面就可以看到的書名,價格,里面還可以看到:
點擊加入購物車
我可以不止買一本,可以兩本、三本,十幾本……
那去結算咯!再看一下價格,900+??,把我賣了都買不起啊,妥妥刪了,隨便去down個PDF下來吧。
(上面都是我瞎扯的,沒有時間學)
2.2 通過這個故事我們能發現誰在用這個系統,系統中包含的類及其屬性方法,類與類之間的關系。嘗試找到這些類與屬性,并使用思維導圖描述類、屬性、方法及類與類之間的關系。
2.3 嘗試使用Java代碼實現故事中描述的這一過程(不必很完善),將來要在這個基礎上逐漸完善、擴展成一個完整的面向對象的系統。(可選:加分)
兩題合在一起做了
1.首先需要有一個啟動類:啟動購物系統,主要就是main方法在這個里面,主要就是要調用其他的類。
2.然后需要一個商品類Goods:最主要的屬性就是商品名和價格
package shopping;public class Goods {private String name;private double price; }PS:然后下面會繼承其他的許多類,我這邊寫了些,比如圖書,服裝。主要是一個網上商城肯定有分類,而且這樣易于搜索。然后還會有一個AllGoods類,按理來說數據操作都是在后臺數據庫完成的?這邊就暫且加一個吧。
3.搜索類:這樣想的,凡是根據滿足關鍵字條件的商品都加入列表中,并且顯示出來,所以暫時先只要:
4.菜單類,主要是和用戶的交互,比如查看訂單,查看個人消息,查看購物車,搜索之類的雜七雜八的:
package shopping;public class Menu {public void startSearch() {Search search = new Search();}public void showMyself(User user) {}public void showShoppingCart(ShoppingCart shoppingCart) {} }5.用戶類,里面放了一些用戶需要的屬性,方法沒怎么加。同樣加了個AllUsers存放所有用戶的信息。
package shopping;public class User {String userName;String password;String address;}6.購物車類,非常核心的一個類,不過同樣地我也沒怎么寫東西,這邊用到了組合,因為商品可以有數量。
package shopping;import java.util.ArrayList; import java.util.concurrent.BlockingDeque;public class ShoppingCart {class Item {private Goods goods;private int num;}private ArrayList<Item> items = new ArrayList<Item>();private double totalPrice;public void add() {}public void delete() {}public void purchase() {}public void clear() {} }7.登錄類:主要就是把登錄這個功能單獨細分出來,然后因為有涉及到驗證碼,所以這邊有加了個驗證碼的類,不知道真正的實現,隨便寫了個。
//Code.java package shopping;import java.io.File;public class Code {File picture;String codeString; }//Login.java package shopping;public class Login {void showCode() {}boolean verify(String userName, String passWord, String code) {return true;}Code code; } 差不多就這樣了,然后貼一下UML類圖,大致現在的關系就是這樣,因為很多屬性沒有考慮到,而且方法還沒有具體實現,所以比較EZ:
3.分析ManagerTest.zip中的代碼,回答幾個問題:
3.1 在本例中哪里體現了使用繼承實現代碼復用?回答時要具體到哪個方法、哪個屬性。
首先,這邊貼一下維基對于代碼復用的定義:
Code reuse, also called software reuse, is the use of existing software, or software knowledge, to build new software,following the reusability principles.
簡言之,就是對曾經使用過的代碼一部分甚至全部重新加以利用。那我們就記住這句話,然后來看看在ManagerTest.java中到底哪些地方體現了代碼的復用。
- 構造器
這邊出現了super關鍵字,這是面向過程語言中一個重要的關鍵字,在構造器當中,我們上回提到了this這個關鍵字表示的是當前對象的引用。而相似地,我們也經常會通過super這個關鍵字去調用父類的構造器或者是父類的方法。這邊我們就是在調用父類的構造器來完成子類對象的初始化。
關于構造器這邊還有要說的點
Note: If a constructor does not explicitly invoke a superclass constructor, the Java compiler automatically inserts a call to the no-argument constructor of the superclass. If the super class does not have a no-argument constructor, you will get a compile-time error. Object does have such a constructor, so if Object is the only superclass, there is no problem.
如果子類的構造器沒有顯式調用父類的構造器,那么Java的編譯器就會自己加一個父類的無參構造器,如果父類沒有無參構造器,那么就會編譯出錯,這是什么情況呢,就是在父類寫了個有參的構造器,然后子類的構造器沒有顯式調用這個有參的構造器,那么編譯就會出錯。就加入我們現在把這第一行刪掉,就會發出“Implicit super constructor Employee() is undefined. Must explicitly invoke another constructor”的編譯錯誤。
- 成員變量
這邊就是name(String)、salary(double)和hireDay(Date)
代碼當中并沒有很明顯體現出哪里是復用了父類的成員,其實在上面我們在介紹構造器的時候,大家就可以發現,我們在Manager類中并沒有定義任何成員變量,但是都沒有出現編譯出錯的信息,究其原因就是子類復用了定義父類成員變量的代碼,所以就不用再重復了。
- 成員方法
這邊是調用父類的方法。從這段代碼我們更可以看出添加super關鍵字的重要性,如果將super去掉,那么就會產生我們并不希望看到的遞歸。主要這個函數還沒有基準條件(Base Case)那么就會一直向下遞歸,直到簿記空間全部被塞滿為止,然后電腦就跑崩了。
說完繼承之后,Java表示權限的四大關鍵字就已經全部出現了,下面分列它們各自的訪問權限范圍。
(PS:發現了博客園的第?個不支持:表格,這邊把我用md語法實現的表格截下來)
3.2 Employee類及其子類Manager都有getSalary方法,那怎么區分這兩個方法呢?
區分兩個同名方法?
那大概想讓編譯器能夠區分吧。
首先,我們在上回提到,如何在一個類當中去區分同名方法,我們的解決辦法是使用不同的參數列表,這個不同的范圍非常大,即使我們使用了相同的參數,只要順序不同,編譯器都可以區分出來。
那么,怎么去區分父類和子類的兩個方法。其實上面我們也說過了,就是我們使用super關鍵字來表示父類,那么假如這個例子super.getSalary()就表示父類的getSalary()方法。因為我們會有遞歸啊,所以在方法內部出現了同名的方法,完全可以認為是遞歸,所以必須得用super來區分。
3.3 文件第26行e.getSalary(),到底是調用Manager類的getSalary方法還是Employee類的getSalary方法。
貼圖解決
e都已經說明是Employee類的了,肯定調用Employee類的方法啊,而且調用子類的方法,聽上去不是有點怪怪的嗎,雖然查了下似乎是可以的,以一種曲線救國的方法,不過應該沒什么必要,這邊貼個鏈接,學到后面了回頭再看。傳說中的父類調用子類方法
不好意思,上面是錯誤的示范。留在這邊,當個反例。趕得太急了,也沒有檢查。這里面也是多態的體現。就是我們下面會說到的動態綁定,編譯器無法得知到底是什么類的對象在調用這個方法,只有在運行的時候,才能夠根據e的類型來確定。這邊只是通過父類給所有的繼承它的子類都提供同名方法的統一接口而已。(感謝老師指出錯誤)
3.4 Manager類的構造函數使用super調用父類的構造函數實現了代碼復用,你覺得這樣的有什么好處?為什么不把父類構造函數中的相關代碼復制粘貼到Manager的構造函數中,這樣看起來不是更直觀嗎?
好處就是少寫了一些代碼。
是很直觀,但是犯了Don't repeat yourself.的錯誤。
使用父類的構造器super()來幫助子類進行初始化,已經是一種約定俗成的方法,所以在代碼的可讀性方面并不輸直接復制粘貼代碼,而且還縮減了代碼量,所以肯定是直接用super調用父類的構造器更好。(而且這樣顯得比較高大上,復制粘貼代碼看上去很蠢。)
這邊又要提到上文我們說的代碼復用的問題
再引用一下wiki
Code reuse aims to save time and resources and reduce redundancy by taking advantage of assets that have already been created in some form within the software product development process.
......
These are some of the main goals behind the invention of object-oriented programming,which became one of the most common forms of formalized reuse.Code reuse
代碼復用就是為了要節省時間和資源,還要減少冗余。造成冗余的易讀性是沒有必要的。而且wiki還說了OOP就是為了更規范地復用代碼而生的,然后如果還傻乎乎的復制粘貼,無話可說。
4.Object類
4.1 編寫一個Fruit類及屬性String name,如沒有extends自任何類。使用System.out.println(new Fruit());是調用Fruit的什么方法呢?該方法的代碼是從哪來的?嘗試分析這些代碼實現了什么功能?
class Fruit {private String name; }public class Main {public static void main(String[] args) {System.out.println(new Fruit());} }運行結果:Fruit@15db9742
在之前的博文中,包括在上面我也有提到,當我們直接輸出某個對象的時候,就會調用toString()方法。
看一下println()的實現
思想就是要將對象用字符串的形式表示出來,然后輸出(使用print()方法),并且加個回車符(newLine()方法)。
valueOf()方法是用來return the string representation of the {@code Object} argument.它的實現就是
正如我們所說的,歸根結底還是調用了toString()方法。在本例中,我們并沒有重寫toString()方法,從運行結果我們可以看出本例中就是使用Object的toString()方法,即類名加上16進制的哈希碼。這邊就引出了一個很重要的點:
當創建一個類時,總是在繼承,因此,除非已明確指出要從其他類中繼承,否則就是隱式地從Java的標準根類Object進行繼承。
——《Java編程思想》
Object的源代碼文檔中也如是提到
Class {@code Object} is the root of the class hierarchy.Every class has {@code Object} as a superclass. All objects, including arrays, implement the methods of this class.
4.2 如果為Fruit類添加了toString()方法,那么使用System.out.println(new Fruit());調用了新增的toString方法。那么其父類中的toString方法的代碼就沒有了嗎?如果同時想要復用其父類的toString方法,要怎么操作?(使用代碼演示)
原來父類的toString()方法并不會沒有啊。一個爸爸可以有好幾個兒子,就因為這個兒子重寫了某個方法,導致其他兒子都得自己重寫?顯然是不可能的。只是對于父類中的方法,我既可以去使用它(不做改變)也可以按照自己的需求去修改它。Object類的toString()方法就是最好的例子,因為類名+哈希碼的字符串表示在日常生活中應用不到,所以推薦每個類都要重寫一個toString()方法。
想在重寫父類方法的同時復用父類的方法,只要用super關鍵字就好了,這邊貼一個代碼演示:
4.3 Fruit類還繼承了Object類的eqauls方法。嘗試分析其功能?自己編寫一個equals方法覆蓋父類的相應方法,功能為當兩個Fruit對象name相同時(忽略大小寫),那么返回true。(使用代碼證明你自己覆蓋的eqauls方法是正確的)
equals()方法是用來“Indicates whether some other object is "equal to" this one.”
equals()方法在Object類中的實現:
如源碼所示,Object類中的equals()方法是比較引用的,即引用相同就返回true,不同返回false。
據說許多人都會把equals()方法寫錯,害怕,那我們盡量寫的規范一點吧,首先這個 方法有5個要求:
1. 自反性(reflexive):對于任何非空引用值 x,x.equals(x) 都應返回 true。
2. 對稱性(symmetric):對于任何非空引用值 x 和 y,當且僅當 y.equals(x) 返回 true 時,x.equals(y) 才應返回 true。
3. 傳遞性(transitive):對于任何非空引用值 x、y 和 z,如果 x.equals(y) 返回 true,并且 y.equals(z) 返回 true,那么 x.equals(z) 應返回 true。
4. 一致性(consistent):對于任何非空引用值 x 和 y,多次調用 x.equals(y) 始終返回 true 或始終返回 false,前提是對象上 equals 比較中所用的信息沒有被修改。
5. 對于任何非空的引用x,x.equals(null)應該返回false
附上參考鏈接!
而且,文檔中還有說到:
Note that it is generally necessary to override the {@code hashCode} method whenever this method is overridden, so as to maintain the general contract for the {@code hashCode} method, which states that equal objects must have equal hash codes.
就是要重寫hashcode()這個方法……
看上去很難,我本來想好好的思考一下怎么寫的,但是自己太懶,想用eclipse生成hashcode()和equals()方法,然后再自己實現,沒想到然后就??都做好了啊???那就不客氣了,貼代碼了,然后我來解釋下吧:
這個自動生成的代碼寫的太好了。只可意會,不可言傳。我也解釋不了什么……
hashcode()方法就是將一個Fruit對象hash成一個整數。這邊是結合了String的hashcode()的方法。
接下來重點介紹一下equals()方法:
如果引用相同,那說明比較的是同一個對象,那么就返回true。滿足自反性。
非空的對象和null比較,返回false。滿足第五條要求。
兩個對象的類要是相同的,類不同的話,相同無從談起。這邊用getClass()方法來代替instanceof,因為后者只是判斷左邊對象是否是右邊類的實例,那如果左邊是子類的對象,右邊是父類,其實也是可以通過的,因為存在繼承關系,so不好。在上面equals()方法附上的鏈接里面有詳細的說明。
還有要對name是否為空進行特判,上次在敲深克隆的代碼時,因為沒有注意到null,一直A不掉。結果試了一下,如果沒有特判null,是會拋出異常的,所以以后都要注意的。后面就是返回字符串之間equals()的返回值了,沒什么了。我唯一改了一下,就是要忽略大小寫。
4.4 在4.3的基礎上使用ArrayList fruitList存儲多個fruit,要求如果fruitList中已有的fruit就不再添加,沒有的就添加進去。請編寫相關測試代碼。并分析ArrayList的contatins方法是如何實現其功能的?
public class Main {public static void main(String[] args) {// TODO Auto-generated method stubArrayList<Fruit> fruits = new ArrayList<Fruit>();Fruit[] fruits2 = new Fruit[6];fruits2[0] = new Fruit("apple");fruits2[1] = new Fruit("Apple");fruits2[2] = new Fruit("apqle");fruits2[3] = new Fruit("蘋果");fruits2[4] = new Fruit("平果");fruits2[5] = new Fruit("apPle");for (int i = 0; i < fruits2.length; i++) {if (!fruits.contains(fruits2[i])) {fruits.add(fruits2[i]);}}for (Fruit fruit : fruits) {System.out.println(fruit.getName());}}}測試結果如圖所示:
要分析ArrayList是如何實現contains()方法,就看看源碼吧:
//contains()方法 public boolean contains(Object o) {return indexOf(o) >= 0; }//indexOf()方法 public int indexOf(Object o) {if (o == null) {for (int i = 0; i < size; i++)if (elementData[i]==null)return i;} else {for (int i = 0; i < size; i++)if (o.equals(elementData[i]))return i;}return -1; }歸根到底,還是要用到equals()方法,因為要查看是否有包含,就需要有對象的比較。正如各位所看到的,我們寫的equals()方法是不區分大小寫的,所以諸如Apple和apPle之類的都是不能加進這個ArrayList的。
5.代碼閱讀:PersonTest.java(abstract、多態)
5.1 畫出類的繼承關系
5.2 讀懂main函數,將自己推測的出代碼運行結果與真正運行結果進行比較。嘗試分析原因
真正的運行結果:
Manager [bonus=12000.3, toString()=Employee [salary=90000.1, toString()=Person [name=Clark, adress=GE, phonenumber=111, email=111@mail.com, age=10, gender=mail]]]
Student [status=1, toString()=Person [name=wang, adress=110, phonenumber=15959, email=15959@163.com, age=18, gender=male]]
Employee [salary=1000.0, toString()=Person [name=zhang, adress=136, phonenumber=1360, email=1360@mail.com, age=21, gender=female]]
Programmer [allowance=50000.0, toString()=Employee [salary=100000.0, toString()=Person [name=Gates, adress=usa, phonenumber=911, email=911@com, age=59, gender=male]]]
分析原因:首先Person類是一個抽象類,所以根本就不存在可以實例化對象。因此這邊只要分析Employee、Student、Manager和Programmer這四個類就行了。觀察這四個類的toString()方法,我們可以發現他們具有統一的格式,就是輸出自己特有的成員變量,然后調用父類的同名方法,對于Manager和Programmer這兩個類,因為他們的父類Employee類也是繼承Person類,所以他們會有兩層嵌套。
5.3 子類中里面使用了super構造函數,作用是什么?如果將子類中的super構造函數去掉,行不行?
作用是調用父類的構造器。
不可以,因為如果將super構造器去掉,那么編譯器會自動加入對父類無參構造器的調用,然而這個例子中沒有一個類是有無參構造器的,所以會編譯出錯。我們會被要求“Must explicitly invoke another constructor”。所以即使無參構造器不會起到任何作用,我們還是最好能加上它,這樣如果有其他類繼承當前類,就可以在代碼中隱式地調用這個什么都不做的構造器,然后顯式地完成全新的初始化(就假如所有的成員變量都不需要用到父類的構造器就能夠完成初始化)。
5.4 PersonTest.java中的代碼哪里體現了多態?你覺得多態有什么好處?多態和繼承有什么關系嗎?
首先要理解什么是多態,如果從廣義的角度去理解,多態是一個很寬泛的概念。大致分為三種:
1.特設多態(Ad hoc polymorphism),函數重載和運算符重載。
2.參數化多態,就是把類型作為參數的多態。例如C++的模板。
3.子類型化。
通過類繼承機制和虛函數機制生效于運行期。可以優雅地處理異質對象集合,只要其共同的基類定義了虛函數的接口。也被稱為子類型多態(Subtype polymorphism)或包含多態(inclusion polymorphism)。在面向對象程序設計中,這被直接稱為多態。多態(計算機科學)來自維基
所以我們這邊就來聊聊OOP中的多態,就是子類型化。實現多態的方法叫做后期綁定,也叫做動態綁定或運行時綁定。即編譯器一直不知道對象的類型,但是方法調用機制能找到正確的方法體,并加以調用。這樣我們就可以編寫只與父類打交道的代碼,并且這些代碼對所有的子類都可以正確運行。
我們來列舉這邊出現的多態:
- System.out.println(person);/* Person類是一個抽象類,不能產生對象,所以也不會直接能夠輸出。但是我們并不知道到底輸出的是屬于哪個類的對象,直到運行的時候,才能知道,比如第0個就是Employee類的對象,就調用Employee類的toString()方法,第一個就是Student類的對象,就調用Student類的toString()方法。 */
- 其他就沒發現了,因為多態要和發送消息聯系起來,也就是方法的調用,這邊用父類調用方法的只有上述一個例子。
多態的好處:
1.可替換性(substitutability)。多態對已存在代碼具有可替換性。例如,多態對圓Circle類工作,對其他任何圓形幾何體,如圓環,也同樣工作。
2.可擴充性(extensibility)。多態對代碼具有可擴充性。增加新的子類不影響已存在類的多態性、繼承性,以及其他特性的運行和操作。實際上新加子類更容易獲得多態功能。例如,在實現了圓錐、半圓錐以及半球體的多態基礎上,很容易增添球體類的多態性。
3.接口性(interface-ability)。多態是超類通過方法簽名,向子類提供了一個共同接口,由子類來完善或者覆蓋它而實現的。超類Shape規定了兩個實現多態的接口方法,computeArea()以及computeVolume()。子類,如Circle和Sphere為了實現多態,完善或者覆蓋這兩個接口方法。
4.靈活性(flexibility)。它在應用中體現了靈活多樣的操作,提高了使用效率。
5.簡化性(simplicity)。多態簡化對應用軟件的代碼編寫和修改過程,尤其在處理大量對象的運算和操作時,這個特點尤為突出和重要。
網上都有比較統一的答案了,這邊就不多說了
簡而言之,多態可以讓我們更優雅地寫出代碼。
多態和繼承的關系:
多態要用單一的接口去操作不同的對象。這邊的接口不是專指Java中的interface,而是泛指對象上可以操作的方法。那么一個是interface的接口實現(后面再說),還有一種就是從父類繼承的相同接口,然后使用該接口的不同形式,即不同版本的動態綁定方法。面向對象的三大特性:封裝、繼承和多態,可以說前面兩個是為最后一個多態來服務的,而且多態不能單獨來看,它只能作為類關系“全景”中的一部分,與其他特性協同工作。
3.使用碼云管理Java代碼
4.PTA實驗
- 4-1,有什么好說的嗎?按部就班就好了。就是注意通過super來調用父類方法就好了。
- 4-2,和書面作業的第五題其實是類似的,用父類開數組,然后每個元素用子類去實例化,最后輸出,則是用到了多態,因為是通過父類的接口去實現子類的方法。
- 4-3,首先要比較的是父類的屬性,如果父類屬性不等直接返回false好了,至于父類的equals()方法怎么寫,就不關我們事了。其次就是要比較子類特有的company和salary兩個變量。只要注意company可能為null,需要特判一下,其他按照提示做下來,就A掉了。
- 4-4,這一題比較難,被卡了一會兒。這邊需要介紹一下深克隆和淺克隆的區別。首先如果都是基本數據類型,不存在深克隆和淺克隆。那么如果是對象,那么將會復制引用,而不是對象的內容,這邊拿一張圖來做個分析:
圖片來源 csdn 詳解Java中的clone方法 -- 原型模式
在淺拷貝中,p1對p進行拷貝,但是p1的name域和p的name域都指向同一個字符串,這樣就會存在一個問題,如果我對p的字符串進行修改,那么p1的字符串也會發生改變。所以我們需要深拷貝,就是復制對象的內容,而非引用。
做這道題時有幾個問題,首先clone()方法的返回值需要是當前類,比如本例就是Car類。其次就是需要判斷對象是否為空,如果對象是空的話,就可以直接復制,這時候如果對null調用方法,就會拋出異常,所以我一開始一直都A不過去。
然后就是要注意需要用clone()方法的類需要Cloneable的接口。這個編譯器會自動加好的0.0 - 5-4,就是按部就班按照提示去做就好了,沒什么特別的地方,用到了抽象類和繼承的思想。在父類當中定義好抽象的方法之后,在子類當中注意定義就好了。如果沒有定義,將還是被視作是抽象類,也就是還是要加上abstract關鍵字。至于sumAllArea()和sumAllPerimeter()方法放在主類當中就好了,可以用。
- 5-5,這道題就更沒什么好說的了,將近一半的代碼都是自動生成的。每一次加入都要判定之前是否已經存在同一個對象,就要涉及到equals()方法的撰寫,稍微注意特判空就行了。
- 5-6,之前我們用了比較器Comparator,這道題我是用的是Comparable接口,只要自己撰寫compareTo()方法就好了,這道題代碼比較長,不過都是按部就班地做下來,主要考察的是ArrayList的使用,用Collections.sort()來完成Arraylist的排序,今天早上做題目的時候楞了一下,忘記了。
看的不過癮的請點下面
回到頂部
做Java作業砸的時間挺多的,基本上交Java作業之前都是熬夜到1點左右,有點吃不消。下周開始就是密集的比賽,時間比較緊迫,所以可能會做的比較粗糙,望諒解。不過話說回來,好好地花時間研究,看《Java編程思想》,真的收獲還是不小的。之前看一點就放棄了,覺得太艱深了,果然還是要結合自己在pta上做題的經驗,然后再回過頭看書,才有用。還有中英文維基百科結合起來一起用,也會學到很多。
轉載于:https://www.cnblogs.com/ljl36/p/6561006.html
總結
以上是生活随笔為你收集整理的201521123091 《Java程序设计》第4周学习总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ps命令显示uid而不是用户名的解决方法
- 下一篇: 论文--R-FCN