日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

第10天 面向对象

發布時間:2025/4/14 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 第10天 面向对象 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

第10天 面向對象

今日任務

1、接口的思想(接口的第二個作用)(掌握)

2、抽象類和接口的區別(了解)

3、多態技術(掌握)

4、Object類概述(掌握)

課堂筆記

1、接口的思想(接口的第二個作用)

?

接口的第一個作用:給事物體系增加額外功能(擴展功能)。

接口的第二個作用:給事物雙方定義規則。一方使用規則,另一方實現規則。

?

?

說明:筆記本就是在使用這個規則,外圍設備(鼠標、鍵盤等)在實現這個規則。

?

2、抽象類和接口的區別

?

接口和抽象類都是描述事物的共性行為,并且描述的行為一般都是抽象的。需要子類或實現類對這些行為進行實現或復寫。

接口和抽象類的區別:

1、接口中只能定義抽象方法;抽象類中除了具有抽象方法外,還可以定義其它方法;

2、接口可以多實現;而抽象類只能單一繼承;

3、接口用來描述事物擴展功能(額外功能);抽象類用來描述事物的共性內容(描述不清楚);

4、接口中沒有構造函數;抽象類中具有構造函數;

?

抽象類和接口的區別代碼體現如下:

//定義接口

interface Inter

{

????void show();

????//接口中只能有抽象方法

????/*void test()

????{

????????System.out.println("test");

????????

????}*/

}

interface InterA

{

????void show();

}

//定義一個類來實現接口

class InterfaceImpl implements Inter,InterA//接口可以多實現

{

????public void show()

????{

????????System.out.println("接口show");

????}

}

//定義一個抽象類

abstract class Abs

{

????//抽象類中除了定義抽象方法還可以定義其他方法

????void demo()

????{

????????System.out.println("demo");

????}

????//抽象類中可以有構造函數,接口中沒有

????Abs()

????{

????????System.out.println("抽象類中的構造函數");

????}

}

class AbstractDemo extends Abs

{

}

class AbstractAndInter

{

????public static void main(String[] args)

????{

????????InterfaceImpl ip=new InterfaceImpl();

????????ip.show();

????????AbstractDemo abs=new AbstractDemo();

????}

}

?

3、多態技術:

3.1、多態介紹

面向對象語言三大特征:封裝、繼承和多態。

多態:表示的是一個事物的多種表現形態。同一個事物,以不同的形態表現出來。

?

多態來源于生活,在生活中我們經常會對某一類事物使用它的共性統稱來表示某個具體的事物,這時這個具體的事物就以其他的形式展示出來。

蘋果:說蘋果,說水果。

狗:說狗,說動物。

貓:說貓,說動物。

?

?

3.2、多態技術在Java中的體現

在Java中的多態代碼體現:

使用父類的引用,表示自己的子類對象。

Cat c = new Cat(); 使用貓類型表示自己,這里不會發生多態現象

Animal a = new Cat(); 使用動物的類型再表示貓,這時就發生的多態的現象。

?

在Java中要使用多態技術:

前提:必須要有繼承/實現;

好處:可以通過父類統一管理子類;

多態技術在java中的代碼體現:

  • 定義一個動物類Animal,在這個類中定義一個eat函數,由于每種動物吃的東西不一樣,所以eat函數體不確定,這里我們可以將eat函數變成抽象函數,Animal類也會變成抽象類;
  • 在分別定義Dog和Cat兩個類,在這兩個類中都復寫Animal類中的eat函數,并在兩個不同類中的eat函數體中輸出不同動物吃不同東西的語句;
  • 定義一個測試多態的類,在這個類中分別創建貓和狗的對象分別調用對應的函數,如果Animal父類中有多個函數,那么我們使用貓和狗的對象調用多個函數時會出現代碼的復用性差的問題,所以我們定義一個函數將重復的代碼寫到函數中,這樣就可以提高了代碼的復用性差的問題;
  • 在主函數中調用自定義函數,并將貓和狗的對象作為參數傳遞給自定義函數,而自定義函數接收的參數類型是父類的Animal類型,這里就使用了多態的現象;

    ?

    //演示多態技術

    abstract class Animal

    {

    ????abstract void eat();

    ????void show()

    ????{

    ????????System.out.println("show run .....");

    ????}

    ????void show2()

    ????{

    ????????System.out.println("show2 run .....");

    ????}

    }

    class Cat extends Animal

    {

    ????void eat()

    ????{

    ????????System.out.println("貓吃魚");

    ????}

    }

    class Dog extends Animal

    {

    ????void eat()

    ????{

    ????????System.out.println("狗啃骨頭");

    ????}

    }

    ?

    class DuoTaiDemo

    {

    ????public static void main(String[] args)

    ????{

    ????????Cat c = new Cat();

    ????????demo(c);

    ????????Dog d = new Dog();

    ????????demo(d);

    ????}

    ????/*

    ????????在調用方法的時候發生了多態的現象

    ????????Animal a = new Cat(); 這里發生了多態

    ????????Animal a = new Dog(); 這里也是多態

    Dog a=new Animal();子類引用是不可以指向父類對象的

    ????????我們在使用多態的時候,永遠只能使用父類的類型接受子類的對象,而不能使用

    ????????子類的類型接受父類的對象。

    ????*/

    ????public static void demo( Animal a )

    ????{

    ????????a.eat();

    ????????a.show();

    ????????a.show2();

    ????}

    }

    ?

    注意:我們在使用多態的時候,永遠只能使用父類的類型接受子類的對象,而不能使用子類的類型接受父類的對象。

    ?

    3.3多態的弊端

    ?

    //演示多態弊端

    ?

    abstract class Animal

    {

    ????abstract void eat();

    }

    class Cat extends Animal

    {

    ????void eat()

    ????{

    ????????System.out.println("貓吃魚");

    ????}

    ????//貓有自己的特有行為 抓老鼠

    ????void catchMouse()

    ????{

    ????????System.out.println("貓抓老鼠");

    ????}

    }

    class Dog extends Animal

    {

    ????void eat()

    ????{

    ????????System.out.println("狗啃骨頭");

    ????}

    ????//狗也有自己的行為 看家

    ????void lookHome()

    ????{

    ????????System.out.println("狗看家");

    ????}

    }

    class DuoTaiDemo2

    {

    ????public static void main(String[] args)

    ????{

    ????????Cat c = new Cat();

    ????????c.eat();

    ????????c.catchMouse();

    ?

    ?

    ????????Dog d = new Dog();

    ????????d.eat();

    ????????d.lookHome();

    ?

    ????????//使用多態調用方法

    ????????Animal a = new Dog();

    ????????a.eat();

    ????????a.lookHome();

    ????}

    }

    ?

    ?

    多態的弊端:

    把一個子類類型提升成了父類的類型,那么在程序編譯的過程中,編譯不會考慮具體是哪個子類類型,而只會根據當前的父類類型去操作,通過父類的引用在調用方法的時候,只會去父類類型所屬的類中找有沒有這些成員,

    如果有編譯通過,如果沒有編譯失敗。

    ?

    多態弊端總結:

    在使用多態技術的時候,程序在編譯的時候,使用多態調用成員(變量和函數),要求被調用的成員在父類中一定要存在,如果父類中沒有編譯就會失敗。(不能使用子類特有功能或者屬性)

    ?

    注意:只要有多態的地方,一定發生類型的提升(肯定是把子類對象使用父類類型在表示)。

    ?

    3.4、多態中的轉型

    在使用多態時,存在一個弊端:不能使用子類中特有的功能(函數)。

    如果在多態中,必須要使用子類特有的功能,需要在多態操作時進行類型的轉換。

    復習下之前學習過的類型轉換:

    自動類型提升 例: byte b=10; int num=b;

    強制類型轉換 例: double d=3.14; int n=(int)d;

    ?

    Animal an = new Dog();

    Animal是父類類型(父引用類型) an是父引用 new Dog()是子類對象

    在以上代碼中,已存在了類型的轉換(向上轉型):父類 父引用=new子類();

    ?

    如果一定要在父類引用中使用子類對象特有的功能,就需要向下轉型(大類型向下轉換):

    說明:子類對象中特定的功能只能子類對象自己調用。

    ?

    如果已經發生多態現象,但是我們還想調用子類的特有屬性或者行為,這時需要使用強制類型轉換,把當前父類類型轉成具體的子類類型。

    ?

    多態中的類型轉換有兩種:

    1)向上轉型(隱式的類型提升) 父引用指向子類對象 例:Animal an = new Dog();

    2)向下轉型(強制類型轉換或者把父類類型轉成子類類型) 把父引用強制轉為子類引用 例:Dog d=(Dog) an;

    強制類型轉換格式:子類類型 子類引用名=(子類類型)父類引用名;

    ?

    ?

    多態類型轉換的代碼體現:

    abstract class Animal

    {

    ????abstract void eat();

    }

    class Cat extends Animal

    {

    ????void eat()

    ????{

    ????????System.out.println("貓吃魚");

    ????}

    ????//貓有自己的特有行為 抓老鼠

    ????void catchMouse()

    ????{

    ????????System.out.println("貓抓老鼠");

    ????}

    }

    ?

    class Dog extends Animal

    {

    ????void eat()

    ????{

    ????????System.out.println("狗啃骨頭");

    ????}

    ????//狗也有自己的行為 看家

    ????void lookHome()

    ????{

    ????????System.out.println("狗看家");

    ????}

    }

    class DuoTaiDemo3

    {

    ????public static void main(String[] args)

    ????{

    ????????Cat c = new Cat();

    ????????c.eat();

    ????????c.catchMouse();

    ?

    ????????Dog d = new Dog();

    ????????d.eat();

    ????????d.lookHome();

    ?

    ????????//使用多態調用方法

    ????????Animal a = new Dog();

    ????????a.eat();

    ????????/*

    ????????????如果已經發生多態現象,但是我們還想調用子類的特有屬性或者行為,這時需要使用

    ????????????強制類型轉換,把當前父類類型轉成具體的子類類型。

    ?

    ????????????在多態中的類型轉換問題:

    ????????????????1、隱式的類型提升。只要有多態就會發生類型提升(向上轉型)。

    ????????????????2、把父類類型轉成子類類型(強制類型轉換,向下轉型)。

    ?

    ????????????什么時候使用向下轉型:

    ????????????只要在程序中我們需要使用子類的特有屬性或行為(方法、函數)的時候,才會使用向下轉型。

    ????????*/

    ?

    ????????//(Dog)(a).lookHome();

    ????????Dog dd = (Dog)a; //多態的轉型

    ????????dd.lookHome();

    ?

    注意:

    1)什么時候使用向下轉型:

    ????只要在程序中我們需要使用子類的特有屬性或行為(方法、函數)的時候,才會使用向下轉型。

  • 無論是向上還是向下轉型,最終都是子類對象做著類型的變化。和父類對象沒有關系。
  • 為什么要使用轉型

    ?

    3.5多態類型轉換時常見異常

    在多態類型轉換時經常會發生一個異常錯誤:ClassCastException(類型轉換異常)。

    ?

    多態類型轉換常見異常代碼演示:

    abstract class Animal

    {

    ????abstract void eat();

    }

    class Cat extends Animal

    {

    ????void eat()

    ????{

    ????????System.out.println("貓吃魚");

    ????}

    ????//貓有自己的特有行為 抓老鼠

    ????void catchMouse()

    ????{

    ????????System.out.println("貓抓老鼠");

    ????}

    }

    ?

    class Dog extends Animal

    {

    ????void eat()

    ????{

    ????????System.out.println("狗啃骨頭");

    ????}

    ????//狗也有自己的行為 看家

    ????void lookHome()

    ????{

    ????????System.out.println("狗看家");

    ????}

    }

    class DuoTaiDemo3

    {

    ????public static void main(String[] args)

    ????{

    ????????Animal a= new Cat();

    ????????demo(a);//傳遞的是貓的對象

    ????}

    ????public static void demo( Animal a )

    ????{

    ????????a.eat();

    //把Animal類型的a轉成 Dog類的d

    Dog d=(Dog)a;//將傳遞過來的貓的對象強制轉換為狗是不可以的,會發生轉換異常

    ????????/*

    ????????????向下轉型有風險,使用需謹慎。

    ????????????在Java中要使用向下轉型,必須先做類型的判斷,然后在轉型

    ????????????Java中的類型判斷 需要使用關鍵字 instanceof

    ????????????格式:

    ????????????????被轉的引用變量名 instanceof 被轉成的類型

    ????????????????如果引用變量所在的那個對象 和被轉成的類型一致,這個表達式返回的是true,否則是false

    ?

    ????????????在多態中使用轉型的時候,一定要判斷,防止類型轉換異常的發生:

    ????????????????如果在程序發生ClassCastException,一定是把不是這種類型的對象轉成了這種類型。

    ????????*/

    ????????if( a instanceof Dog )

    ????????{

    ????????????Dog d = (Dog)a;

    ????????????d.lookHome();

    ????????}

    ????????else if( a instanceof Cat )

    ????????{

    ????????????Cat c = (Cat)a;

    ????????????c.catchMouse();

    ????????}????

    ????}

    }

    ?

    ?

    向下轉型有風險,使用需謹慎。在Java中要使用向下轉型,必須先做類型的判斷,然后在轉型Java中的類型判斷 需要使用關鍵字 instanceof。

    ????????????格式:

    ????????????????被轉的引用變量名 instanceof 被轉成的類型

    如果引用變量所在的那個對象 和被轉成的類型一致,這個表達式返回的是true,否則是false。

    在多態中使用轉型的時候,一定要判斷,防止類型轉換異常的發生:

    如果在程序發生ClassCastException,一定是把不是這種類型的對象轉成了這種類型。

    ?

    總結:

    只要有多態,就會有類型的轉換。

    把子類對象賦值給父類的引用,這時發生了向上的轉型(隱式類型轉換)。

    如果我們需要使用子類的特有行為或屬性,這時必須向下轉型,需要把父類的引用轉成具體所指的那個對象的類型。

    在向下轉型的時候一定要做類型的判斷,防止ClassCastException異常的發生。

    ?

    判斷格式:

    if( 父類引用變量名 instanceOf 子類對象所屬的類名 )

    {

    進行轉換。

    }

    3.6、多態中調用成員的細節(掌握)

    學習多態中的成員使用規律:需要掌握的是以多態形式使用成員,需要考慮程序的編譯和運行2個階段。

    3.6.1多態調用成員變量

    在使用多態時,子父類中存在相同的成員變量:

    ?

    結論:

    在多態中,使用父類的引用(f)訪問成員變量,子父類中存在一模一樣的成員變量時:

    1)代碼在編譯的時期(javac 源文件):需要查看父類中有沒有這個成員變量,如果有,編譯通過,沒有編譯失敗。

    2)編譯通過的前提下,運行(java 類文件)時期:這時操作的依然是父類中的成員變量。

    記住:多態時,子父類中存在一模一樣的成員變量時,引用變量,編譯運行都看引用類(父類)中的變量。(編譯時以等號左邊作為參考,運行時也是以等號左邊作為參考)

    注意:如果發生多態時,只要是在其他類中使用成員變量,那么這個成員變量必須存在于父類中,無論子類中是否含有對應的成員變量,如果父類中沒有成員變量,那么編譯和運行都不會通過,和子類中是否含有成員變量沒有關系。

    ?

    3.6.2多態調用非靜態成員函數

    在多態中,使用父類引用調用成員函數的時候,一般函數都復寫存在。

    在使用多態時,子父類中存在一模一樣的成員方法時:

    ?

    結論:

    在多態中,使用父類的引用(f)調用函數的時候,子父類中存在一模一樣的成員方法時:

    1)代碼在編譯的時期(javac 源文件):要看父類中有沒有這個函數,有,編譯通過,沒有編譯失敗。

    2)編譯通過的前提下,運行(java 類文件)時期:運行的是子類中復寫父類之后的那個函數。如果沒有復寫,運行的肯定還是父類的函數。

    記住:多態時,子父類中存在一模一樣的成員方法時,編譯時以等號左邊作為參考,運行時是以等號右邊作為參考。

    3.6.3多態調用靜態成員函數

    在使用多態時,子父類中存在一模一樣的靜態方法時:

    ?

    靜態的成員是隨著類的加載而存在,和創建的對象沒有任何關系,只跟類有關系。在java中,使用對象去調用靜態成員,底層JVM還是會以對象所屬的類型(類)去調用靜態成員。因此使用多態調用靜態函數的時候,編譯運行都要看父類中的函數。

    ?

    結論:

    在使用多態時,子父類中存在一模一樣的靜態方法時:

    編譯時期是以等號左邊作為參考,運行時期也是以等號左邊作為參考。

    也就是說,在使用多態時,子父類中存在一模一樣的靜態方法時,與子類是否存在靜態函數沒有關系,只和父類中有關系。

    ?

    總結多態中成員使用規律:

    成員變量和靜態成員函數,編譯運行都看左邊(父類中的)。只有非靜態成員函數,編譯看父類,運行看子類對象。

    3.7、多態的練習

    練習的目的:需要掌握多態中,自始至終只有子類對象存在,沒有父類的對象,并且把子類對象交給父類的引用在使用。

    ?

    練習黑旋風和黑旋風老爸的故事。

    黑旋風:

    講課(){}

    看電影(){}

    黑旋風老爸:

    講課(){}

    釣魚(){}

    ?

    //多態練習

    class Dad

    {

    ????void teach()

    ????{

    ????????System.out.println("黑旋風老爸講論語");

    ????}

    ????void fish()

    ????{

    ????????System.out.println("黑旋風老爸釣魚");

    ????}

    }

    class Hxf extends Dad

    {

    ????void teach()

    ????{

    ????????System.out.println("黑旋風講Java");

    ????}

    ????void lookFilm()

    ????{

    ????????System.out.println("黑旋風在看速7");

    ????}

    }

    ?

    class DuoTaiTest

    {

    ????public static void main(String[] args)

    ????{

    ????????/*

    ????????Hxf hxf = new Hxf ();

    ????????hxf .teach();

    ????????hxf .fish();

    ????????*/

    ????????Dad dad = new Hxf (); //多態

    ????????dad .teach();

    ???? dad .fish();

    //dad.lookFilm();//編譯報錯,因為父類中沒有lookFilm這個函數

    ???? /*

    ????????????現在我就想調用子類中特有的函數,怎么辦?

    ????????????我們這里需要使用強制類型轉換,將父類轉換為子類

    ????????*/

    ????????Hxf hxf = (Hxf)dad; //黑旋風卸妝 向下轉型

    ????????hxf .lookFilm();

    ????}

    }

    ?

    ?

    4、Object類概述

    在學習面向對象編程思想,遇到需求時,先去找有沒有解決問題的功能存在。這些解決問題的功能通常是封裝在類中(功能類),使用這些功能類基本可以解決開發中大部分的問題(例:折半查找、選擇排序等)。

    問題:這些解決問題的功能類都在哪里?

    在java設計時,已經提供了很多解決問題的封裝類。這些解決問題的封裝類,我們統稱為:API

    在開發中,只要去相應的包(文件夾)中去找對應的封裝類就可以解決問題。

    API:application programming interface。應用程序接口。我們這里通常把api簡稱為幫助文檔。

    想要使用java提供的解決各種問題的API,就需要先學會如何查閱API文檔。

    4.1 查閱API文檔的技巧

    使用"索引"查找相應的信息

    如下圖操作,點擊選項,選擇顯示標簽

    ?

    點擊完顯示標簽后,會出現如下圖所示界面:

    ?

    然后點擊索引,會出現如下圖所示的界面:

    在查找框里輸入要查找的類或者接口即可。

    ?

    在搜索框里輸入要查找的類,選中并雙擊或者回車。

    ?

    4.2 如何查閱源代碼

    在開發中,除了查閱API以外,還經常會查看JDK的源代碼,幫助解決開發中的問題。

    在安裝JDK時,隨著JDK版本的安裝,在JDK安裝目錄也存在一個當前版本的JDK源碼文件

    ?

    查看源代碼的步驟:(前提:需要知道要查找的功能類屬于哪個包

  • 新建一個文件夾,并把src.zip文件解壓到創建的文件夾中

    ?

  • 找到要查閱源代碼的功能類或接口

    ?

  • 使用記事本之類的工具,打開要查看的源代碼文件

    ?

    4.3 Object類說明

    在所有類中的構造函數中有個隱式的super語句,找父類。如果一個類沒有顯示指定它的父類,那么這個類的父類默認就是Object類。Object類的構造函數中是沒有隱式的super的。

    通過API的查閱,可以得到:

    1、Object是java提供的功能類(API中的類)和開發人員自己書寫的類的父類;

    2、因為所有的類都繼承了Object類,所以繼承了Object類的子類可以使用Ojbect類中的功能(函數);

    疑問:既然自己定義的類也要繼承Object類,那為什么在代碼中沒有顯式書寫繼承Object?

    Object類屬于java.lang包下。而java.lang包會被JVM在運行時自動加載,繼承了Object的子類也不需要顯式書寫,JVM會自動為書寫的類添加繼承。

    Object類中的常用函數:

    equals 方法 toString 方法

    4.4、equals方法介紹

    需求:判斷學生是否為同齡人

  • 定義一個學生Student類,在Student類中定義name和age屬性,并定義構造函數給name和age初始化值;
  • 在Student類中定義一個比較是否是同齡的函數,如果相同就返回true,不相同就返回false;
  • 定義一個測試類,在這個類中分別創建兩個對象,然后使用一個對象調用類中的比較是否同齡的函數,根據函數返回的true或者false判斷是否同齡;

    ?

    /*

    ????判斷兩個學生是否是同齡人

    */

    //定義一個學生類

    class Student

    {

    ????//屬性

    ????String name;

    ????int age;

    ????//定義構造函數給屬性初始化值

    ????Student(String name,int age)

    ????{

    ????????this.name=name;

    ????????this.age=age;

    ????}

    ????/*

    ????????定義一個函數根據外界傳遞過來的值比較年齡是否相等,

    ????????使用return關鍵字將比較的結果返回給調用者

    ????????Student a=new Student("技導",18)

    ????????因為compareAge函數是s對象調用的,所以在這個函數中的隱式變量this

    ????????記錄著s對象的堆內存地址名

    ????*/

    ????public boolean compareAge(Student a)

    ????{

    ????????/*

    ????????????this.age表示黑旋風的年齡17

    ????????????a.age表示技導的年齡18

    ????????*/

    ????????return this.age==a.age;

    ????}

    }

    class ObjectDemo1

    {

    ????public static void main(String[] args)

    ????{

    ????????/*

    ????????????創建兩個對象

    ????????????下面的兩個對象表示在對空間中開辟兩個不同的空間

    ????????????一個空間叫做s,另一個空間叫做s1

    ????????*/

    ????????Student s=new Student("黑旋風",17);

    ????????Student s1=new Student("技導",17);

    ????????//使用黑旋風的對象s調用compareAge函數

    ????????//使用flag來接受返回回來的值

    ????????boolean flag=s.compareAge(s1);

    ????????/*

    ????????????如果返回回來的值是true,說明是同齡人

    ????????????如果返回回來的值是false,說明不是同齡人

    ????????*/

    ????????if(flag==true)

    ????????{

    ????????????System.out.println("是同齡人");

    ????????}else

    ????????{

    ????????????System.out.println("不是同齡人");

    ????????}

    ????}

    }

    ?

    使用以上方式可以解決問題。

    ?

    面向對象:遇到需求時,先去找有沒有存在已經解決問題的功能(功能是封裝在類中)。

    有,就直接使用封裝了功能的功能類解決問題。

    ?

    以上需求中,是需要解決判斷是否為同齡人的功能。(其實就是一個判斷是否相等的功能)

    首先,去找java API中是否有比較功能。

    問題:Student類中不具備比較功能,但是,Student類繼承了Object類,所以可以去Object類中找是否存在解決問題的功能

    ?

    Object類中的功能:

    ?

    使用Object類中的eqauls函數解決需求中的問題:

    ?

    以上程序運行結果不正確。

    分析:為什么使用Object類中的equals功能會存在結果不正確呢?

    查看Object類中的equals功能的源代碼

    上述代碼中的Object類中的this 表示的是調用這個equals函數的那個對象,obj是調用equals方法時傳遞進來的那個對象,而this中保存的是對象的內存地址,obj中接受的也是傳遞進來的那個對象內存地址。所以這里使用== ,其實是在比較2個對象的內存地址是否相等。(就是堆內存中的地址)

    ?

    結論:Object類中的equals方法中,比較的是堆中的地址是否相等

    ?

    而我們真正在開發中要比較2個對象是否相等,不應該去比較內存地址,而應該比較的是對象中的數據是否相同。單單使用Object類中的equals功能,并不能直接解決我們需求中的問題。遇到這種情況,在開發中的做法是:重寫Object類中的equals函數,因此所有的程序中都應該復寫Object類中的equals。

    ?

    ?

    /*

    ????判斷兩個學生是否是同齡人

    */

    //定義一個學生類

    class Student

    {

    ????//屬性

    ????String name;

    ????int age;

    ????//定義構造函數給屬性初始化值

    ????Student(String name,int age)

    ????{

    ????????this.name=name;

    ????????this.age=age;

    ????}

    ????//重寫Object類中的equals函數(重寫:和父類中的方法一模一樣)

    ????public boolean equals(Object obj) {

    ????????/*

    ????????????因為這里發生了多態,所以不能使用父類的對象obj調用父類中不存在的屬性age,

    ????????????所以會報錯。所以我們應該使用子類Student對象來調用子類中的屬性age

    ????????????而這里obj是父類對象,我們需要使用向下轉型將父類對象obj轉換為子類對象

    ????????????因為發生向下類型轉換,為了防止發生轉換異常,所以我們要判斷子類對象類型

    ????????*/

    ????????Student s=null;

    ????????if(obj instanceof Student)

    ????????{

    ????????????s=(Student)obj;

    ????????}

    return this.age==s.age;

    }

    }

    class ObjectDemo2

    {

    ????public static void main(String[] args)

    ????{

    ????????/*

    ????????????創建兩個對象

    ????????????下面的兩個對象表示在對空間中開辟兩個不同的空間

    ????????????一個空間叫做s,另一個空間叫做s1

    ????????*/

    ????????Student s=new Student("黑旋風",17);

    ????????Student s1=new Student("技導",17);

    ????????//使用黑旋風的對象s調用compareAge函數

    ????????//使用flag來接受返回回來的值

    ????????//boolean flag=s.compareAge(s1);

    ????????/*

    ????????????public boolean equals(Object obj) {

    ????????????????這里的this記錄著調用這個方法的對象s的堆中內存地址名

    ????????????????obj表示傳遞進來的參數對象s1,Object obj=new Student("技導",17);這里發生多態

    ????????????????obj里面存放的也是s1中的堆中內存地址

    ????????????????s和s1的堆中內存地址名不同

    ???????????????? return (this == obj);

    ????????????}

    ????????????public boolean compareAge(Student a)

    ????????????{

    ???????? ?

    ????????????????return this.age==a.age;

    ????????????}

    ????????*/

    ????????boolean flag=s.equals(s1);

    ????????System.out.println(flag);

    ???????? ?

    ????????/*

    ????????????如果返回回來的值是true,說明是同齡人

    ????????????如果返回回來的值是false,說明不是同齡人

    ????????*/

    ????????if(flag==true)

    ????????{

    ????????????System.out.println("是同齡人");

    ????????}else

    ????????{

    ????????????System.out.println("不是同齡人");

    ????????}

    ????}

    }

    ?

    ?

    ?

    總結:

    關系運算中的==和equals的區別:

  • equals函數是用來比較2個對象是否相等的。要比較對象是否相等,必須調用函數(equals)來比較。但是必須得復寫equals函數。
  • 而學習的關系運算中的 == 只能比較2個具體的數據是否相等。

    4.5、toString方法介紹

    需求:輸出Student類的具體信息,也就是根據輸出Student類的對象來輸出Student的具體名字和姓名。

  • 定義一個Student類,在這個類中定義兩個name和age屬性;
  • 在Student類中定義一個構造函數,給name和age兩個屬性賦值;
  • 定義一個測試類,在這個測試類中創建Student類的對象并初始化值;
  • 在屏幕上打印Student類的對象;

    以上程序的運行結果,不符合需求。要求是想要輸出學生類中的具體信息,比如通過打印對象的名字stu,我們希望打印出具體的stu對象所擁有的名字和年齡,而打印一串地址名在開發中沒有什么太大意義。

    ?

    問題:為什么輸出stu時,顯示的結果:Student@7ea06d25?為什么輸出的是一個引用地址而不是我們想要的對象的屬性的值呢?我們應該怎么做才能打印出屬性的值而不是打印一串地址的值呢?

    這里我們需要借助Object類中的toString方法來解決,toString是一個方法,它需要對象來調用,toString的意思是將調用它的對象轉換成字符串形式。

    我們在打印對象的時候也可以按照如下方法去做:

    System.out.println(stu.toString());打印的結果和我們寫System.out.println(stu);是一樣的。

    在上述打印語句中println()的方法中打印對象stu的時候,如果不加 .toString()方法,在println()的方法中默認也是使用對象stu調用toString()方法,所以在開發中寫與不寫toString()方法是一樣的。

    ?

    ?

    ?

    根據以上分析我們想要建立自定義對象的表現形式,我們需要覆蓋超類(所有類的父類)中的toString()方法就可以了。

    在Student類中可以重寫toString方法,讓程序輸出學生類的具體信息,代碼實現如下:

    ?

    小結:

    在開發中,如果子類繼承父類時,父類中已經存在了解決問題的功能,但是父類中的功能并不能滿足子類的需求,這時,子類就需要重寫(覆蓋)父類中的方法。

  • 轉載于:https://www.cnblogs.com/beyondcj/p/5860863.html

    總結

    以上是生活随笔為你收集整理的第10天 面向对象的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。