亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java基礎(chǔ)之面向?qū)ο髾C(jī)制(多態(tài)、繼承)底層實(shí)現(xiàn)

 更新時(shí)間:2021年04月29日 17:03:33   作者:Rachel~Liu  
這篇文章主要介紹了Java基礎(chǔ)之面向?qū)ο髾C(jī)制(多態(tài)、繼承)底層實(shí)現(xiàn),文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下

一、Java的前世

為什么會(huì)產(chǎn)生Java?Java的特點(diǎn)是什么?

從C語(yǔ)言開(kāi)始講,C語(yǔ)言是一種結(jié)構(gòu)化語(yǔ)言,模塊化編程,便于程序的調(diào)試,依靠非常全面的運(yùn)算符和多樣的數(shù)據(jù)類(lèi)型,可以輕易完成各種數(shù)據(jù)結(jié)構(gòu)的構(gòu)建,通過(guò)指針類(lèi)型更可對(duì)內(nèi)存直接尋址以及對(duì)硬件進(jìn)行直接操作,因此既能夠用于開(kāi)發(fā)系統(tǒng)程序,也可用于開(kāi)發(fā)應(yīng)用軟件。其缺點(diǎn)就是封裝性弱,程序的安全性上不是很好。C語(yǔ)言的異常處理一般使用setjmp()與longjmp(),在捕獲到異常時(shí)進(jìn)行跳轉(zhuǎn);或者使用abort()和exit()兩個(gè)函數(shù),強(qiáng)行終止程序的運(yùn)行。如果要實(shí)現(xiàn)多線程,應(yīng)該要直接操作底層操作系統(tǒng),語(yǔ)言本身沒(méi)有封裝該機(jī)制。

C語(yǔ)言是一門(mén)面向過(guò)程的語(yǔ)言,所謂面向過(guò)程指的是以“事件過(guò)程”為中心的編程思想,即按照事件的解決步驟,在函數(shù)中一步一步實(shí)現(xiàn)。其實(shí),生活中大部分事情都可以用面向過(guò)程的思想來(lái)解決。然而,當(dāng)問(wèn)題的規(guī)模變大,且問(wèn)題中有多個(gè)部分是共同的特征時(shí),我們?nèi)匀恍枰獙?duì)這件事情建立一步一步操作,此時(shí)面向過(guò)程就顯得繁重冗余,因此產(chǎn)生了面向?qū)ο蟮乃枷搿?/p>

面向?qū)ο蟮乃枷胧菍⑹录械囊恍┕餐卣鞒橄蟪鰜?lái)作為一個(gè)對(duì)象,一個(gè)對(duì)象包括屬性和方法,比如說(shuō)一個(gè)班級(jí)中的同學(xué),大家都擁有姓名、成績(jī)、年齡、興趣愛(ài)好,在操作這些數(shù)據(jù)的時(shí)候,我們只需要將共同的部分抽象出來(lái),然后給每個(gè)同學(xué)一個(gè)對(duì)象的實(shí)例。如果是面向過(guò)程的方法,我們需要為每一個(gè)同學(xué)定義屬性變量,執(zhí)行某個(gè)動(dòng)作需要定義獨(dú)立的方法。因此,產(chǎn)生了C++語(yǔ)言。

C++繼承自C語(yǔ)言,可以進(jìn)行面向過(guò)程的程序設(shè)計(jì),也可以抽象化出對(duì)象進(jìn)行基于對(duì)象的程序設(shè)計(jì),也可以進(jìn)行繼承、多態(tài)為特點(diǎn)的面向?qū)ο蟮某绦蛟O(shè)計(jì)。在C++的面向?qū)ο笤O(shè)計(jì)中,將數(shù)據(jù)和相關(guān)操作封裝在一個(gè)類(lèi)中,類(lèi)的實(shí)例為一個(gè)對(duì)象。支持面向?qū)ο箝_(kāi)發(fā)的四個(gè)特性:封裝、抽象、繼承、多態(tài)。在C++語(yǔ)言中,內(nèi)存分為堆(程序運(yùn)行時(shí)分配內(nèi)存)和棧(函數(shù)內(nèi)部聲明的變量)兩部分,往往需要手動(dòng)管理內(nèi)存,通過(guò)new,delete動(dòng)態(tài)劃分內(nèi)存并進(jìn)行內(nèi)存的回收;類(lèi)中包含構(gòu)造函數(shù)和析構(gòu)函數(shù),分別為建立對(duì)象和刪除對(duì)象釋放資源。

Java也是一門(mén)面向?qū)ο蟮恼Z(yǔ)言,不僅吸收了C++的各種優(yōu)點(diǎn),同時(shí)摒棄了C++種難以理解的多繼承、指針等概念,功能更加強(qiáng)大且簡(jiǎn)單易上手。其特點(diǎn):簡(jiǎn)單、OOP、平臺(tái)無(wú)關(guān)性(JVM的功勞);相比于面向?qū)ο蟮恼Z(yǔ)言C++而言,Java JVM的動(dòng)態(tài)內(nèi)存管理非常優(yōu)秀。在發(fā)展的過(guò)程中,逐漸更新了更多強(qiáng)大的功能:XML支持、安全套接字soket支持、全新的I/O API、正則表達(dá)式、日志與斷言;泛型、基本類(lèi)型的自動(dòng)裝箱、改進(jìn)的循環(huán)、枚舉類(lèi)型、格式化I/O及可變參數(shù)。

在C語(yǔ)言、C++、Java的演化過(guò)程中,并不會(huì)導(dǎo)致新語(yǔ)言取代舊語(yǔ)言,每種語(yǔ)言按照自身的特點(diǎn)有了自己適合的領(lǐng)域。如追求程序的性能和執(zhí)行效率,如系統(tǒng)底層開(kāi)發(fā),就需要使用C++,甚至C語(yǔ)言;安卓開(kāi)發(fā)、網(wǎng)站、嵌入式、大數(shù)據(jù)技術(shù)等領(lǐng)域,一般使用Java語(yǔ)言,由于其安全性、便攜性、可移植性、可維護(hù)性等,很容易實(shí)現(xiàn)多線程,代碼的可讀性高。

C語(yǔ)言和C++是編譯型的語(yǔ)言,而Java是解釋型的語(yǔ)言:

  • 編譯型語(yǔ)言:程序在執(zhí)行之前需要一個(gè)專(zhuān)門(mén)的編譯過(guò)程,把程序編譯成為機(jī)器語(yǔ)言的文件。

程序執(zhí)行效率高,依賴(lài)編譯器,跨平臺(tái)性差

  • 解釋型語(yǔ)言:程序不需要編譯,程序運(yùn)行時(shí)才翻譯成機(jī)器語(yǔ)言,每執(zhí)行一次都要翻譯一次。

效率比較低,依賴(lài)解釋器,跨平臺(tái)性好

Java是靜態(tài)-強(qiáng)類(lèi)型語(yǔ)言。

二、多態(tài)

多態(tài)是同一個(gè)行為具有多個(gè)不同表現(xiàn)形式或形態(tài)的能力。多態(tài)就是同一個(gè)接口,使用不同的實(shí)例而執(zhí)行不同操作。

一般實(shí)現(xiàn)形式:

  • 重載@Overload:同一類(lèi)種方法名相同,參數(shù)不同;返回類(lèi)型不要求
  • 重寫(xiě)@Override:子類(lèi)繼承自父類(lèi)的方法重寫(xiě)實(shí)現(xiàn)過(guò)程,返回值、形參不能變、只能重寫(xiě)函數(shù)體內(nèi)的語(yǔ)句,便于子類(lèi)根據(jù)自身需要定義自己的行為。Animal b = new Dog();
  • 接口
  • 抽象類(lèi)、抽象方法

重寫(xiě)規(guī)則:

final,static方法不可被重寫(xiě)

參數(shù)列表:與被重寫(xiě)方法的參數(shù)列表必須完全相同

返回類(lèi)型:與被重寫(xiě)方法的返回類(lèi)型可以不相同,但是必須是父類(lèi)返回值的派生類(lèi)

訪問(wèn)權(quán)限:不能比父類(lèi)中被重寫(xiě)的方法的訪問(wèn)權(quán)限更低(public > protected > private > )

拋異常:如果父類(lèi)方法拋異常,子類(lèi)不能拋更廣泛的異常

同包:除了private final可以重寫(xiě)所有父類(lèi)方法

不同包:只能重寫(xiě)public 或者 protected的非final方法

子類(lèi)中調(diào)用父類(lèi)被重寫(xiě)方法可以用super.method()

三、Java中多態(tài)的底層實(shí)現(xiàn)

多態(tài)性特征的最基本體現(xiàn)有“重載”和“重寫(xiě)”,其實(shí)這兩個(gè)體現(xiàn)在Java虛擬機(jī)中時(shí)分派的作用。分派又分為靜態(tài)分派和動(dòng)態(tài)分派,靜態(tài)分派是指所有依賴(lài)靜態(tài)類(lèi)型來(lái)定位方法執(zhí)行版本的分派動(dòng)作,動(dòng)態(tài)分派是指在運(yùn)行期根據(jù)實(shí)際類(lèi)型確定方法執(zhí)行版本的分派過(guò)程。

 Animal animal = new Bird();

在上面代碼中Animal是父類(lèi),Bird是繼承Animal的子類(lèi);那么在定義animal對(duì)象時(shí)前面的“Animal”稱(chēng)為變量的靜態(tài)類(lèi)型(Static Type),或者叫外觀類(lèi)型(Apparent Type),后面的“Bird”則稱(chēng)為變量的實(shí)際類(lèi)型(Actual Type),靜態(tài)類(lèi)型和實(shí)際類(lèi)型在程序中都可以發(fā)生一些變化,區(qū)別是靜態(tài)類(lèi)型的變化僅僅在使用時(shí)發(fā)生,變量本身的靜態(tài)類(lèi)型不會(huì)被改變,并且最終的靜態(tài)類(lèi)型是在編譯器可知的;而實(shí)際類(lèi)型變化的結(jié)果在運(yùn)行期才可以確定,編譯器在編譯程序的時(shí)候并不知道一個(gè)對(duì)象的實(shí)際對(duì)象是什么。

//實(shí)際類(lèi)型變化
Animal bird = new Bird();
Animal eagle = new Eagle();
//靜態(tài)類(lèi)型變化
sd.sayHello((Bird)bird);
sd.sayHello((Eagle)eagle);

animal對(duì)象的靜態(tài)類(lèi)型是Animal,實(shí)際類(lèi)型是Bird。靜態(tài)類(lèi)型在編譯期可知,實(shí)際類(lèi)型在運(yùn)行時(shí)可知。

四、重載

同一個(gè)類(lèi)中相同方法名的不同方法。

重載,使用哪個(gè)重載版本,就完全取決于傳入參數(shù)的數(shù)量數(shù)據(jù)類(lèi)型。
方法重載是通過(guò)靜態(tài)分派實(shí)現(xiàn)的,靜態(tài)分派是發(fā)生在編譯階段,因此匹配到靜態(tài)類(lèi)型Animal。

例如下面代碼:

package test;
 
/**
* @Description: 方法靜態(tài)分派演示
* @version: v1.0.0
 */
public class StaticDispatch {
    
	static abstract class Animal{ }
	
	static class Bird extends Animal{ }
	
	static class Eagle extends Animal{ }
	
	public void sayHello(Animal animal) {
		System.out.println("hello,animal");
	}
	
	public void sayHello(Bird bird) {
		System.out.println("hello,I'm bird");
	}
	
	public void sayHello(Eagle eagle) {
		System.out.println("hello,I'm eagle");
	}
	
	public static void main(String[] args){
	    Animal bird = new Bird(); // 靜態(tài)類(lèi)型Animal(編譯期可知)--實(shí)際類(lèi)型Bird(運(yùn)行期可知)
	    Animal eagle = new Eagle(); // 靜態(tài)類(lèi)型Animal(編譯期可知)--實(shí)際類(lèi)型Eagle(運(yùn)行期可知)
	    StaticDispatch sd = new StaticDispatch();
	    sd.sayHello(bird);
	    sd.sayHello(eagle);
	}
}
/* 結(jié)果:
hello,animal
hello,animal
*/

代碼中刻意地定義了兩個(gè)靜態(tài)類(lèi)型相同Animal,實(shí)際類(lèi)型不同的變量,但虛擬機(jī)(準(zhǔn)確的是編譯器)在重載時(shí)是通過(guò)參數(shù)的靜態(tài)類(lèi)型而不是實(shí)際類(lèi)型來(lái)作為判斷依據(jù)的。并且靜態(tài)類(lèi)型是編譯期可知的,因此,在編譯階段,Javac編譯器會(huì)根據(jù)參數(shù)的靜態(tài)類(lèi)型決定使用哪個(gè)重載版本,因此選擇了sayHello(Animal)作為調(diào)用目標(biāo)。

方法重載是通過(guò)靜態(tài)分派實(shí)現(xiàn)的,并且靜態(tài)分派是發(fā)生在編譯階段,所以確定靜態(tài)分派的動(dòng)作實(shí)際上不是由虛擬機(jī)來(lái)執(zhí)行的;另外,編譯器雖然能確定出方法重載的版本,但在很多情況下這個(gè)版本并不是“唯一的”,往往只能確定一個(gè)“更加適合”的版本。

五、重寫(xiě)

方法的重寫(xiě):與虛擬機(jī)中動(dòng)態(tài)分派的過(guò)程有著密切聯(lián)系。

package test;
 
/**
* @Description: 方法動(dòng)態(tài)分派演示
* @version: v1.0.0
 */
public class DynamicDispatch {
    
	static abstract class Animal{
		protected abstract void sayHello();
	}
	
	static class Bird extends Animal{
 
		@Override
		protected void sayHello() {
			System.out.println("Bird say hello");
		}
		
	}
	
	static class Eagle extends Animal{
		@Override
		protected void sayHello() {
			System.out.println("Eagle say hello");
		}
		
	}
	
	public static void main(String[] args){
	    Animal bird = new Bird();
	    Animal eagle = new Eagle();
	    bird.sayHello();
	    eagle.sayHello();
	    bird = new Eagle();
	    bird.sayHello();
	}
}

/* 結(jié)果:
Bird say hello
Eagle say hello
Eagle say hello
*/

通過(guò)javap反編譯命令來(lái)看一段該代碼的字節(jié)碼:

>javap -c DynamicDispatch.class
Compiled from "DynamicDispatch.java"
public class com.carmall.DynamicDispatch {
  public com.carmall.DynamicDispatch();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: new           #2                  // class com/carmall/DynamicDispatch$Bird

       3: dup
       4: invokespecial #3                  // Method com/carmall/DynamicDispatch$Bir
d."<init>":()V
       7: astore_1
       8: new           #4                  // class com/carmall/DynamicDispatch$Eagl
e
      11: dup
      12: invokespecial #5                  // Method com/carmall/DynamicDispatch$Eag
le."<init>":()V
      15: astore_2
      16: aload_1
      17: invokevirtual #6                  // Method com/carmall/DynamicDispatch$Ani
mal.sayHello:()V
      20: aload_2
      21: invokevirtual #6                  // Method com/carmall/DynamicDispatch$Animal.sayHello:()V
      24: new           #4                  // class com/carmall/DynamicDispatch$Eagle
      27: dup
      28: invokespecial #5                  // Method com/carmall/DynamicDispatch$Eagle."<init>":()V
      31: astore_1
      32: aload_1
      33: invokevirtual #6                  // Method com/carmall/DynamicDispatch$Animal.sayHello:()V
      36: return
}

上面的指令,invokevirtual表示運(yùn)行時(shí)按照對(duì)象的類(lèi)來(lái)調(diào)用實(shí)例方法;invokespecial根據(jù)編譯時(shí)類(lèi)型來(lái)調(diào)用實(shí)例方法,也就是會(huì)調(diào)用父類(lèi)。

0~15行的字節(jié)碼是準(zhǔn)備動(dòng)作,作用時(shí)建立birdeagle的內(nèi)存空間、調(diào)用BirdEagle類(lèi)型的實(shí)例構(gòu)造器,將這兩個(gè)實(shí)例的引用存放在第1、2個(gè)局部變量表Slot之中。

接下來(lái)的16~21行時(shí)關(guān)鍵部分;這部分把剛剛創(chuàng)建的兩個(gè)對(duì)象的引用壓到棧頂,這兩個(gè)對(duì)象是將要執(zhí)行的sayHello()方法的所有者,稱(chēng)為接收者(Receiver);17和21句是方法調(diào)用命令,這兩條調(diào)用命令單從字節(jié)碼角度來(lái)看,無(wú)論是指令(invokevirtual)還是參數(shù)(都是常量池中第6項(xiàng)的常量,注釋顯示了這個(gè)常量是sayHello方法的符號(hào)引用)完全一樣的,但是這兩句執(zhí)行的目標(biāo)方法并不同,這是因?yàn)?code>invokevirtual指令的多態(tài)查找過(guò)程引起的,該指令運(yùn)行時(shí)的解析過(guò)程可分為以下幾個(gè)步驟:

  • 找到操作數(shù)棧第一個(gè)元素所指向的對(duì)象的實(shí)際類(lèi)型,記為C。如果在類(lèi)型C中找到了與常量中描述符和簡(jiǎn)單名稱(chēng)都一樣的方法,則進(jìn)行訪問(wèn)權(quán)限校驗(yàn),如果通過(guò)則返回該方法的的直接引用,查找過(guò)程結(jié)束;如果不通過(guò),則返回java.lang.IllegalAccessError異常。
  • 否則,按照繼承關(guān)系從下往上一次對(duì)C的各個(gè)父類(lèi)進(jìn)行第二步的搜索和驗(yàn)證過(guò)程。
  • 如果始終都沒(méi)有找到合適的方法,則拋出java.lang.AbstractMethodError異常。
  • 由于invokevirtual指令執(zhí)行的第一步就是在運(yùn)行期確定接收者的實(shí)際類(lèi)型,所以?xún)纱握{(diào)用的invokevirtual指令把常量池中的類(lèi)方法符號(hào)引用解析到了不同的直接引用上,這個(gè)過(guò)程就是Java語(yǔ)言中重寫(xiě)的本質(zhì)。
package java.lang;

import java.lang.annotation.*;

/**
 * Indicates that a method declaration is intended to override a
 * method declaration in a supertype. If a method is annotated with
 * this annotation type compilers are required to generate an error
 * message unless at least one of the following conditions hold:
 *
 * <ul><li>
 * The method does override or implement a method declared in a
 * supertype.
 * </li><li>
 * The method has a signature that is override-equivalent to that of
 * any public method declared in {@linkplain Object}.
 * </li></ul>
 *
 * @author  Peter von der Ah&eacute;
 * @author  Joshua Bloch
 * @jls 9.6.1.4 @Override
 * @since 1.5
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

到此這篇關(guān)于Java基礎(chǔ)之面向?qū)ο髾C(jī)制(多態(tài)、繼承)底層實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Java面向?qū)ο髾C(jī)制底層實(shí)現(xiàn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • IDEA 2023創(chuàng)建JSP項(xiàng)目的完整步驟教程

    IDEA 2023創(chuàng)建JSP項(xiàng)目的完整步驟教程

    這篇文章主要介紹了IDEA 2023創(chuàng)建JSP項(xiàng)目的完整步驟教程,創(chuàng)建項(xiàng)目需要經(jīng)過(guò)新建項(xiàng)目、設(shè)置項(xiàng)目名稱(chēng)和路徑、選擇JDK版本、添加模塊和工件、配置Tomcat服務(wù)器等步驟,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2024-10-10
  • 批量將現(xiàn)有Jar包上傳到Maven私服

    批量將現(xiàn)有Jar包上傳到Maven私服

    今天小編就為大家分享一篇關(guān)于批量將現(xiàn)有Jar包上傳到Maven私服,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-12-12
  • Java泛型類(lèi)型擦除

    Java泛型類(lèi)型擦除

    這篇文章主要為大家詳細(xì)介紹了Java泛型類(lèi)型擦除,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-03-03
  • java中BigDecimal的介紹及使用教程BigDecimal格式化及BigDecimal常見(jiàn)問(wèn)題

    java中BigDecimal的介紹及使用教程BigDecimal格式化及BigDecimal常見(jiàn)問(wèn)題

    BigDecimal是Java在java.math包中提供的線程安全的API類(lèi),用來(lái)對(duì)超過(guò)16位有效位的數(shù)進(jìn)行精確的運(yùn)算,這篇文章主要介紹了java中BigDecimal的介紹及使用,BigDecimal格式化,BigDecimal常見(jiàn)問(wèn)題,需要的朋友可以參考下
    2023-08-08
  • Spring Cache手動(dòng)清理Redis緩存

    Spring Cache手動(dòng)清理Redis緩存

    這篇文章主要介紹了Spring Cache手動(dòng)清理Redis緩存,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-10-10
  • Java 獲取當(dāng)前設(shè)備的 IP 地址(最新推薦)

    Java 獲取當(dāng)前設(shè)備的 IP 地址(最新推薦)

    Internet 協(xié)議 (IP) 地址可以是連接到 TCP/IP 網(wǎng)絡(luò)的每個(gè)設(shè)備的標(biāo)識(shí)符,該標(biāo)識(shí)符用于識(shí)別和定位中間通信的節(jié)點(diǎn),這篇文章主要介紹了在 Java 中獲取當(dāng)前設(shè)備的 IP 地址,需要的朋友可以參考下
    2023-06-06
  • Java中的snowflake算法詳解

    Java中的snowflake算法詳解

    這篇文章主要介紹了Java中的snowflake算法詳解,Snowflake算法產(chǎn)生是為了滿足Twitter每秒上萬(wàn)條消息的請(qǐng)求,每條消息都必須分配一條唯一的id,這些id還需要一些大致的順序,并且在分布式系統(tǒng)中不同機(jī)器產(chǎn)生的id必須不同,需要的朋友可以參考下
    2023-08-08
  • 解析java中super的用法分析

    解析java中super的用法分析

    本篇文章是對(duì)java中super的用法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • spring-shiro權(quán)限控制realm實(shí)戰(zhàn)教程

    spring-shiro權(quán)限控制realm實(shí)戰(zhàn)教程

    這篇文章主要介紹了spring-shiro權(quán)限控制realm實(shí)戰(zhàn)教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • java.io.IOException:?UT010029:?Stream?is?closed異常分析及解決

    java.io.IOException:?UT010029:?Stream?is?closed異常分析及解決

    這篇文章主要給大家介紹了關(guān)于java.io.IOException:?UT010029:?Stream?is?closed異常分析及解決辦法,文中通過(guò)代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2024-02-02

最新評(píng)論