程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java的面向對象編程根本概念進修筆記整頓

Java的面向對象編程根本概念進修筆記整頓

編輯:關於JAVA

Java的面向對象編程根本概念進修筆記整頓。本站提示廣大學習愛好者:(Java的面向對象編程根本概念進修筆記整頓)文章只能為提供參考,不一定能成為您想要的結果。以下是Java的面向對象編程根本概念進修筆記整頓正文


小我懂得,編程中所謂的 類¨ 與實際世界中對物體的分門別類中的類是統一個概念,只是在編程中將其借用出去。類代表有一系列個性和雷同操作或舉措的事物,在編程中即為籠統的數據類型。詳細的每一個個別(實際世界中)、實例變量(關於在編程中來講)就是對象。

  類是實際世界某些對象的配合特點(屬性和操作)的表現,對象是類的實例。

    類的屬性:就是類的靜態屬性的簡稱,指類內包括的各項數據,如變量或其他類的對象;
   類的辦事:  則被稱為成員函數或辦法。


¨ 

Java中類的界說情勢以下:

[潤飾符] class 類名 [extends 父類] [implements 接口名]
{
 類成員變量聲明
 類辦法聲明

}

我們再來細心說說這中央的每個部門:

在class症結字前,也即類的潤飾符有年夜體分三品種型——拜訪潤飾符public公共類、final潤飾符(終究類解釋符)和abstract潤飾符(籠統類解釋符)

          而個中,權限潤飾符只能為public或默許(即為空,甚麼都沒有,表現界說為友愛的),public表現該類可被任何處所應用和拜訪(只需法式能找到該類地位),不管是在統一包內,照樣在分歧包。留意,這與C++中分歧,C++中沒有還對類的拜訪權限用潤飾符來限制的,而是對類之間的繼續關系有拜訪權限的解釋,除此以外,它們卻是都對類的屬性和辦法有拜訪權限無限制。          默許的拜訪權限(即界說為友愛的),等於指只能被統一包內的類援用和拜訪,而不克不及被其它包中的類拜訪和援用,即便import出來。

前面還會提到:以類的屬性和辦法缺省潤飾符時,也表現為只能被統一包中的類援用和拜訪。

Java中不許可多重繼續,這與C++中分歧,也算是為了填補這個缺乏,Java中引進了接口的概念。


上述類的界說中,類體中重要是類的詳細內容,包含類的屬性和類的辦法。類的屬性可所以簡略變量,也能夠是某些類的實例,假如是類的實例,可以以下界說:

[潤飾符]   類名 對象名=new類名(參數列表);

在聲明對象和龐雜變量時,可以不在聲明時用創立,可以在今後的結構函數中創立。

類中界說的辦法平日起到兩種感化:一是環繞著類的屬性停止各類操作;二是與其他的類或對象停止數據交換、新聞傳遞等操作。

Java中聲明辦法的語法以下:

 [潤飾符] 前往值類型 辦法名(參數列表)

throws 破例名1,破例名2,…

{ 辦法體:

 部分變量聲明;

 語句序列;

}

類的辦法,又稱為成員函數,用來劃定類屬性上的操作,完成類的外部功效的機制,同時也是類與外界停止交互的主要窗口。

Java法式員把留意力放在創立稱為類的用戶自界說類型(user-definedtype)上,類也稱為法式員界說的類型(programmer-definedtype),每一個類都含稀有據和一組操作數據的辦法,類中的數據部門稱為實例變量。用戶界說類型(即類)的實例稱為對象。


對象是類的一個實例,類是同種對象的籠統,是創立對象的模板。在法式中創立—個對象將在內存中開拓一塊空間,個中包含該對象的屬性和辦法。創立對象應用症結字運算符new。

結構函數(可以比較C++中,與C++簡直雷同)


創立本身的結構函數
•結構函數的名字和類的名字是雷同的。當結構Employee類的對象時,此結構函數被啟動,實例字段賦初值,在Java中,界說和初始化是同一的——二者缺一弗成。
  例如,用上面的代碼創立Employee類的一個實例時,

newEmployee (“James Bond”,100000,1950,1,1);

結構函數的特色有:

(1)結構函數和類具有雷同的名字。

(2)一個類可以有多個結構函數。

(3)結構函數可以有0個、1個或多個參數。

(4)結構函數沒有前往值。

(5)結構函數老是和new運算符一路被挪用。

結構函數的感化
 (1)對象初始化

(2)引入更多的靈巧度(變量賦值或更龐雜的操作)

(3)Java中可以不界說結構函數

 Java中可以不界說結構函數,此時體系會主動為該體系生成一個默許的結構函數。這個結構函數的名字與類名雷同,它沒有任何情勢參數,也不完成任何操作。

 辦法概述
Java法式是由一個個類界說構成的,類有兩個部門:屬性和辦法。屬性描寫類是甚麼,辦法描寫類做甚麼。任何對象都有自力的內存存儲它的屬性。類的一切的對象同享存貯在內存的辦法。

    換言之:辦法是類的重要構成部門。在一個類中,法式的感化表現在辦法中。

  辦法等於JAVA創立一個著名字的子法式。一個主辦法和若干個子辦法組成。主辦法挪用其他辦法,其他辦法間也可相互挪用,統一個辦法可被一個或多個辦法挪用隨意率性次。
在一個辦法中界說另外一個辦法將發生語法毛病。


(1)最好防止部分變量“屏障”實例變量,在一個類中不應用同名標識符便可以做到這一點;辦法挪用中參數用來傳遞數值、傳遞援用,同時辦法還可以嵌套、遞歸挪用。
(2)辦法體中假如指定了非void的前往值類型,辦法中就必需包括一條return語句包管任何情形下都有前往數值,return語句前面不克不及跟任何表達式;
Java法式的根本構造以下:

引入Java類庫;
界說用戶類1
{
 
 界說類1的若干變量或對象:
 界說類1的辦法1;
 界說類1的辦法2;
  …
 界說類1的辦法M1;
}
界說用戶類2
{
 界說類2的若干變量或對象:
 界說類2的辦法1;
 界說類2的辦法2;
  …
 界說類2的辦法M2
}

Java推出了“拜訪掌握潤飾符”的概念,許可庫創立者聲明哪些器械是客戶法式員可使用的,哪些是弗成應用的。

這類拜訪掌握的級別在“最年夜拜訪”和“最小拜訪”的規模之間,分離包含:public,“默許”(有關鍵字),protected和private。上面的列表解釋拜訪掌握潤飾符寄義:


公共拜訪掌握符public
用於類:  

Java中類的拜訪掌握符只要一個:public,即公共的。一個類被聲明為公共類,注解它可以被一切的其他類所拜訪和援用,這裡的拜訪和援用是指這個類作為全體是可見和可以使用的,法式的其他部門可以創立這個類的對象、拜訪這個類外部可見的成員變量和挪用它的可見的辦法。
一個類作為全體對法式的其他部門可見,其實不能代表類內的一切屬性和辦法也同時對法式的其他部門可見,前者只是後者的需要前提,類的屬性和辦法可否為一切其他類所拜訪,還要看這些屬性和辦法本身的拜訪掌握符。

用於類內屬性:    

用public潤飾的類內屬性稱為公共屬性,若這個類是公共類則它可以被一切的其他類拜訪。

缺省拜訪掌握符
用於類  

   假設一個類沒有拜訪掌握符,解釋它具出缺省的拜訪掌握特征。這類缺省的拜訪掌握權劃定該類只能被統一個包中的類拜訪和援用,而弗成以被其他包中的類應用,這類拜訪特征稱為包拜訪性。經由過程聲明類的拜訪掌握符可使全部法式構造清楚、嚴謹,削減能夠發生類間攪擾和毛病。

用於類屬性  

    類內的屬性和辦法假如沒有拜訪掌握符號來限制,也解釋它們具有包拜訪性。

3 公有拜訪掌握符private
用private潤飾的屬性或辦法只能被該類本身所拜訪和修正,而不克不及被任何其他類,包含該類的子類,來獲得和援用
1). 公有數據
例若有三個實例字段,它們含有在Employee類的實例外部被操作的數據。

private string name;

private double salary;

private Date hireDay;

       private(公有的)症結字用來確保可以拜訪這些實例字段的只能是Employee類自己的辦法。


2).公有辦法
在完成類時,我們使一切的數據字段都是公有的,由於地下的數據是風險的。關於辦法又是甚麼情形呢 ?固然年夜多半辦法是地下的,然則公有辦法也常常應用。這些辦法只能被統一個分別的辦法。

總起來講,鄙人面的情形下可以選擇公有辦法:

  (1)與類的應用者有關的那些辦法。

(2)假如類的完成轉變了,不輕易保護的那些辦法。


掩護拜訪掌握符protected
用protected潤飾的成員變量可以被三品種所援用:該類本身、與它在統一個包中的其他類、在其他包中的該類的子類。應用protected潤飾符的重要感化是許可其他包中的它的子類來拜訪父類的特定屬性。
         protected症結字為我們引入了一種名為“繼續”的概念,它以現有的類為基本,並在個中參加新的成員,同時不會對現有的類發生影響——我們將這類現有的類稱為“基本類”或許“根本類”(Base Class)。亦可轉變誰人類現有成員的行動。關於從一個現有類的繼續,我們說本身的新類“擴大”(extends)了誰人現有的類

公有掩護拜訪掌握符private protected
private和protected按次序連用組成一個完全的拜訪掌握符:公有掩護拜訪掌握符。用privateprotected潤飾的成員變量可以被兩品種拜訪和援用,一種是該類自己,一種是該類的一切子類,豈論這些子類是與該類在統一個包裡,照樣處於其他的包中。

絕對於protected,privateprotected潤飾符把統一包內的非子類消除在可拜訪的規模以外,使得成員變量更專有於具有明白繼續關系的類,而不是松懈地組合在一路的包。

靜態潤飾符
static稱為靜態潤飾符,它可以潤飾類中的屬性和辦法。

應用static(靜態)症結字,可知足兩方面的請求:

(1)一種情況是只想用一個存儲區域來保留一個特定的數據——不管要創立若干個對象,乃至基本不創立對象;被static潤飾的屬性稱為靜態屬性,這類屬性一個最實質的特色是:它們是類的屬性,而不屬於任何一個類的詳細對象。換句話說,關於該類的任何一個詳細對象而言,靜態屬性是一個公共的存儲單位,任何一個類的對象拜訪它時,取到的都是雷同的數值,異樣任何一個類的對象去修正它時,也都是在對統一個內存單位做操作。
(2)另外一種情況是我們須要一個特別的辦法,它沒有與這個類的任何對象聯系關系。也就是說,即便沒有創立對象,也須要一個能用類直接挪用的辦法。

 static一項主要的用處就是贊助我們在不用創立對象的條件下挪用誰人辦法。


靜態常量
靜態變量是很少見的。但是,靜態常量卻很廣泛。例如,Math類中界說了一個靜態常量:
public class Math

{

……

public static final double PI=3.1.4159265358979323846;

……

}

靜態辦法
      聲明一個辦法為static至多有三重寄義:
(1)應用這個辦法時,應當應用類名做前綴,而不是某一個詳細的對象名;
(2)非static的辦法是屬於某個對象的辦法,在這個對象創立時對象的辦法在內存中具有本身公用的代碼段;而static的辦法是屬於全部類的,它在內存中的代碼段將跟著類的界說而分派和裝載,不被任何一個對象專有;
(3)因為static辦法是屬於全部類的,所以它不克不及把持和處置屬於某個對象的成員變量,而只能處置屬於全部類的成員變量。

5  main辦法
    main辦法其實不對任何對象施加操作。現實上,當法式開端履行時,還不存在任何對象。靜態辦法被履行,並結構法式所需的對象。

   提醒  每一個類都可以有一個main辦法。這是對類停止單位測試的一個很便利技能。

abstract是籠統潤飾符,可以用來潤飾類或辦法。

籠統類
當一個類被聲明為abstract時,這個類被稱為是籠統類。所謂籠統類就是沒有詳細實例對象的類。
針對這個成績,Java專門供給了一種機制,名為“籠統辦法”。它屬於一種不完全的辦法,只含有一個聲明,沒無方法主體。上面是籠統辦法聲明時采取的語法:
abstract void X();

籠統辦法
     作為類辦法潤飾符,abstract則聲清楚明了一種唯一辦法頭,而沒有詳細的辦法體和操作完成的籠統辦法。

     可見,abstract辦法只要辦法頭的聲明,而用一個分號來取代辦法體的界說:至於辦法體的詳細完成,那是由以後類的分歧子類在它們各自的類界說中完成的。
須要特殊留意的是,一切的籠統辦法,都必需存在於籠統類之


中。
    除籠統辦法,籠統類也能夠有詳細的數據和辦法。
  在Java編程說話中籠統辦法長短常主要的概念。在接口裡你會年夜量的用到它。
留意:這裡要與接口停止比較、記憶,接口中的辦法都屬於籠統辦法,固然,接口中也有屬性,其詳細性質將在後文胪陳。

終究類、終究屬性、終究辦法與終結器(C++中可沒有final終究潤飾符)


final是終究潤飾符,它可以潤飾類、屬性和辦法。別的終結器的症結字與final很鄰近,一並引見

終究類

    假如一個類被聲明為final,意味著它不克不及再派生出新的子類,不克不及作為父類被繼續。是以一個類不克不及既被聲明為abstract的,又被聲明為final的。

被界說成final的類,平日是一些有特別感化的、用來完成尺度功效的類,將一個類界說為final則可以將它的內容、屬性和功效固定上去,與它的類名構成穩固的映照關系,從而包管援用這個類時所完成的功效是精確無誤的

終究屬性
很多法式設計說話都有本身的方法告知編譯器某個數據是“常數”。常數重要運用於下述兩個方面:

(1)編譯期常數,它永久不會轉變;

(2)在運轉期初始化的一個值,我們不願望它產生變更。

     可以把一個實例字段界說為final(不克不及轉變的)。在對象被結構時,這類字段必需被初始化。即,必需包管在每個結構函數停止之前其值已被設定。今後字段的值不克不及轉變

終究辦法
          之所以要應用final辦法,能夠是出於對兩方面來由的斟酌。
        第一個是為辦法“上鎖”,避免任何繼續類轉變它的原來寄義。設計法式時,若願望一個辦法的行動在繼續時代堅持不變,並且弗成被籠罩或改寫,便可以采用這類做法。
     采取final辦法的第二個來由是法式履行的效力

終結器
終結器的感化是收受接管對象時履行的辦法。相似與結構函數是創立對象時履行的辦法一樣。

protected voidfinalize(){
   System.out.println(“ “);

  }

其它潤飾符

volatile

  假如一個屬性被volatile潤飾,解釋這個屬性可以同時被幾個線程所掌握和修正。

synchronized

  重要用於線程同步

native

  表現該辦法不是用java說話寫成的(是用C,C++等說話寫的)

網上查到的一點材料:——外部類


簡略的說,外部類就是類中的類,舉個例子:

class A {
private int i;
private void m() {

}
class B {
mm(int j) {
i = j;
m();
}
}
}

這裡,B就是A的外部類
外部類的特色就是,可以便利的拜訪內部類外面的公有辦法和屬性,好比,這裡B外面可以直接拜訪A外面的公有屬性i,和公有辦法m()

面向對象編程最主要的特點就是封裝性(也可稱作籠統性)、繼續性和多態性,那末,作為面向對象編程說話,Java在這方面更是有其精彩的地方:

“繼續性是軟件復用的一種情勢,對下降軟件龐雜性卓有成效。繼續性同時是面向對象法式設計說話的特色,采取對象但沒有繼續性的說話是基於對象的說話,但不是面向對象的說話,這是二者的差別”

類之間的繼續關系是實際世界中遺傳關系的直接模仿,它表現類之間的內涵接洽和對屬性和操作的同享,即子類可以沿用父類(被繼續類)的某些特點。固然,子類也能夠具有本身自力的屬性和操作

繼續性是軟件復用的一種情勢。新類由已存在的類生成,經由過程保存它們的屬性和行動,而且依據新類的請求對機能加以修正,添加新的屬性和行動。假如子類只從一個父類繼續,則稱為單繼續;假如子類從一個以上父類繼續,則稱為多繼續。留意Java不支撐多重繼續,但它支撐“接口”概念。接口使Java取得了多重繼續的很多長處,摒棄了響應的缺陷。留意:C++支撐多繼續

繼續關系的界說:

[潤飾符]class子類名
extends父類名,父類名2


父類名跟在extends

  症結字前面,用來講明以後類是哪一個曾經存在類的子類,存在繼續關系。

界說 雇員類  Employee的兩個子類:

普通雇員類:CommonEmployee

主    管    類:ManagerEmployee

子類從父類繼續有兩個重要的方面:

(1)屬性的繼續。例如,公司是一個父類,一個公司著名稱、地址、司理、雇員等,這些都屬於構造方面。

(2)辦法的繼續。一個父類界說了若干操作,如一個公司要有項目、利潤、錄用司理、錄用職工等操作,子公司也將繼續這些行動s;mp

classCommonEmployeeextends
 Employee//子類1:

{
 intm_ManagerNo ;//界說類屬性m _ManagerNo,代表雇員下屬的編號
}
classManagerEmployeeextends Employee //子類2:
{
 intm_SecretaryNo; //界說類屬性m_SecretaryNo,代表秘書的編號
}

屬性繼續與隱蔽
雖然Employee類是一個父類,然則其實不由於它是父類就意味著它有更多的功效。恰好相反,子類比它們的父類具有更多的功效。由於子類是父類的擴大,增長了父類沒有的屬性和辦法
(1)子類不克不及拜訪父類的private成員,但子類可以拜訪其父類的public,

(2)protected拜訪是public和private拜訪之間一個掩護性的中央條理。

(3)因為被繼續的父類成員沒有在子類聲明中列出,然則這些成員確切存在於子類中。
在這裡,要辨別一下繼續、籠罩與重載這幾個易混雜的概念:

只要辦法這一概念層面,這三個概念才易混雜:

辦法繼續

關於子類對象,可使用父類中的辦法。即便這些辦法沒有顯著地在子類中界說,它們也主動地從父類中繼續過去了

辦法籠罩


辦法的籠罩是指:子類界說同名辦法來籠罩父類的辦法,是多態技巧的一個完成。當父類辦法在子類中被籠罩時,平日是子類版本挪用父類版本,並做一些附加的任務。

有許多留意事項,這裡,我重要提一下this與super,C++中有this(且與Java中中概念差不多),然則沒有super。


this表現的是以後對象自己,this代表以後對象的一個援用。可以懂得為對象的另外一個名字。應用this可以挪用以後對象的辦法和屬性。

如:this.getName()和getName()在類中是一樣的。


super表現的是以後對象的直接父類對象,是以後對象的父類對象的援用
辦法重載


重載的界說:可以用雷同的辦法名但分歧的參數表來界說辦法(參數表中參數的數目、類型或順序有差別),這稱為辦法重載。
•重載(overloading):當多個辦法具有雷同的名字而含有分歧的參數時,便產生重載。編譯器必需遴選處挪用哪一個辦法。它經由過程將在分歧辦法頭部中的參數類型和在特定的辦法挪用中應用值的類型停止比擬,從而遴選出准確的辦法。


多態性許可以同一的作風處置已存在的變量及相干的類,使增長體系中新功效變得輕易。這裡,貼一下網上找的材料,能更清晰地將繼續中需特殊留意的多態、繼續中的成績弄清:

 Java的多態性
面向對象編程有三個特點,即封裝、繼續和多態。

    封裝隱蔽了類的外部完成機制,從而可以在不影響應用者的條件下轉變類的外部構造,同時掩護了數據。

     繼續是為了重用父類代碼,同時為完成多態性作預備。那末甚麼是多態呢?

     辦法的重寫、重載與靜態銜接組成多態性。Java之所以引入多態的概念,緣由之一是它在類的繼續成績上和C++分歧,後者許可多繼續,這確切給其帶來的異常壯大的功效,然則龐雜的繼續關系也給C++開辟者帶來了更年夜的費事,為了躲避風險,Java只許可單繼續,派生類與基類間有IS-A的關系(即“貓”is a “植物”)。如許做固然包管了繼續關系的簡略清楚明了,然則必將在功效上有很年夜的限制,所以,Java引入了多態性的概念以填補這點的缺乏,另外,籠統類和接口也是處理單繼續劃定限制的主要手腕。同時,多態也是面向對象編程的精華地點。

     要懂得多態性,起首要曉得甚麼是“向上轉型”。

     我界說了一個子類Cat,它繼續了Animal類,那末後者就是前者是父類。我可以經由過程

 Cat c = new Cat();

 實例化一個Cat的對象,這個不難懂得。但當我如許界說時:

 Animal a = new Cat();

 這代表甚麼意思呢?

     很簡略,它表現我界說了一個Animal類型的援用,指向新建的Cat類型的對象。因為Cat是繼續自它的父類Animal,所以Animal類型的援用是可以指向Cat類型的對象的。那末如許做有甚麼意義呢?由於子類是對父類的一個改良和擴大,所以普通子類在功效上較父類更壯大,屬性較父類更奇特,

界說一個父類類型的援用指向一個子類的對象既可使用子類壯大的功效,又可以抽取父類的個性。

所以,父類類型的援用可以挪用父類中界說的一切屬性和辦法,而關於子類中界說而父類中沒有的辦法,它是迫不得已的;

同時,父類中的一個辦法只要在在父類中界說而在子類中沒有重寫的情形下,才可以被父類類型的援用挪用;

關於父類中界說的辦法,假如子類中重寫了該辦法,那末父類類型的援用將會挪用子類中的這個辦法,這就是靜態銜接。

 看上面這段法式:

class Father{ 
 public void func1(){ 
  func2(); 
 } 
 //這是父類中的func2()辦法,由於上面的子類中重寫了該辦法 
 //所以在父類類型的援用中挪用時,這個辦法將不再有用 
 //取而代之的是將挪用子類中重寫的func2()辦法 
 public void func2(){ 
  System.out.println("AAA"); 
 } 
} 
 
class Child extends Father{ 
 //func1(int i)是對func1()辦法的一個重載 
 //因為在父類中沒有界說這個辦法,所以它不克不及被父類類型的援用挪用 
 //所以鄙人面的main辦法中child.func1(68)是纰謬的 
 public void func1(int i){ 
  System.out.println("BBB"); 
 } 
 //func2()重寫了父類Father中的func2()辦法 
 //假如父類類型的援用中挪用了func2()辦法,那末必定是子類中重寫的這個辦法 
 public void func2(){ 
  System.out.println("CCC"); 
 } 
} 
 
public class PolymorphismTest { 
 public static void main(String[] args) { 
  Father child = new Child(); 
  child.func1();//打印成果將會是甚麼? 
 } 
}

     下面的法式是個很典范的多態的例子。子類Child繼續了父類Father,偏重載了父類的func1()辦法,重寫了父類的func2()辦法。重載後的func1(int i)和func1()不再是統一個辦法,因為父類中沒有func1(int i),那末,父類類型的援用child就不克不及挪用func1(int i)辦法。而子類重寫了func2()辦法,那末父類類型的援用child在挪用該辦法時將會挪用子類中重寫的func2()。

     那末該法式將會打印出甚麼樣的成果呢?

     很明顯,應當是“CCC”。

     關於多態,可以總結它為:

(1)應用父類類型的援用指向子類的對象(現實對象);

(2)該援用只能挪用父類中界說的辦法和變量;

(3)假如子類中重寫了父類中的一個辦法,那末在挪用這個辦法的時刻,將會挪用子類中的這個辦法;(靜態銜接、靜態挪用)
(4)變量不克不及被重寫(籠罩),”重寫“的概念只針對辦法,假如在子類中”重寫“了父類中的變量,那末在編譯時會報錯。


多態是經由過程:
 (1) 接口 和 完成接口並籠罩接口中統一辦法的幾個分歧的類表現的
 (2) 父類 和 繼續父類並籠罩父類中統一辦法的幾個分歧子類完成的.

1.根本概念

 多態性:發送新聞給某個對象,讓該對象自行決議呼應何種行動。
 經由過程將子類對象援用賦值給超類對象援用變量來完成靜態辦法挪用。

 ava 的這類機制遵守一個准繩:當超類對象援用變量援用子類對象時,被援用對象的類型而不是援用變量的類型決議了挪用誰的成員辦法,然則這個被挪用的辦法必需是在超類中界說過的,也就是說被子類籠罩的辦法。

 (1)假如a是類A的一個援用,那末,a可以指向類A的一個實例,或許說指向類A的一個子類。
 (2)假如a是接口A的一個援用,那末,a必需指向完成了接口A的一個類的實例。


Java多態性完成機制

 SUN今朝的JVM完成機制,類實例的援用就是指向一個句柄(handle)的指針,這個句柄是一對指針:
一個指針指向一張表格,現實上這個表格也有兩個指針(一個指針指向一個包括了對象的辦法表,別的一個指向類對象,注解該對象所屬的類型);
另外一個指針指向一塊從java堆中為分派出來內存空間。

總結

 (1)經由過程將子類對象援用賦值給超類對象援用變量來完成靜態辦法挪用。

DerivedC c2=new DerivedC(); 
BaseClass a1= c2; //BaseClass 基類,DerivedC是繼續自BaseClass的子類 
a1.play(); //play()在BaseClass,DerivedC中均有界說,即子類覆寫了該辦法 

剖析:
* 為何子類的類型的對象實例可以覆給超類援用?
主動完成向上轉型。經由過程該語句,編譯器主動將子類實例向上挪動,成為通用類型BaseClass;
* a.play()將履行子類照樣父類界說的辦法?
子類的。在運轉時代,將依據a這個對象援用現實的類型來獲得對應的辦法。所以才有多態性。一個基類的對象援用,被付與分歧的子類對象援用,履行該辦法時,將表示出分歧的行動。

 在a1=c2的時刻,依然是存在兩個句柄,a1和c2,然則a1和c2具有統一塊數據內存塊和分歧的函數表。

 (2)不克不及把父類對象援用賦給子類對象援用變量

BaseClass a2=new BaseClass(); 
DerivedC c1=a2;//失足 

 在java外面,向上轉型是主動停止的,然則向下轉型卻不是,須要我們本身界說強迫停止。
c1=(DerivedC)a2; 停止強迫轉化,也就是向下轉型.

 (3)記住一個很簡略又很龐雜的規矩,一個類型援用只能援用援用類型本身含有的辦法和變量。
你能夠說這個規矩纰謬的,由於父類援用指向子類對象的時刻,最初履行的是子類的辦法的。
其實這其實不抵觸,那是由於采取了前期綁定,靜態運轉的時刻又依據型別去挪用了子類的辦法。而假若子類的這個辦法在父類中並沒有界說,則會失足。
 例如,DerivedC類在繼續BaseClass中界說的函數外,還增長了幾個函數(例如 myFun())

 剖析:
當你應用父類援用指向子類的時刻,其實jvm曾經應用了編譯器發生的類型信息調劑轉換了。
這裡你可以如許懂得,相當於把不是父類中含有的函數從虛擬函數表中設置為弗成見的。留意有能夠虛擬函數表中有些函數地址因為在子類中曾經被改寫了,所以對象虛擬函數表中虛擬函數項目地址曾經被設置為子類中完成的辦法體的地址了。


 (4)Java與C++多態性的比擬

 jvm關於多態性支撐處理辦法是和c++中簡直一樣的,
只是c++中編譯器許多是把類型信息和虛擬函數信息都放在一個虛擬函數表中,然則應用某種技巧來差別。

 Java把類型信息和函數信息離開放。Java中在繼續今後,子類會從新設置本身的虛擬函數表,這個虛擬函數表中的項目有由兩部門構成。從父類繼續的虛擬函數和子類本身的虛擬函數。
虛擬函數挪用是經由虛擬函數表直接挪用的,所以才得以完成多態的。

            Java的一切函數,除被聲明為final的,都是用前期綁定。

1個行動,分歧的對象,他們詳細表現出來的方法紛歧樣,
         好比:     辦法重載 overloading 和 辦法重寫(籠罩)override 

     class Human{ 
     void run(){輸入 人在跑} 
      } 
    class Man extends Human{ 
   void run(){輸入 漢子在跑} 
     } 
     這個時刻,同是跑,分歧的對象,紛歧樣(這個是辦法籠罩的例子) 
    class Test{ 
   void out(String str){輸入 str} 
    void out(int i){輸入 i} 
    } 

                這個例子是辦法重載,辦法名雷同,參數表分歧

               ok,明確了這些還不敷,還用人在跑舉例
              Human ahuman=new Man();
              如許我等於實例化了一個Man的對象,並聲清楚明了一個Human的援用,讓它去指向Man這個對象
               意思是說,把 Man這個對象當 Human看了.

               好比去植物園,你看見了一個植物,不曉得它是甚麼, "這是甚麼植物? " "這是年夜熊貓! "
               這2句話,就是最好的證實,由於不曉得它是年夜熊貓,但曉得它的父類是植物,所以,
               這個年夜熊貓對象,你把它當做其父類 植物看,如許子通情達理.

              這類方法下要留意 new Man();切實其實實例化了Man對象,所以 ahuman.run()這個辦法 輸入的   是 "漢子在跑 "

               假如在子類 Man下你 寫了一些它獨有的辦法 好比 eat(),而Human沒有這個辦法,

 在挪用eat辦法時,必定要留意 強迫類型轉換 ((Man)ahuman).eat(),如許才可以...

 對接口來講,情形是相似的...

 實例:

package domatic; 

//界說超類superA 
class superA { 
int i = 100; 

void fun(int j) { 
j = i; 
System.out.println("This is superA"); 
} 
} 

// 界說superA的子類subB 
class subB extends superA { 
int m = 1; 

void fun(int aa) { 
System.out.println("This is subB"); 
} 
} 

// 界說superA的子類subC 
class subC extends superA { 
int n = 1; 

void fun(int cc) { 
System.out.println("This is subC"); 
} 
} 

class Test { 
public static void main(String[] args) { 
superA a = new superA(); 
subB b = new subB(); 
subC c = new subC(); 
a = b; 
a.fun(100); 
a = c; 
a.fun(200); 
} 
} 

/*
* 上述代碼中subB和subC是超類superA的子類,我們在類Test中聲清楚明了3個援用變量a, b,
* c,經由過程將子類對象援用賦值給超類對象援用變量來完成靜態辦法挪用。或許有人會問:
* "為何(1)和(2)不輸入:This is superA"。
* java的這類機制遵守一個准繩:當超類對象援用變量援用子類對象時,
* 被援用對象的類型而不是援用變量的類型決議了挪用誰的成員辦法,
* 然則這個被挪用的辦法必需是在超類中界說過的,
* 也就是說被子類籠罩的辦法。
* 所以,不要被上例中(1)和(2)所困惑,固然寫成a.fun(),然則因為(1)中的a被b賦值,
* 指向了子類subB的一個實例,因此(1)所挪用的fun()現實上是子類subB的成員辦法fun(),
* 它籠罩了超類superA的成員辦法fun();異樣(2)挪用的是子類subC的成員辦法fun()。
* 別的,假如子類繼續的超類是一個籠統類,固然籠統類不克不及經由過程new操作符實例化,
* 然則可以創立籠統類的對象援用指向子類對象,以完成運轉時多態性。詳細的完成辦法同上例。
* 不外,籠統類的子類必需籠罩完成超類中的一切的籠統辦法,
* 不然子類必需被abstract潤飾符潤飾,固然也就不克不及被實例化了
*/
 以上年夜多半是以子類籠罩父類的辦法完成多態.上面是另外一種完成多態的辦法-----------重寫父類辦法

JAVA裡沒有多繼續,一個類之能有一個父類。而繼續的表示就是多態。一個父類可以有多個子類,而在子類裡可以重寫父類的辦法(例如辦法print()),如許每一個子類裡重寫的代碼紛歧樣,天然表示情勢就紛歧樣。如許用父類的變量去援用分歧的子類,在挪用這個雷同的辦法print()的時刻獲得的成果和表示情勢就紛歧樣了,這就是多態,雷同的新聞(也就是挪用雷同的辦法)會有分歧的成果。舉例解釋:

//父類 
public class Father{ 
 //父類有一個打孩子辦法 
 public void hitChild(){ 
 } 
} 
//子類1 
public class Son1 extends Father{ 
 //重寫父類打孩子辦法 
 public void hitChild(){ 
  System.out.println("為何打我?我做錯甚麼了!"); 
 } 
} 
//子類2 
public class Son2 extends Father{ 
 //重寫父類打孩子辦法 
 public void hitChild(){ 
  System.out.println("我曉得錯了,別打了!"); 
 } 
} 
//子類3 
public class Son3 extends Father{ 
 //重寫父類打孩子辦法 
 public void hitChild(){ 
  System.out.println("我跑,你打不著!"); 
 } 
} 

//測試類 
public class Test{ 
 public static void main(String args[]){ 
  Father father; 

  father = new Son1(); 
  father.hitChild(); 

  father = new Son2(); 
  father.hitChild(); 

  father = new Son3(); 
  father.hitChild(); 
 } 
} 

都挪用了雷同的辦法,湧現了分歧的成果!這就是多態的表示!

import java.io.*;
class Super{
  Super(){
    System.out.println("This is super class!");
  }
  void method(){
    System.out.println("Super's method");
  }
}
class Sub extends Super{
  Sub(){
    super();
    System.out.println("\n\t:and here is the child");
  }
  void method(){
    System.out.println("child's method");
  }
}


public class Super_Sub{
  public static void main(String[] args){
    Super sup=new Sub();
    sup.method();


    Sub child=(Sub)new Super();//這裡,現實分派的內存是Super的,然則卻用Child來指代它,這就是“向下轉型”(父類假裝子類,由於子類在UML中畫時是鄙人的嘛),必經強迫類型轉換
    child.method();
  }
}

關於數據來講,繼續能否為准確的設計可以用一個簡略的規矩來斷定。“is-a”規矩注解子類的每個對象都是一個超類的對象。例如,每個司理是一個員工。但是,只要司理類是員工類的子類才是成心義的。很顯著,反過去就不可了——其實不是每一個員工都是司理。

    還有一個明白論述“is-a”規矩的辦法是替換准繩。該准繩劃定不管什麼時候,假如法式須要一個超類對象,都可以用一個子類對象來取代

靜態綁定
懂得挪用一個對象辦法的機制長短常主要的。上面詳細引見:X.f;

(1)編譯器檢討對象的聲明類型和辦法名。

(2)接著,編譯器檢討辦法挪用中的參數類型。假如在一切的叫做f的辦法中有一個其參數類型同挪用供給的參數類型最婚配,那末該辦法就會被選擇挪用。這個進程稱作超載選擇。(靜態)

(3)當法式運轉而且應用靜態綁定來挪用一個辦法時,那末虛擬機必需挪用同x所指向的對象的現實類型相婚配的辦法版本。


……

假如類中沒有寫結構函數,那末體系會主動為該類供給一個默許結構函數,該結構函數將一切的實例字段初始化為默許值:

……

包用處:


Java許可把多個類搜集在一路成為一組,稱作包(package)。包便於組織義務,和使本身的義務和其別人供給的代碼庫相分別。
   尺度Java庫被分類成很多的包,個中包含java.1ang、java.util和java.net等等。尺度Java包是分條理的。就像在硬盤上嵌套有各級子目次一樣,可以經由過程條理嵌套組織包。一切的Java包都在Java和Javax包條理內

 創立包

曾經看到,已有的庫,好比JavaAPI中的類和接口,可以導入到Java法式中。

Java API中的每個類和接口屬於一個特定的包。它包括一組相干聯的類和接口,現實是對類和接口停止組織的目次構造。

例如,假定文件名是MyClass.java。它意味著在誰人文件有一個、並且只能有一個public類。並且誰人類的名字必需是MyClass(包含年夜小寫情勢):

packagemypackage;

publicclass MyClass

{

……

}

創立可復用的類的步調扼要解釋以下:
(1)界說一個public類。假如類不是public,它只能被統一包中的其他類應用。
(2)選擇一個包名,並把package語句加到可復用的類的源代碼文件中。
(3)編譯這個類。如許,它就被放到恰當的包目次構造中,以供編譯器息爭譯器應用。
(4)把這個可復用的類導入到須要用它的法式中。如今便可以應用它了。
留意 在Java說話中可以湧現在類界說的括號裡面的唯一兩個語句,它們是package和import。

包援用---每一個類名前加上完全的包名
例如,給出一個指向此包中的類的快捷方法。一旦應用import(導入)了今後,就不再須要給出完全的包名。

可以引入一個特定的類,也能夠引入全部包。import語句要放在源文件的頭部(但在一切package語句的上面)。例如,可以經由過程上面的語句引入在java.util包中的一切的類:

importjava.util.*;

然後,便可以應用

Datetoday=new Date();

而不須要在後面加上包名。也能夠引入包中某個特定的類:

importjava.util.Date;

要把類放人一個包中,必需把此包的名字放在源文件頭部,而且放在對包中的類停止界說的代碼之前。例如,在文件Employee.java的開端部門以下:

packagecom.horstmann.corejava;

publicclass Employee

{

……

}

把包中的文件放入與此完全的包名相婚配的子目次中。例如,在包com.horstmann.corejava中的一切的類文件都必需放在子目次com/horstmann/core.java(Windows下的com\horstmann\corejava)下。這是最簡略的一種辦法

類被存儲在文件體系的子目次中。類的途徑必需與地點包名相婚配。

在後面的例子中,包目次com/horstmann/corejava是法式目次的一個子目次。但是如許支配很不靈巧。普通,有多個法式須要拜訪包文件。為了使包可以在多個法式間同享,須要做以下工作:

1)把類放在一個或多個特定的目次中,好比/home/user/classdir。此目次是包樹的根本目次。假如參加了類com.horstmann.corejava.Employee,那末此類文件必需位於子目次/home/user/classdir/com/horstmann/corejava下。

2)設置類途徑。類途徑是其子目次包括類文件的一切根本目次的聚集。classpath


曾經接觸過public和private拜訪指導符。

被標志為Public的部件可以被任何類應用,而公有部件只能被界說它們的類應用。假如沒有指定public或private,那末部件(即類、辦法或變量)可以被統一個包中的一切辦法拜訪。


Java API包
為了簡化面向對象的編程進程,Java體系事前設計並完成了一些表現了經常使用功效的尺度類,如用於輸出/輸入的類,用於數學運算的類,用於圖形用戶界面設計的類,用於收集處置的類等。這些體系尺度類依據完成的功效分歧,可以劃分紅分歧的聚集,每一個聚集是一個包,合稱為類庫。可以援用這些包,也能夠創立本身的包。

  Java的類庫是體系供給的已完成的尺度類的聚集,是Java編程的API,它可以贊助開辟者便利、快捷地開辟Java法式

接口重要感化是可以贊助完成相似於類的多重繼續的功效。在Java中,出於簡化法式構造的斟酌,不再支撐類間的多重繼續而只支撐單重繼續,即一個類至少只能有一個直接父類。但是在處理現實成績的進程中,僅僅依附單重繼續在許多情形下都不克不及將成績的龐雜性表述完全,須要其他的機制造為幫助。


接口聲明
Java中聲明接口的語法以下:

[public] interface 接口名 [extends 父接口名列表]

{ //接口體;

//常量域聲明

 [public] [static] [final] 域類型 域名=常量值;

 //籠統辦法聲明

 [public] [abstract] 前往值 辦法名(參數列表) [throw異常列表];

}

從下面的語律例定可以看出,界說接口與界說類異常類似,現實上完整可以把接口懂得成為一種特別的類,接口是由常量和籠統辦法構成的特別類

(1)接口中的屬性都是用final潤飾的常量,
(2)接口中的辦法都是用abstract潤飾的籠統辦法,在接口中只能給出這些籠統辦法的辦法名、前往值和參數列表,而不克不及界說辦法體,即僅僅劃定了一組信息交流、傳輸和處置的“接口”

 接口的完成

一個類要完成某個或某幾個接口時,有以下的步調和留意事項:

(1)在類的聲明部門,用implements症結字聲明該類將要完成哪些接口;

  以下:

 class類名implements接口{

 

}

(2)假如完成某接口的類不是abstract的籠統類,則在類的界說部門必需完成指定接口的一切籠統辦法,即為一切籠統辦法界說辦法體,並且辦法頭部門應當與接口中的界說完整分歧,即有完整雷同的前往值和參數列表;

(3)假如完成某接口的類是abstract的籠統類,則它可以不完成該接口一切的辦法。

(4)一個類在完成某接口的籠統辦法時,必需應用完整雷同的辦法頭。

(5)接口的籠統辦法,其拜訪限制符都已指定是public,所以類在完成辦法時,必需顯式地應用public潤飾符。

小結:

多重繼續是指一個子類繼續多個父類。Java不支撐多重繼續,但Java供給了接口。

子類不克不及拜訪父類的private成員,但子類可以拜訪其父類的public,protected和包拜訪成員;要拜訪父類的包拜訪成員,子類必定要在父類的包內。

子類結構函數老是先挪用(顯式的或隱式地)其父類的結構函數,以創立和初始化子類的父類成員。

子類的對象可以看成其父類的對象看待,反之則不可(即向上轉型)

protected拜訪是public和private拜訪之間一個掩護性的中央條理。父類辦法、子類辦法和在統一個包內類的辦法都能拜訪父類的protected成員,但其他辦法均不克不及拜訪

一個子類對象援用可以隱式地轉換成一個父類對象援用。應用顯式的類型轉換,可以把父類援用轉換成子類援用。假如目的不是子類對象,將發生ClassCastException破例處置。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved