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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java面向对象(2) —— 继承

發布時間:2023/12/10 java 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java面向对象(2) —— 继承 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

  • 前言
  • 繼承的概念和實現
    • extends關鍵字
    • super關鍵字
    • 繼承過來的屬性和方法的權限研究
    • 方法重寫Override
  • Object根類常見方法
    • toString()
      • 常把toString()方法重寫后應用
    • equals()
      • 重寫:判斷兩個對象p1和p2特征是否相同
      • IDEA的重寫模板:敲equals可選擇的方案之一
      • String 類重寫:判斷字符串是否相等
  • 繼承練習:java面向對象下的簡單工廠模式

前言

下面C語言的代碼中定義了兩個在內容上高度重復的結構體

#include <stdio.h>struct Person //人 {int name;char* address;void (*pEat)(); void (*pDrink)(); };struct Student //學生也是人,所以有一定的重復性 { int name;char* address;void (*pEat)();void (*pDrink)();int score; //學生獨有的特征,有分數,要上學void (*goToSchool)(); };

然而對于C語言來說這兩個結構體沒有任何聯系,這樣造成了代碼的浪費,重復。

而java的繼承特性,就解決了這一問題。

繼承的概念和實現

生活中,繼承的概念隨處可見。

比如:

java繼承背后的思想是:基于已存在的類來構建新類。

當從已存在類繼承時,就重用了他的方法和屬性,還可以添加新的方法和屬性來定制新類以應對要求。

繼承的意義:代碼重用,體現不同抽象層次

約定:從其他類導出的類叫做子類,通常父類更通用更抽象,子類更特殊更具體。

在java中,除了object外,所有類都是子類,都只有唯一的父類,即為object類。

所以繼承在OOP(Object-Oriented Program面向對象編程 )中不可或缺,創建一個類時,總是在繼承

extends關鍵字

在java語言中,用extends關鍵字來表示一個類繼承了另一個類,如Student繼承了Person

public class Student extends Person{ ... }
  • 1
  • 2
  • 3

例子:

class Person {String name;String address;void eat() {System.out.println("人吃飯");}void drink() {System.out.println("人喝水");} }class Student extends Person{ //可以直接使用Person中的屬性了int score;void goToSchool() {System.out.println("學生要上學");} }public class Demo1 {public static void main(String[] args) {Person p = new Person();p.name = "人";p.eat();Student s = new Student();s.name = "學生"; //person中的特征s.eat(); //person中的方法} }

super關鍵字

super和this關鍵字的特點類似:super代表的是對父類對象的引用

作用:

(1)當子父類的成員出現同名時,可以通過super來區分
(2)子類的構造方法中,通過super關鍵字調用父類的構造方法

強調:

(1)當構造一個子類對象的時候一定會先調用父類的構造方法來構造父類的對象。
(2)調用父類構造方法的語句必須是子類構造方法中的第一條指令

super關鍵字的例子:

class Person {String name;String address;void eat() {System.out.println("人吃飯");}void drink() {System.out.println("人喝水");}//Person(){}//解決方法一:在父類中寫一個無參的構造方法Person(String name,String address){//構造方法給屬性賦初值this.name = name;this.address = address;System.out.println("父類構造方法被調用");} }class Student extends Person{ //可以直接使用Person中的屬性了int score;void goToSchool() {System.out.println("學生要上學");}/*Student(){ //如果不寫父類中已有的構造方法的話,系統分配類似于這樣的無參構造方法//如果父類寫了構造方法而子類沒有“對應的”構造方法,就會出錯//解決方法一:在父類中寫一個無參的構造方法;//解決方法二:應用super關鍵字,在子類中完成對父類構造方法的引用}*/ //父類可能有多個構造方法,子類只需要引用一個初始化自己就好//解決方法二:Student(String name,String address){ //沒有下面的super的話 系統不認定這是一個構造方法super(name, address); //調用了父類的構造方法,這個語句必須放在子類構造方法的第一句System.out.println("子類構造方法被調用");}public void eat(){ //因為父類已經有了方法eat,這里權限不能降低,所以加public,后面講多態會介紹:方法的重寫super.eat(); //調用父類的eat,super是對父類的引用。//子類中有eat,父類也有同名的方法,如何區分是父類還是子類的eat,用super!System.out.println("student eat");} }public class Demo1 {public static void main(String[] args) {//在實例化一個對象的時候,子類的構造方法調用會導致父類的構造方法也被調用:Student s = new Student("小明","西祠胡同1號");s.eat();} }

結果:

父類構造方法被調用 子類構造方法被調用 人吃飯 student eat

父類的地址:西祠胡同1號

繼承過來的屬性和方法的權限研究

重點看看父類中的私有屬性private會不會被子類繼承,如果可以,顯然其他的默認屬性如public、默認等肯定也可以。

class Person {String name;private String address; //私有的屬性void eat() {System.out.println("人吃飯");}Person(String name,String address){this.name = name;this.address = address;System.out.println("父類構造方法被調用");} }class Student extends Person{int score;void goToSchool() {System.out.println("學生要上學");}Student(String name,String address){super(name, address); //調用了父類的構造方法 可以間接的訪問到父親的address!}/*void setAddress(String address){this.address = address; //這里提示了address是父類私有的,說明實際上沒有被繼承過來 //不給你用,父親”私藏的“所有東西兒子都是不知道的,繼承不到}*/ }

結論:父類私有的無論是方法還是屬性,都無法被子類繼承。

方法重寫Override

方法重寫是指子類可以根據需要對從父類繼承過來的方法進行改寫,是多態機制的前奏。

(1)重寫方法必須和被重寫方法具有相同的方法名稱、參數列表和返回值
(2)重寫方法不能比被重寫方法有更嚴格的訪問權限
(3)父類中的私有方法,不能被重寫
(4)在子類重寫的方法中繼承調用父類被重寫的方法可以通過super.函數名獲取

注意區別:前面封裝部分提到的方法重載是同一方法名,不同參數列表。而重寫的話則全部都是一樣的,包括函數名、參數、返回值。

例子:

class Person {String name;private String address;public void printName(){System.out.println("name="+name);}private void printAddress(){ //父類的私有方法,想要"重寫"這個方法,子類中的方法不能是privateSystem.out.println("address="+address);} }class Student extends Person {int score;public void printName() { //(1)重寫方法必須和被重寫方法具有相同的名稱、參數列表和返回值//(2)重寫方法不能比被重寫方法有更嚴格的訪問權限System.out.println("子類name=" + name); //方法的實現改了,也是重寫啊,別看就改了一點}public void printAddress(){ //如果這里用的是private,那下面的stu1.printAdd就會報錯System.out.println("想用你的私有方法");//注意:如果父類方法權限是private,子類不能用private去重寫這個方法} //這對于子類來說,父類是不可見的,是看不到父類的方法的 } //所以這對于子類來說,就是【構造了一種新的方法】,既不是方法重寫也不是方法重載!//是不是重寫,就概念的東西,初學,也不必爭辯,知道這么用就行 public class Demo1 {public static void main(String[] args){Student stu1 = new Student();stu1.name = "小明";stu1.printName();stu1.printAddress(); } }

運行結果:

子類name=小明 想用你的私有方法 //說明子類對父類私有方法的重寫 “成功”

Object根類常見方法

java中,所有類都直接或間接繼承自java.lang.Object類,是所有類的根類。如hashcode()、clone()、getClass()、finalize()。

重點介紹下面兩類toString()和equals()

toString()

做個簡單的測試:

package com.huatianzhu.learn;class Person {String name; }public class Demo1 {public static void main(String[] args) {Person p = new Person();p.name = "huatianzhu";System.out.println(p.toString());} }

結果

com.huatianzhu.learn.Person@49e4cb85
  • 1

為什么會是上面的結果?

返回格式:

getClass().getName()+"@"+Integer.toHexString(hashCode());
  • 1

(1)getClass().getName()代表返回對象所屬類的包名.類名,即com.huatianzhu.learn
(2)Integer.toHexString(hashCode())代表將對象的哈希值用16進制表示,其中hashCode()代表返回該對象的哈希值。

常把toString()方法重寫后應用

然而,在實際開發中,通常希望toString()方法返回的不只是上面的信息,所以Object的toString()方法通常會被重寫,如下:

@Override public String toString() {return "Person{" +"name='" + name + '\'' +", address='" + address + '\'' +'}'; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

(這是IDEA的重寫方案:自動補全后就跳出來了如上代碼)

運行結果:使得toString()根據實際需求打印出信息

Person{name='huatianzhu', address='null'}
  • 1

equals()

equals方法沒有重寫的話,用于判斷對象的內存地址引用是否使用一個地址。重寫之后一般用來比較對象的內容是否相等(比如student對象,里面有姓名和年齡,我們重寫,判斷這兩個對象是相等的

重寫:判斷兩個對象p1和p2特征是否相同

package com.huatianzhu.learn;import java.util.Objects;class Person {String name;String address;public boolean equals(Person p){//傳對象參數//Person p = (Person)arg0;不給這樣做強換if(this.address == p.address && this.name == p.name)//C語言比較字符串使用strcmp()return true;elsereturn false;} }public class Demo1 {public static void main(String[] args) {Person p1 = new Person();p1.name = "xiaoming";p1.address = "西祠胡同1號";Person p2 = new Person();p2.name = "xiaoming";p2.address = "西祠胡同1號";System.out.println(p1.equals(p2));} }

運行結果

true
  • 1

IDEA的重寫模板:敲equals可選擇的方案之一

package com.huatianzhu.learn;import java.util.Objects;class Person {String name;String address;//下面兩個override都是IDEA自帶的重寫模板@Overridepublic boolean equals(Object o) {if (this == o) return true;if (!(o instanceof Person)) return false;Person person = (Person) o;return Objects.equals(name, person.name) &&Objects.equals(address, person.address);}@Overridepublic int hashCode() {return Objects.hash(name, address);} }public class Demo1 {public static void main(String[] args) {Person p1 = new Person();p1.name = "xiaoming";p1.address = "西祠胡同1號";Person p2 = new Person();p2.name = "xiaoming";p2.address = "西祠胡同1號";System.out.println(p1.equals(p2));} }

運行結果

true
  • 1

String 類重寫:判斷字符串是否相等

String 類中重寫了 equals() 方法用于比較兩個字符串的內容是否相等。

語法:public boolean equals(Object anObject)

實例:

public class Test {public static void main(String args[]) {String Str1 = new String("huatianzhu");String Str2 = Str1; //直接把 對象1 賦值給 對象2 String Str3 = new String("chenlichen");boolean retVal;retVal = Str1.equals( Str2 );System.out.println("返回值 = " + retVal );retVal = Str1.equals( Str3 );System.out.println("返回值 = " + retVal );} }

運行結果:

返回值 = true 返回值 = false
  • 1
  • 2

繼承練習:java面向對象下的簡單工廠模式

之前做智能家居項目的時候,用了C語言的鏈表,做了簡單工廠模式。在java中感受一下,這面向對象(主要是繼承)的魅力。免除了C語言中在工廠鏈表增加節點的模式,其實底層的實現機制也是類似鏈表。

abstract class Device //抽象類,abstract后面也會有介紹 {String open;String close;void init(){System.out.println("設備的初始化");}abstract void diffFunction(); //抽象方法,不同設備有不同的使用方法,不好在//這個大的類進行規劃,所以做得抽象點Device(String cmd1,String cmd2){this.open = cmd1; //設備的開關指令this.close = cmd2;} }class Camera extends Device {Camera(String cmd1,String cmd2){super(cmd1,cmd2); //當父類有構造方法時(非空),子類必須調用父類的} //構造方法進行屬性的初始化void diffFunction(){System.out.println("相機拿來拍照"); //對抽象方法的具體化,相機是拿來拍照的} //也必須具體化,否則這個繼承的子類也要修飾成抽象類/*public void takePhoto(){System.out.println("拍了張張片"); //每個設備不一樣的功能可以在其父類Device中進行方法的抽象} */ //然后在子類中進行具體化,這是面向對象很方便的地方 }class Lightone extends Device {Lightone(String cmd1,String cmd2){super(cmd1,cmd2);}void diffFunction(){System.out.println("第一個燈拿來照亮臥室");}/*void printInfo(){System.out.println("燈1額外執行的東西");}*/ }class Lighttwo extends Device {Lighttwo(String cmd1,String cmd2){super(cmd1,cmd2);}void diffFunction(){System.out.println("第二個燈拿來照亮浴室");}/*void printInfo(){System.out.println("燈2額外執行的東西");}*/ }class Factory { //返回值是對象Device的方法static Device getDevice(String name){ //作為靜態方法,不用依靠Factory創建的對象訪問if(name == "相機"){return new Camera("open-c1","close-c1");//因為Device是抽象的,不可實例化} //但其繼承這個抽象類的類,使用時必須實例化else if(name == "燈1"){ //所以此處方法返回類型寫的是Device,但返回了具體的實例對象//這也是以后會講解到的多態。return new Lightone("open-d1","close-d1");}else if(name == "燈2"){return new Lighttwo("open-d2","close-d2");}elsereturn null;} }public class Test {public static void main(String[] args) {Factory.getDevice("相機").diffFunction();//通過名字找到子類,并調用子類的功能方法Factory.getDevice("燈1").diffFunction();//是不是像極了C語言的工廠模式,從鏈表中找設備Factory.getDevice("燈2").diffFunction();} }

總結

以上是生活随笔為你收集整理的Java面向对象(2) —— 继承的全部內容,希望文章能夠幫你解決所遇到的問題。

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