C++跟Java的相關(guān)比較.docx_第1頁
C++跟Java的相關(guān)比較.docx_第2頁
C++跟Java的相關(guān)比較.docx_第3頁
C++跟Java的相關(guān)比較.docx_第4頁
C++跟Java的相關(guān)比較.docx_第5頁
已閱讀5頁,還剩51頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

C+與Java比較.doc概括 JAVA的優(yōu)勢:跨平臺;開源;有甲骨文,ibm等大公司的強力支持;簡單易學(xué),語法規(guī)則。 C+最大的優(yōu)勢在于她的通用和全面。 JAVA和C+都是面向?qū)ο笳Z言。也就是說,它們都能夠?qū)崿F(xiàn)面向?qū)ο笏枷?封裝,繼乘,多態(tài))。而由于c+為了照顧大量的C語言使用者,而兼容了C,使得自身僅僅成為了帶類的C語言,多多少少影響了其面向?qū)ο蟮膹氐仔訨AVA則是完全的面向?qū)ο笳Z言,它句法更清晰,規(guī)模更小,更易學(xué)。它是在對多種程序設(shè)計語言進行了深入細致研究的基礎(chǔ)上,摒棄了其他語言的不足之處,從根本上解決了c+的固有缺陷。 Java和c+的相似之處多于不同之處,但兩種語言有幾處主要的不同使得Java更容易學(xué)習(xí),并且編程環(huán)境更為簡單。 我在這里不能完全列出不同之處,僅列出比較顯著的區(qū)別: 1(指針 JAVA語言讓編程者無法找到指針來直接訪問內(nèi)存無指針,并且增添了自動的內(nèi)存管理功能,從而有效地防止了c,c+語言中指針操作失誤,如野指針所造成的系統(tǒng)崩潰。但也不是說JAVA沒有指針,虛擬機內(nèi)部還是使用了指針,只是外人不得使用而已。這有利于Java程序的安全。 2(多重繼承 c+支持多重繼承,這是c+的一個特征,它允許多父類派生一個類。盡管多重繼承功能很強,但使用復(fù)雜,而且會引起許多麻煩,編譯程序?qū)崿F(xiàn)它也很不容易。Java不支持多重繼承,但允許一個類繼承多個接口(extends+implement),實現(xiàn)了c+多重繼承的功能,又避免了c+中的多重繼承實現(xiàn)方式帶來的諸多不便。 3(數(shù)據(jù)類型及類 Java是完全面向?qū)ο蟮恼Z言,所有函數(shù)和變量都必須是類的一部分。除了基本數(shù)據(jù)類型之外,其余的都作為類對象,包括數(shù)組。對象將數(shù)據(jù)和方法結(jié)合起來,把它們封裝在類中,這樣每個對象都可實現(xiàn)自己的特點和行為。而c+允許將函數(shù)和變量定義為全局的。此外,Java中取消了c,c+中的結(jié)構(gòu)和聯(lián)合,消除了不必要的麻煩。 4(自動內(nèi)存管理 Java程序中所有的對象都是用new操作符建立在內(nèi)存堆棧上,這個操作符類似于c+的new操作符。下面的語句由一個建立了一個類Read的對象,然后調(diào)用該對象的work方法: Read r,new Read(); r.work(); 語句Read r,new Read();在堆棧結(jié)構(gòu)上建立了一個Read的實例。Java自動進行無用內(nèi)存回收操作,不需要程序員進行刪除。而c十十中必須由程序員釋放內(nèi)存資源,增加了程序設(shè)計者的負擔(dān)。Java中當一個對象不被再用到時,無用內(nèi)存回收器將給它加上標簽以示刪除。JAVA里無用內(nèi)存回收程序是以線程方式在后臺運行的,利用空閑時間工作。 5(操作符重載 Java不支持操作符重載。操作符重載被認為是c十十的突出特征,在Java中雖然類大體上可以實現(xiàn)這樣的功能,但操作符重載的方便性仍然丟失了不少。Java語言不支持操作符重載是為了保持Java語言盡可能簡單。 6(預(yù)處理功能 Java不支持預(yù)處理功能。c,c十十在編譯過程中都有一個預(yù)編澤階段,即眾所周知的預(yù)處理器。預(yù)處理器為開發(fā)人員提供了方便,但增加了編譯的復(fù)雜性。JAVA虛擬機沒有預(yù)處理器,但它提供的引入語句(import)與c十十預(yù)處理器的功能類似。 7. Java不支持缺省函數(shù)參數(shù),而c十十支持 在c中,代碼組織在函數(shù)中,函數(shù)可以訪問程序的全局變量。c十十增加了類,提供了類算法,該算法是與類相連的函數(shù),c十十類方法與Java類方法十分相似,然而,由于c十十仍然支持c,所以不能阻止c十十開發(fā)人員使用函數(shù),結(jié)果函數(shù)和方法混合使用使得程序比較混亂。 Java沒有函數(shù),作為一個比c十十更純的面向?qū)ο蟮恼Z言,Java強迫開發(fā)人員把所有例行程序包括在類中,事實上,用方法實現(xiàn)例行程序可激勵開發(fā)人員更好地組織編碼。 8 字符串 c和c十十不支持字符串變量,在c和c十十程序中使用Null終止符代表字符串的結(jié)束,在Java中字符串是用類對象(string和stringBuffer)來實現(xiàn)的,這些類對象是Java語言的核心,用類對象實現(xiàn)字符串有以下幾個優(yōu)點: (1)在整個系統(tǒng)中建立字符串和訪問字符串元素的方法是一致的; (2)Java字符串類是作為Java語言的一部分定義的,而不是作為外加的延伸部分; (3)Java字符串執(zhí)行運行時檢空,可幫助排除一些運行時發(fā)生的錯誤; (4)可對字符串用“十”進行連接操作。 9 goto語句 “可怕”的goto語句是c和c+的“遺物”,它是該語言技術(shù)上的合法部分,引用goto語句引起了程序結(jié)構(gòu)的混亂,不易理解,goto語句子要用于無條件轉(zhuǎn)移子程序和多結(jié)構(gòu)分支技術(shù)。鑒于以廣理由,Java不提供goto語句,它雖然指定goto作為關(guān)鍵字,但不支持它的使用,使程序簡潔易讀。 l0(類型轉(zhuǎn)換 在c和c十十中有時出現(xiàn)數(shù)據(jù)類型的隱含轉(zhuǎn)換,這就涉及了自動強制類型轉(zhuǎn)換問題。例如,在c十十中可將一浮點值賦予整型變量,并去掉其尾數(shù)。Java不支持c十十中的自動強制類型轉(zhuǎn)換,如果需要,必須由程序顯式進行強制類型轉(zhuǎn)換。 11.異常 JAVA中的異常機制用于捕獲例外事件,增強系統(tǒng)容錯能力 try,可能產(chǎn)生例外的代碼 catch(exceptionType name) /處理 其中exceptionType表示異常類型。而C+則沒有如此方便的機制。 Java并不僅僅是C+語言的一個變種,它們在某些本質(zhì)問題上有根本的不同: (1)Java比C+程序可靠性更高。有人曾估計每50行C+程序中至少有一個BUG.姑且不去討論這個數(shù)字是否夸張,但是任何一個C+程序員都不得不承認C+語言在提供強大的功能的同時也提高了程序含BUG的可能性。Java語言通過改變語言的特性大大提高了程序的可靠性。 (2)Java語言不需要程序?qū)?nèi)存進行分配和回收。Java丟棄了C+ 中很少使用的、很難理解的、令人迷惑的那些特性,如操作符重載、多繼承、自動的強制類型轉(zhuǎn)換。特別地,Java語言不使用指針,并提供了自動的廢料收集,Examda提示: 在Java語言中,內(nèi)存的分配和回收都是自動進行的,程序員無須考慮內(nèi)存碎片的問題。 (3)Java語言中沒有指針的概念,引入了真正的數(shù)組。不同于C+中利用指針實現(xiàn)的“偽數(shù)組”,Examda,Java引入了真正的數(shù)組,同時將容易造成麻煩的指針從語言中去掉,這將有利于防止在c+程序中常見的因為數(shù)組操作越界等指針操作而對系統(tǒng)數(shù)據(jù)進行非法讀寫帶來的不安全問題。 (4)Java用接口(Interface)技術(shù)取代C+程序中的多繼承性。接口與多繼承有同樣的功能,但是省卻了多繼承在實現(xiàn)和維護上的復(fù)雜性。 工作中造成的影響是: 1.C+開發(fā)成本高,C+是微軟支持的,比如做一個WEB網(wǎng)站,那么首先你要購買正版的WINDOW系統(tǒng),加上正版的WEB服務(wù)器。這可是筆不小的開銷。JAVA的話,操作系統(tǒng)可以使用免費的LINUX,服務(wù)器有免費的,當然也有收費的??傮w來收開銷要遠小于C+的.net。 2.C+比JAVA快,當然這不是絕對的。如果你熟悉JAVA的工作原理就明白了。JAVA是在原有的系統(tǒng)再添加一層虛擬機運行的。而C+會有微軟支持(操作系統(tǒng)級別的支持,且無任何中間機制,所以速度要快)。這也就是為什么游戲大部分是采用C+開發(fā)的原因。不過隨著硬件的速度越來越快,這點最終會被克服。 細微上的區(qū)別 一、基本程序設(shè)計結(jié)構(gòu): Java的基本程序結(jié)構(gòu)、關(guān)鍵字、操作符都和C/C+非常相似,以下為主要的幾點區(qū)別: 1. Java的原始數(shù)值型數(shù)據(jù)類型中不包含無符號類型,如c中的unsigned int。 2. 在進行移位運算時,當向左邊移動時,如1 35, 對于int類型,由于其占有4個bytes(32bits), 因此在Java中,大于32的移位將對32取模,即1 35的結(jié)果等于1 = 0: ); 7 n = in.nextInt(); 8 if (n 0) 9 break read_data; 10 11 12 /下面的代碼將會被立即執(zhí)行,當break跳出最外層的循環(huán)之后。 13 if (n 0) 14 . 15 else 16 . 17 18 5. Java中支持0長度的數(shù)組定義,如int et = new int0; 在C/C+中,該寫法將會導(dǎo)致編譯錯誤。 6. 多維數(shù)組的兩種常用訪問方式。 1 public static void main(String args) 2 int magicSquare = 3 4 16,3,2,13, 5 5,10,11,8, 6 9,6,7,12, 7 4,15,14,1 8 ; 9 / 通過普通的for循環(huán)訪問 10 for (int i = 0; i magicSquare.length; +i) 11 for (int j = 0; j magicSquarei.length; +j) 12 System.out.printf(%s ,magicSquareij); 13 14 System.out.println(); 15 16 / 通過普通的for each循環(huán)訪問17 for (int row : magicSquare) 18 for (int col : row) 19 System.out.printf(%s ,col); 20 21 System.out.println(); 22 23 24 /*兩次輸出結(jié)果均為: 25 16 3 2 13 26 5 10 11 8 27 9 6 7 12 28 4 15 14 1 */ 7. Java中的不規(guī)則二維數(shù)組。 1 public void foo() 2 int odds = new intNMAX+1; 3 for (int n = 0; n = NMAX; +n) 4 oddsn = new intn + 1; 5 6 for (int n = 0; n odds.length; +n) 7 for (int k = 0; k oddsn.length; +k) 8 oddsnk = n * k; 9 10 C/C+中對應(yīng)于Java的不規(guī)則二維數(shù)組的表示方式。 1 void foo() 2 int* odds = new int*10; 3 for (int n = 0; n 10; +n) 4 if (n = 0) 5 oddsn = new int; 6 else 7 oddsn = new intn + 1; 8 9 10 for (int n = 0; n 10; +n) 11 for (int k = 0; k n + 1; +k) 12 oddsnk = n * k; 13 14 /注:C/C+代碼部分需要自行釋放分配的內(nèi)存。 15 for (int n = 0; n 10; +n) 16 if (n = 0) 17 delete oddsn; 18 else 19 delete oddsn; 20 21 delete odds; 22 二、對象與類: 1. Java對象實例的存儲方式: 所有的Java對象實例都是通過new的方式創(chuàng)建的,如Employee employee = new Employee()。而此時創(chuàng)建的employee對象實例,實際是指向Employee對象的一個實例的引用,主要體現(xiàn)為實例之間基于等號的賦值,如:employee = employee2; 賦值后兩個變量將指向同一個Employee對象實例。Java處理對象變量的方式和C+中的引用比較類似,但是還是存在一定的差異,首先C+不存在空引用,既引用變量定義時也必須被同時聲明其所引用的對象實例,再者就是引用一旦定義時初始化后就不能再被重新賦值了。因此這里可以將Java的對象變量看做C+中的對象指針,如:BirthdayDate d; /*Java*/ 等同于 BirthdayDate* d; /*C+*/。 與Java對象實例聲明的方式相同,C+中的對象指針也是通過new的方式進行初始化的,如BirthdayDate* d = new BirthdayDate. 同樣可以將C+中的對象指針賦值為NULL,也可以將其重新賦值指向另外一個對象實例。與Java相同,通過new操作符創(chuàng)建的對象實例是存儲在堆中的,不同的是,Java的對象在創(chuàng)建后,無需開發(fā)人員在去關(guān)注該對象實例需要合適被釋放,所有的操作均有Java虛擬機中提供的垃圾回收機制自動完成。而C+中的該類對象,則需要開發(fā)人員通過調(diào)用delete操作符來自行完成釋放,如果忘記釋放將會產(chǎn)生內(nèi)存泄露。在C+中,不僅可以將對象存儲在堆上,同樣也可以定義并存儲的棧上,如BrithdayDate d; 該對象實例不需要手工釋放,在棧退出時將自動釋放該對象的存儲空間,同時也會調(diào)用該對象的析構(gòu)函數(shù)。 2. Java對象方法的顯式參數(shù)和隱式參數(shù): 1 public class Employee 2 public void raiseSalary(double byPercent) 3 double raise = salary + byPercent / 100; 4 salary += raise; 5 6 private double salary; 7 raiseSalary是Employee類的一個成員方法,該方法是由兩個參數(shù)構(gòu)成,一個是顯式參數(shù)byPercent,另一個則是隱式參數(shù)this,既raiseSalary方法是實現(xiàn)體可以改為: 1 public void raiseSalary(double byPercent) 2 double raise = this.salary + byPercent / 100; 3 this.salary += raise; 4 這里的隱式參數(shù)this表示當前調(diào)用raiseSalary方法的對象實例的自身,該機制和C+基本相同。 注:靜態(tài)方法中不存在該特征。 3. Java對象中定義的final實例域,如:public class Employee . private final String name; , 該類型的field必須在對象構(gòu)造函數(shù)中進行初始化,之后該變量將不能再被重新賦值。和final字段相似,C+對象中的const成員變量也必須在對象構(gòu)造函數(shù)的初始化列表中完成賦值任務(wù),在之后的使用中該字段將不會再被修改,否則會產(chǎn)生編譯錯誤。對于Java的final域而言,以便應(yīng)用于基本數(shù)據(jù)類型,如int,double等,或者不可變類型,如String。對于可變類型而言,final修飾符可能會造成某些預(yù)料之外的混亂,如 private final Date hiredate; 當該field作為某個get方法的返回值返回給調(diào)用者之后,final的修飾作用只能保證返回后的date對象不能再被重新賦值并指向新的對象實例引用,但是可以通過直接修改返回值對象的自身數(shù)據(jù)來破壞對象的封裝性,從而可能造成數(shù)據(jù)的非法性,或者狀態(tài)的不一致性。 4. 函數(shù)參數(shù)傳遞的方式:傳值和傳引用。 在Java中調(diào)用函數(shù)是,參數(shù)都是通過傳值的方式傳遞到函數(shù)內(nèi)部,然而根據(jù)參數(shù)類型的不同,其表現(xiàn)仍然存在一定的差異。主要總結(jié)為以下3點: 被調(diào)用方法不能修改一個基本數(shù)據(jù)類型的參數(shù),如:int,double,boolean等,見如下代碼: 1 private static void tripleValue(double x) 2 x *= 3; 3 System.out.println(End of method: x = + x); 4 5 6 public static void testTripleValue() 7 System.out.println(Test tripleValue); 8 double percent = 10; 9 System.out.println(Before: percent = + percent); 10 tripleValue(percent); 11 System.out.println(After: percent = + percent); 12 13 /* 結(jié)果如下: 14 Test tripleValue 15 Before: percent = 10.0 16 End of method: x = 30.0 17 After: percent = 10.0 */ 被調(diào)用方法可以改變一個對象參數(shù)的狀態(tài),見如下代碼: 1 private static void tripleSalary(Employee x) 2 x.raiseSalary(200); 3 System.out.println(End of method: salary = + x.getSalary(); 4 5 6 public static void testTripleSalary() 7 System.out.println(Test tripleSalary); 8 Employee harry = new Employee(Harry,50000); 9 System.out.println(Before: salary = + harry.getSalary(); 10 tripleSalary(harry); 11 System.out.println(After: salary = + harry.getSalary(); 12 13 /* 結(jié)果如下: 14 Test tripleSalary 15 Before: salary = 50000.0 16 End of method: x = 150000.0 17 After: salary = 150000.0 */ 被調(diào)用方法不能實現(xiàn)讓對象參數(shù)引用一個新的對象,見如下代碼: 1 private static void swap(Employee a,Employee b) 2 Employee temp = x; 3 x = y; 4 y = temp; 5 System.out.println(End of method: x = + x.getName(); 6 System.out.println(End of method: y = + y.getName(); 7 8 public static void testSwap() 9 System.out.println(Test Swap); 10 Employee a = new Employee(Alice,70000); 11 Employee b = new Employee(Bob,60000); 12 System.out.println(Before: a = + a.getName(); 13 System.out.println(Before: b = + b.getName(); 14 swap(a,b); 15 System.out.println(After: a = + a.getName(); 16 System.out.println(After: b = + b.getName(); 17 18 /* 結(jié)果如下: 19 Test swap 20 Before: a = Alice 21 Before: b = Bob 22 End of method: x = Bob 23 End of method: y = Alice 24 After: a = Alice 25 After: b = Bob */ C+有值調(diào)用和引用調(diào)用,引用參數(shù)標有&符號。如:void tripleValue(double& x)或void swap(Employee& x,Employee& y)方法實現(xiàn)修改他們引用參數(shù)的目的,既該方法執(zhí)行完成后,調(diào)用函數(shù)的參數(shù)變量的值將發(fā)生改變。 5. 對象的構(gòu)造和構(gòu)造函數(shù): 在Java中如果一個class沒有定義任何構(gòu)造函數(shù),Java編譯器將自動生成一個缺省的構(gòu)造函數(shù),沒有任何參數(shù),其行為只是按照Java默認的方式初始化該類的所有域變量,如數(shù)值型為0,布爾為false,對象則為null。但是如果該class定義了自己的構(gòu)造函數(shù),那么缺省構(gòu)造函數(shù)將不會被自動生成,再試圖調(diào)用自動生成的缺省構(gòu)造函數(shù)將會導(dǎo)致編譯錯誤。該行為和C+完全一致。但是Java提供了另外一種域變量初始化方式,如下: 1 public class Employee 2 . 3 private String name = ; /直接賦值 4 private int id = assignId();/通過調(diào)用域方法完成初始化。 5 在C+中不能直接在類的定義中以任何形式直接初始化成員變量。但是C+提供了在構(gòu)造函數(shù)中以初始化列表的方式完成成員變量對象的初始化,特別是const成員,必須在這里賦值。 通過一個構(gòu)造器調(diào)用另一個構(gòu)造器從而完成域變量的初始化和部分代碼復(fù)用。通過this關(guān)鍵字(或稱隱式參數(shù))作為函數(shù)名,然后傳入?yún)?shù)調(diào)用你期望的另一個構(gòu)造函數(shù),注:this被調(diào)用之前不能執(zhí)行任何其他的code。 1 public Employee(double s) 2 /calls Employee(String,double) 3 this(Employee # + nextId,s); 4 +nextId; 5 在C+中如果打算完成此功能,必須將構(gòu)造函數(shù)的部分邏輯抽取出來,以便讓多個構(gòu)造函數(shù)去調(diào)用,然后不同的構(gòu)造函數(shù)之間不能直接調(diào)用。 在Java定義的子類中,如果子類的構(gòu)造函數(shù)不是調(diào)用父類的缺省構(gòu)造函數(shù),則需要在子類構(gòu)造函數(shù)的第一行代碼中指定欲調(diào)用的父類構(gòu)造函數(shù),該調(diào)用需要通過super關(guān)鍵字來完成。見如下代碼: 1 public class MyFirst 2 public static void main(String args) 3 BaseClass bc1 = new SonClass(); 4 BaseClass bc2 = new SonClass(5); 5 6 7 8 class BaseClass 9 public BaseClass() 10 System.out.println(This is BaseClass); 11 12 13 public BaseClass(int i) 14 System.out.println(This is BaseClass with i.); 15 16 17 18 class SonClass extends BaseClass 19 public SonClass() 20 System.out.println(This is SonClass); 21 22 23 public SonClass(int i) 24 super(5); 25 System.out.println(This is SonClass with i); 26 27 28 /* 結(jié)果如下: 29 This is BaseClass 30 This is SonClass 31 This is BaseClass with i. 32 This is SonClass with i */ 在C+中也可以完成該種類型的指定,但是必須在子類構(gòu)造函數(shù)的初始化列表中完成對父類指定構(gòu)造函數(shù)的調(diào)用。 1 class BaseClass 2 public: 3 BaseClass() 4 printf(This is BaseClassn); 5 6 7 BaseClass(int i) 8 printf(This is BaseClass with in); 9 10 ; 11 12 class SonClass : public BaseClass 13 public: 14 SonClass() 15 printf(This is SonClassn); 16 17 18 SonClass(int i) : BaseClass(i) 19 printf(This is SonClass with in); 20 21 ; 22 23 int main() 24 25 BaseClass* bc1 = new SonClass; 26 BaseClass* bc2 = new SonClass(5); 27 delete bc1; 28 delete bc2; 29 return 0; 30 31 /* 結(jié)果如下: 32 This is BaseClass 33 This is SonClass 34 This is BaseClass with i. 35 This is SonClass with i */ 在Java的域變量初始化方法中存在初始化塊的方式,既除聲明即初始化、構(gòu)造函數(shù)初始化之外的第三種域變量初始化方式。在一個類的聲明中可以存在多個代碼塊,只要構(gòu)造類的對象,這些塊就會被執(zhí)行,然后再運行類的構(gòu)造函數(shù)。靜態(tài)域變量可以在靜態(tài)初始化塊中完成初始化的工作,但是該初始化塊只是在類第一次加載時被執(zhí)行一次,之后都將不再被執(zhí)行。見如下代碼: 1 class Employee 2 public Employee(String n,double s) 3 name = n; 4 salary = s; 5 6 7 . 8 9 private static int nextId; 10 private int id; 11 private String name; 12 private double salary; 13 14 /object initialization block. 15 16 id = nextId; 17 nextId+; 18 19 20 /static initialization block. 21 static 22 23 Random generator = new Random(); 24 nextId = generator.nextInt(); 25 26 6. C+的對象析構(gòu)和Java對象的finalize方法: C+是有顯式的析構(gòu)方法,其中放置一些當對象不再使用時需要執(zhí)行的清理代碼。在析構(gòu)函數(shù)中,最常見的操作時回收分配給對象的存儲空間,系統(tǒng)資源等。有Java有自動的垃圾回收器,不需要人工回收內(nèi)存,所以Java并不支持析構(gòu)函數(shù)。如果打算在Java的代碼中完成類似的工作,可以通過為該類添加finalize方法,該方法將會在垃圾收集器清除對象之前調(diào)用,在實際應(yīng)用中,不要依賴于使用finalize方法回收任何短缺的資源,這是因為很難知道這個方法什么時候才能調(diào)用。如果某個資源確實需要在使用完畢后立刻關(guān)閉,那么就需要由人工來管理??梢詰?yīng)用一個類似dispose或close的方法完成相應(yīng)的清理操作。特別需要說明,如果一個類使用了這樣的方法,當對象不再被使用時一定要調(diào)用它。 7. Java的包 vs C+的名字空間 他們具有極為相同的只能,即防止名字污染。當一個應(yīng)用程序中存在多個第三方組件,那么不同組件中命名了相同名稱的類將是極為可能發(fā)生的,如Java中的Date類,在java.util和java.sql中均存在該名稱的類的聲明。為了有效的防止名字污染,C+中采用了namespace和using namespace的指令來明確定義某個類具體所位于的具體位置,Java中則采用了package和import語句。 Java在Java SE5.0 開始,import語句不僅可以導(dǎo)入類,還增加了導(dǎo)入靜態(tài)方法和靜態(tài)域的功能。如import static java.lang.System.*。在完成該靜態(tài)導(dǎo)入之后,就可以在剩下的代碼中直接使用System類的靜態(tài)方法和靜態(tài)域了,如out.println();exit(0)。該技巧主要用于帶有較長名稱的常量,如if (d.get(DAY_OF_WEEK) = MONDAY) .,看起來比if (d.get(Calendar.DAY_OF_WEEK) = Calendar.MONDAY) .要容易的多。 三、繼承: 1. Java和C+在對象繼承方面的主要差異: 對象的繼承性是所有面向?qū)ο笳Z言都支持的面向?qū)ο筇匦灾?,Java和C+作為兩個重要的面向?qū)ο箝_發(fā)語言在此方面有著較多的相似性,但是在有些概念的表示方式上還是存在著一定的差異,先列舉如下: 1) 對象繼承的關(guān)鍵字,Java中采用extents關(guān)鍵字,如class DeriveClass extends BaseClass, 在C+中則使用(:)冒號表示類之間的繼承,如class DeriveClass : public BaseClass。 2) Java的繼承方式中不存在public,protected和private,其表現(xiàn)行為和C+中的public繼承完全一致。 3) 在有些情況下,子類中的方法需要顯式的調(diào)用超類中的方法實現(xiàn),特別是當子類中也存在同樣方法簽名的實現(xiàn)時,如果沒有明確的指出需要調(diào)用超類的方法,Java的編譯器會將子類當前的方法列為本次調(diào)用的候選方法,見如下代碼: 1 class DeriveClass extends BaseClass 2 public double getSalary() 3 double baseSalary = getSalary(); 4 return baseSalary + bonus; 5 6 以上代碼中的getSalary()方法將會遞歸的調(diào)用其自身,而開發(fā)者的實際用意是調(diào)用超類中的getSalary方法,由于超類和子類中具有相同簽名的該方法,因此編譯器在此時選擇了子類中的getSalary。其修改方式如下: 1 class DeriveClass extends BaseClass 2 public double getSalary() 3 double baseSalary = super.getSalary(); 4 return baseSalary + bonus; 5 6 加上關(guān)鍵字super明確的指出要調(diào)用超類中的getSalary方法。在C+中的實現(xiàn)方式為BaseClass:getSalary(),既在方法簽名的前面加上父類的名字和兩個連在一起的冒號(:)。 1 class DeriveClass : public BaseClass 2 public: 3 double getSalary() 4 double baseSalary = BaseClass:getSalary(); 5 return baseSalary + bonus; 6 7 4) Java中所有未聲明為final的方法都視為可以繼承的虛方法。在C+中,盡管沒有此類限制,但是在實際的應(yīng)用中還是存在一些潛在的技巧以達到此效果。對于C+類中聲明的公有成員方法,如果該方法未聲明為virtual,既虛函數(shù),則暗示該類的子類實現(xiàn)者不要在子類中覆蓋(override)該方法。 5) Java中不支持多重繼承,不僅有效的避免了C+因多重繼承而帶來的一些負面影響,與此同時,在Java中可以通過繼承(extends)單個父類和實現(xiàn)(implements)多個接口的方式更好表達該類設(shè)計意愿。 6) Java中如果子類和超類同時包含具有相同簽名的公有域方法,那么在子類中將覆蓋超類中的域方法。這其中的方法簽名只是包括方法名和參數(shù)列表,既參數(shù)的個數(shù)和類型,函數(shù)的返回值不包含在方法簽名中,但是在Java中針對該種方法覆蓋的返回值還是存在一定的限制,既子類中的返回值的類型,或者與超類中該方法的返回值類型相同,或者為其返回類型的子類。C+中沒有此類返回值類型的限制。但是Java的此類限制也會帶來一些潛在的迷惑和危險,見如下代碼: 1 class Employee 2 public Employee getBuddies() . 3 4 5 class Manager extends Employee 6 public Manager getBuddies() . 7 8 9 public static void main(String args) 10 Employee m = new Manager().getBuddies(); 11 /在Java中子類的數(shù)組在復(fù)制給超類的數(shù)組時不需要顯式的轉(zhuǎn)換,就像 12 /子類的實例賦值給超類的實例一樣,也不需要任何顯式的轉(zhuǎn)換。 13 /賦值之后e和m指向相同的內(nèi)存地址,同樣e0和m0也指向相同的實例。 14 Employee e = m; 15 /本次賦值合法也不會引發(fā)任何異常,但是會導(dǎo)致一個潛在的問題,既 16 /m0的對象已經(jīng)被悄悄的改變了,指向了Employee的另外一個子類。 17 e0 = new OtherEmployee(); 18 /此時再調(diào)用m0中Manager定義的域方法時將會引發(fā)Java的運行時異常。 19 m0.setBonus(1000); 20 7) Java中的final類,如果某個自定義類型被加入final關(guān)鍵字,則表示該類將不能被繼承,否則會直接產(chǎn)生編譯錯誤。在C+中沒有特殊的關(guān)鍵字類完成此類限制,然而在實際的應(yīng)用中也同樣存在一些潛在的技巧協(xié)助開發(fā)者來進行此類限制的甄別。如將父類中的析構(gòu)函數(shù)不設(shè)置為虛函數(shù),此方法則間接的暗示子類的實現(xiàn)者要留意,如果仍然繼承該父類,那么在實現(xiàn)多態(tài)時,如BaseClass* c = new DeriveClass,如果之后需要釋放c變量的內(nèi)存資源時 delete c, 此時由于父類中的析構(gòu)函數(shù)并不是虛函數(shù),因此此次調(diào)用將只會執(zhí)行父類的析構(gòu)函數(shù),而不會調(diào)用子類的析構(gòu)函數(shù),最終導(dǎo)致類分割所帶來的一些潛在錯誤或資源泄漏。 8) 內(nèi)聯(lián)方法,在C+中有特殊的關(guān)鍵字inline用于幫助編譯器來推斷是否需要將該方法編譯成內(nèi)聯(lián)方法,以提高運行時的效率。在Java中沒有此類關(guān)鍵字,而是通過編譯器的一連串推演,最終決定該域方法是否可以編譯成內(nèi)聯(lián)方法,主要候選方法為簡短、被頻繁調(diào)用且沒有真正被子類覆蓋的域方法。 9) 超類到子類的強制類型轉(zhuǎn)換。在Java中可以通過直接強轉(zhuǎn)的方式來轉(zhuǎn)換,如Manager m = (Manager)e。如果裝換失敗將會引發(fā)運行時異常ClassCastException,因此很多情況下為了避免此類異常的發(fā)生,需要在強轉(zhuǎn)之前先進行判斷,如if (e instanceof Manager) . , 如果條件為真,裝換將順利完成。在C+中也可以采用這樣的直接強轉(zhuǎn)方法,但是即使類型不匹配程序也不會在強轉(zhuǎn)是引發(fā)任何異常,而是在后面針對該變量的使用時才會導(dǎo)致錯誤的發(fā)生。在C+中存在dynamic_cast關(guān)鍵字,如dynamic_cast和dynamic_cast,前者為基于指針的轉(zhuǎn)換,如果轉(zhuǎn)換失敗返回變量為NULL,而后者則會引發(fā)異常。 10) 抽象類:在Java中如果class被定義為abstract class,該類將不能被實例化,如果子類未能完全實現(xiàn)超類中所有的抽象方法,那么子類也將會被視為抽象類。C+中沒有特殊的關(guān)鍵字來表示抽象類,而且通過將類中的一個或多個方法定義為純虛方法來間接實現(xiàn)的,見如下C+代碼,其中的first和second均為純虛方法,既在方法的尾部添加 = 0 。 1 class AbstractClass 2 public: 3 virtual void first() = 0; 4 virtual void second() = 0; 5 virtual void third(); 6 11) protected關(guān)鍵字在Java和C+中針對域方法和域字段的訪問方式存在著不同的限制級別,相同之處是protected的方法和字段都可以被子類直接訪問,不同之處是Java中相同包中的類也可以直接他們。C+自身并不存在包的概念,然而即便是相同名字空間內(nèi)的對象也不能直接訪問。 2. Object: Java是單根結(jié)構(gòu)的框架,所有的對象都是Object的子類,即使在對象聲明時沒有進行直接的指定,Java的編譯器將會自行搞定這些。C+中沒有適當?shù)念愖鳛樗袑ο蟮母?,然而在有些類庫中可以自行定義,如MFC的CObject等。Java的Object中有3個非常重要的方法equals、hashCode和toString。如果子類中重載了他們中的任意一個方法,同時也建議重載另外兩個域方法。 1) equals: 主要用于判定兩個對象是否相等。類的實現(xiàn)者可以根據(jù)自己的真實邏輯來重新實現(xiàn)該方法,通用實現(xiàn)規(guī)則見下例: 1 public class Employee 2 /1. 顯式參數(shù)命名為otherObject,稍后需要將它轉(zhuǎn)換成另一個叫做other的變量。 3 public boolean equals(Object otherObject) 4 /2. 檢測this與otherObject是否引用同一個對象(一種優(yōu)化) 5 if (this = otherObject) 6 return true; 7 /3. 檢測otherObject是否為null,如果null,則返回false。 8 if (otherObject = null) 9 return false; 10 /4. 比較this與otherObject是否屬于同一個類。 11 /如果子類中的equals語義各不相同,使用下面的getClass方式,精確定義類類型。 12 if (getClass() != otherObject.getClass() 13 return false; 14 /如果子類中的equal語義和超類完全相同,可以使用instanceof檢測即可。 15 /5. 將otherObject轉(zhuǎn)換為相應(yīng)的類類型變量 16 Employee other = (Employee)otherObject; 17 /6. 現(xiàn)在開始對所有需要比較的域進行比較了。其中使用=比較基本類型, /使用equals比較對象類型。 18 return name.equals() & salary = other.salary; 19 20 注:數(shù)組元素的比較可以調(diào)用Arrays.equals方法檢測。如果子類中重新定義了equals方法,就要在其中包含調(diào)用super.equals(other). Java在語言規(guī)范中給出了自定義equals方法需要遵守的規(guī)則: 自反性: 對于任何非空引用x,x.equals(x)應(yīng)該返回true。 對稱性: 對于任何引用x和y,當且僅當y.equals(x)返回true,x.equals(y)也應(yīng)該返回true。 傳遞性: 對于任何引用x,y和z,如果x.equals(y)返回true,y.equals(z)返回

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論