第一篇:二級(jí)JAVA總結(jié)
對(duì)長度為n的線性表進(jìn)行冒泡排序,最壞情況先需要比較的次數(shù)為log2n。
對(duì)長度為n的線性表進(jìn)行順序排序,最壞情況先需要比較的次數(shù)為n。
高內(nèi)聚低耦合有利于模塊的獨(dú)立性。
二叉樹屬于非線性結(jié)構(gòu)。
算法具有可行性、確定性、有窮性和擁有足夠的情報(bào)四個(gè)基本特征。
JAVA的反匯編命令是javap。
軟件(程序)調(diào)試的任務(wù)是診斷和改正程序中的錯(cuò)誤。
數(shù)據(jù)庫應(yīng)用系統(tǒng)中的核心問題是數(shù)據(jù)庫設(shè)計(jì)。
在JAVA中,線程是搶占式的。
Object是所有類的根。
在軟件開發(fā)中,需求分析階段常使用的工具有數(shù)據(jù)流圖(DFD)、數(shù)據(jù)字典(DD)、判斷樹和判斷表。
關(guān)系數(shù)據(jù)庫管理系統(tǒng)能實(shí)現(xiàn)的專門關(guān)系運(yùn)算包括選擇、投影、連接。
支持子程序調(diào)用的數(shù)據(jù)結(jié)構(gòu)是棧。
init()方法用于初始化Applet ,start()方法用于激活A(yù)pplet,paint()方法執(zhí)行Applet的繪制功能。前序是根—左—右,中序是左—根—右,后序是左—右—根。
JAVA中,負(fù)責(zé)并發(fā)管理的機(jī)制是虛擬機(jī)。
JAVA中單精度常量以f或F結(jié)尾。
軟件工程的理論和技術(shù)性研究的內(nèi)容主要包括軟件開發(fā)技術(shù)和軟件工程管理。
相對(duì)于數(shù)據(jù)庫系統(tǒng),文件系統(tǒng)的主要缺陷有數(shù)據(jù)依賴、數(shù)據(jù)不一致性和冗余性。順序存儲(chǔ)結(jié)構(gòu)的存儲(chǔ)一定是連續(xù)的,鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)的存儲(chǔ)空間不一定是連續(xù)的。結(jié)構(gòu)化程序設(shè)計(jì)的3種基本結(jié)構(gòu)是順序、選擇、重復(fù)。
棧的特點(diǎn)是先進(jìn)后出。隊(duì)列的特點(diǎn)是先進(jìn)先出。有序線性表既可以采用順序存儲(chǔ)結(jié)構(gòu),也可以采用鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)。
數(shù)據(jù)庫設(shè)計(jì)中反映用戶對(duì)數(shù)據(jù)要求的模式是外模式。
對(duì)象具有如下特征:標(biāo)識(shí)唯一性、分類型、多態(tài)性、封裝性和模塊獨(dú)立性。
面向?qū)ο蠓椒ㄖ校^承是指類之間共享屬性和操作的機(jī)制。
類Pane默認(rèn)的布局管理器是FlowLayout。
Frame默認(rèn)的布局管理器是BorderLayout。
第二篇:2018年二級(jí)Java復(fù)習(xí)資料
一、Java的歷史、現(xiàn)狀
1.Java歷史
在上世紀(jì)90年代初,sun公司有一個(gè)叫做Green的項(xiàng)目,目的是為家用消費(fèi)電子產(chǎn)品開發(fā)一個(gè)分布式代碼系統(tǒng),這樣就可以對(duì)家用電器進(jìn)行控制,和它們進(jìn)行信息交流。詹姆斯·高斯林(JamesGosling)等人基于C++開發(fā)一種新的語言O(shè)ak(Java的前身)。Oak是一種用于網(wǎng)絡(luò)的精巧而安全的語言。Sun公司曾依此投標(biāo)一個(gè)交互式電視項(xiàng)目,但結(jié)果是被SGI打敗,Sun打算拋棄Oak。隨著互聯(lián)網(wǎng)的發(fā)展,Sun看到了Oak在計(jì)算機(jī)網(wǎng)絡(luò)上的廣闊應(yīng)用前景,于是改造Oak,在1995年5月以“Java”的名稱正式發(fā)布,從此Java走上繁榮之路。
當(dāng)然提到Java歷史,不得不提的一個(gè)故事就是Java的命名。開始“Oak”的命名是以項(xiàng)目小組辦公室外的樹而得名,但是Oak商標(biāo)被其他公司注冊了,必須另外取一個(gè)名字,傳說有一天,幾位Java成員組的會(huì)員正在討論給這個(gè)新的語言取什么名字,當(dāng)時(shí)他們正在咖啡館喝著Java(爪哇)咖啡,有一個(gè)人靈機(jī)一動(dòng)說就叫Java怎樣,得到了其他人的贊同,于是,Java這個(gè)名字就這樣傳開了。當(dāng)然對(duì)于傳說,了解一下就好了,不必過于認(rèn)真。
2.Java 作為學(xué)習(xí)Java的人士,對(duì)Java歷史上發(fā)生的大事件有一個(gè)了解是應(yīng)該的。
JDK(JavaSoftwareDevelopKit)):Java軟件開發(fā)工具包。JDK是Java的核心,包括了Java運(yùn)行環(huán)境,一系列Java開發(fā)工具和Java基礎(chǔ)的類庫。目前主流的JDK是Sun公司發(fā)布的JDK,除了Sun之外,還有很多公司和組織都開發(fā)了自己的JDK,例如IBM公司開發(fā)的JDK,BEA公司的Jrocket,還有GNU組織開發(fā)的JDK等等。
3.Java特點(diǎn)
簡單地說,Java具有如下特點(diǎn):簡單的、面向?qū)ο蟆⑵脚_(tái)無關(guān)、多線程、分布式、安全、高性能、可靠的、解釋型、自動(dòng)垃圾回收等特點(diǎn)。
這里只解釋一下平臺(tái)無關(guān)和分布式,其余的在后面會(huì)逐步接觸到。
3.1平臺(tái)無關(guān)
所謂平臺(tái)無關(guān)指的是:用Java寫的程序不用修改就可在不同的軟硬件平臺(tái)上運(yùn)行。這樣就能實(shí)現(xiàn)同樣的程序既可以在Windows下運(yùn)行,到了Unix或者Linux環(huán)境不用修改就直接可以運(yùn)行了。Java主要靠Java虛擬機(jī)(JVM)實(shí)現(xiàn)平臺(tái)無關(guān)性。
平臺(tái)無關(guān)性就是一次編寫,到處運(yùn)行:Write Once, Run Anywhere 3.2分布式
分布式指的是:軟件由很多個(gè)可以獨(dú)立執(zhí)行的模塊組成,這些模塊被分布在多臺(tái)計(jì)算機(jī)上,可以同時(shí)運(yùn)行,對(duì)外看起來還是一個(gè)整體。也就是說,分布式能夠把多臺(tái)計(jì)算機(jī)集合起來就像一臺(tái)計(jì)算機(jī)一樣,從而提供更好的性能。
4.Java標(biāo)準(zhǔn)組織——JCP JCP(Java Community Process)是一個(gè)開放的國際組織,成立于 1995 年,主要職能是發(fā)展和更新 Java 技術(shù)規(guī)范、參考實(shí)現(xiàn)(RI)、技術(shù)兼容包(TCK)。Java 技術(shù)和 JCP 兩者的原創(chuàng)者都是 SUN 計(jì)算機(jī)公司。組織成員可以提交 JSR(Java Specification Requests),通過討論、認(rèn)可、審核以后,將進(jìn)入到下一版本的規(guī)范里面。
也就是說 JCP 是目前 Java 技術(shù)發(fā)展事實(shí)上的控制者和領(lǐng)領(lǐng)導(dǎo)者。
二、Java從代碼到運(yùn)行
用一個(gè)圖來描述這個(gè)過程會(huì)比較容易理解:
1.編寫代碼
首先把我們想要計(jì)算機(jī)做的事情,通過 Java 表達(dá)出來,寫成 Java 文件,這個(gè)過程就是編寫代碼的過程。如上圖所示的 Hello.java 文件。
2.編譯
寫完 Java 代碼后,機(jī)器并不認(rèn)識(shí)我們寫的 Java 代碼,需要進(jìn)行編譯成為字節(jié)碼,編譯后的文件叫做 class 文件。如上圖所示的 Hello.class 文件。
3.類裝載ClassLoader 類裝載的功能是為執(zhí)行程序?qū)ふ液脱b載所需要的類。
ClassLoader能夠加強(qiáng)代碼的安全性,主要方式是:把本機(jī)上的類和網(wǎng)絡(luò)資源類相分離,在調(diào)入類的時(shí)候進(jìn)行檢查,因而可以限制任何“特洛伊木馬”的應(yīng)用。
4.字節(jié)碼(byte-code)校驗(yàn)
功能是對(duì) class 文件的代碼進(jìn)行校驗(yàn),保證代碼的安全性。
Java 軟件代碼在實(shí)際運(yùn)行之前要經(jīng)過幾次測試。JVM 將代碼輸入一個(gè)字節(jié)碼校驗(yàn)器以測試代碼段格式并進(jìn)行規(guī)則檢查--檢查偽造指針、違反對(duì)象訪問權(quán)限或試圖改變對(duì)象類型的非法代碼。注意----所有源于網(wǎng)絡(luò)的類文件都要經(jīng)過字節(jié)碼校驗(yàn)器字節(jié)碼校驗(yàn)器對(duì)程序代碼進(jìn)行四遍校驗(yàn),這可以保證代碼符合JVM 規(guī)范并且不破壞系統(tǒng)的完整性。如果校驗(yàn)器在完成四遍校驗(yàn)后未返回出錯(cuò)信息,則下列各點(diǎn)可被保證:
-類符合JVM規(guī)范的類文件格式所有操作代碼的參數(shù)類型將總是正確的對(duì)象域訪問是合法的
5.解釋(Interpreter)可是機(jī)器也不能認(rèn)識(shí) class 文件,還需要被解釋器進(jìn)行解釋,機(jī)器才能最終理解我們所要表達(dá)的東西。
6.運(yùn)行
最后由運(yùn)行環(huán)境中的 Runtime 對(duì)代碼進(jìn)行運(yùn)行,真正實(shí)現(xiàn)我們想要機(jī)器完成的工作。
7.說明
由上面的講述,大家看到,Java通過一個(gè)編譯階段和一個(gè)運(yùn)行階段,來讓機(jī)器最終理解我們想要它完成的工作,并按照我們的要求進(jìn)行運(yùn)行。
在這兩個(gè)階段中,需要我們?nèi)ネ瓿傻木褪蔷幾g階段的工作,也就是說:我們需要把我們想要機(jī)器完成的工作用 Java 語言表達(dá)出來,寫成 Java 源文件,然后把源文件進(jìn)行編譯,形成 class 文件,最后就可以在 Java 運(yùn)行環(huán)境中運(yùn)行了。運(yùn)行階段的工作由 Java平臺(tái)自身提供,我們不需要做什么工作。
三、Java程序設(shè)計(jì)基礎(chǔ)
1.Java編程概況
現(xiàn)在你可以復(fù)習(xí)一下Java語言的背景材料,它的基本結(jié)構(gòu)象C/C++,但任何用面向過程語言編寫過程序的人都可以了解Java語言的大部分結(jié)構(gòu).1.1程序結(jié)構(gòu)
Java語言的源程序代碼由一個(gè)或多個(gè)編譯單元(compilationunit)組成,每個(gè)編譯單元只能包含下列內(nèi)容(空格和注釋除外):*一個(gè)程序包語句(packagestatement)*入口語句(importstatements)*類的聲明(classdeclarations)*界面聲明(interfacedeclarations)每個(gè)Java的編譯單元可包含多個(gè)類或界面,但是每個(gè)編譯單元最多只能有一個(gè)類或者界面是公共的。Java的源程序代碼被編譯后,便產(chǎn)生了Java字節(jié)代碼。Java的運(yùn)行系統(tǒng)工作起來如同一臺(tái)虛擬機(jī)。在當(dāng)前的Java實(shí)現(xiàn)中,每個(gè)編譯單元就是一個(gè)以.java為后綴的文件。每個(gè)編譯單元有若干個(gè)類,編譯后,每個(gè)類生成一個(gè).class文件。.class文件是Java虛擬機(jī)能夠識(shí)別的代碼。
1.2注釋
三種類型如下://注釋一行/*一行或多行注釋*//**文檔注釋**/文檔注釋一般放在一個(gè)變量或函數(shù)定義前,指示在任何自動(dòng)生成文檔系統(tǒng)中調(diào)入。
1.3標(biāo)識(shí)符
變量,函數(shù),類和對(duì)象的名稱都是標(biāo)識(shí)符,程序員需要標(biāo)識(shí)和使用的東西都需要標(biāo)識(shí)符。在Java語言里,標(biāo)識(shí)符以字符或_,$開頭,后面可以包含數(shù)字,標(biāo)識(shí)符是大小寫有區(qū)別的,沒有長度限制。
有效的標(biāo)識(shí)符mynameict_networkHello_sys_path$bill 例子:inta_number;char_onechar;float$bill;1.4數(shù)據(jù)類型
Java使用五種基本類型:integer(整數(shù)),floating(浮點(diǎn)數(shù)),point(指針),Boolean(布爾變量),CharacterorString(字符或字符串)。
integer整數(shù)下邊給出的數(shù)據(jù)表示都是整數(shù)的例子:4,15,089,0xAD00整數(shù)長度數(shù)據(jù)類型表示8bitsbyte16bitsshort32bitsint64bitslong floating浮點(diǎn)數(shù)下邊給出的數(shù)據(jù)表示都是浮點(diǎn)數(shù)的例子:6.37,3.7E15,3e8 浮點(diǎn)數(shù)長度數(shù)據(jù)類型表示32bitsfloat64bitsdouble Boolean布爾變量下邊是布爾變量的兩種可能取值:
truefalseCharacter字符下邊給出的都是字符的例子:a(tab)u(unicode)String字符串下邊給出的都是字符串的例子:
“Thisisastringliteral”“中國科學(xué)院計(jì)算所”數(shù)組你可以定義任意類型的數(shù)組.chars[];這是字符型數(shù)組;int[]array;這是整型數(shù)組;你還可以定義數(shù)組的數(shù)組.intblock[][]=newint[2][3];數(shù)組邊界在運(yùn)行時(shí)被檢測,避免堆棧溢出和內(nèi)存崩潰.在Java里,數(shù)組實(shí)際上是一個(gè)對(duì)象,數(shù)組有一個(gè)成員變量: length。你可以用這個(gè)成員函數(shù)來查看任意數(shù)組的長度.inta[][]=newint[10][3]a.length/*10*/a[0].length/*3*/創(chuàng)建數(shù)組在Java里創(chuàng)建數(shù)組,你可使用兩種基本方法:
創(chuàng)建一個(gè)空數(shù)組:intlist[]=newint[50];或你可以用初始數(shù)值填充數(shù)組.Stringnames[]={“Chenji”,“Yuan”,“Chun”,“Yang”};相當(dāng)于下面功能:Stringnames[];names=newString[4];names[0]=newString(“Chenji”);names[1] =newString(“Yuan”);names[2]=newString(“Chun”);names[3]=newString(“Yang”);在編譯時(shí)你不能象下例那樣創(chuàng)建靜態(tài)數(shù)組。intname[50];//將產(chǎn)生一個(gè)編譯錯(cuò)誤你也不能用new操作去填充一個(gè)沒定義大小的數(shù)組。intname[];for(inti=0;i 1.5表達(dá)式
Java語言的表達(dá)式和C語言非常類似。運(yùn)算符運(yùn)算符(operator)優(yōu)先級(jí)從高到底排列如下:.[]()++--!~instanceof*/%+-==!=&^&&||?:=op=,整數(shù)運(yùn)算符在整數(shù)運(yùn)算時(shí),如果操作數(shù)是long類型,則運(yùn)算結(jié)果是long類型,否則為int類型,絕不會(huì)是byte,short或char型。這樣,如果變量i被聲明為short或byte,i+1的結(jié)果會(huì)是int。如果結(jié)果超過該類型的取值范圍,則按該類型的最大值取模。單目整數(shù)運(yùn)算符是:運(yùn)算符操作-單目非~位補(bǔ)碼++加1--減1++運(yùn)算符用于表示直接加1操作。增量操作也可以用加運(yùn)算符和賦值操作間接完成。++lvalue(表示lvalue+=1,++lvalue也表示lvalue=lvalue+1(只要lvalue沒有副作用)。--運(yùn)算符用于表示減1操作。++和--運(yùn)算符既可以作為前綴運(yùn)算符,也可以做為后綴運(yùn)算符。雙目整數(shù)運(yùn)算符是:運(yùn)算符操作**+加-減*乘/除%取模&位與|位或^位異或=,==和!=產(chǎn)生boolean類型的數(shù)據(jù)。
布爾運(yùn)算符布爾(boolean)變量或表達(dá)式的組合運(yùn)算可以產(chǎn)生新的boolean值。單目運(yùn)算符!是布爾非。雙目運(yùn)算符&,|和^是邏輯AND,OR和XOR運(yùn)算符,它們強(qiáng)制兩個(gè)操作數(shù)求布爾值。為避免右側(cè)操作數(shù)冗余求值,用戶可以使用短路求值運(yùn)算符&&和||。用戶可以使用==和!=,賦值運(yùn)算符也可以用&=、|=、^=。三元條件操作符?:和C語言中的一樣。
浮點(diǎn)運(yùn)算符浮點(diǎn)運(yùn)算符可以使用常規(guī)運(yùn)算符的組合:如單目運(yùn)算符++、--,雙目運(yùn)算符+、-、*和/,以及賦值運(yùn)算符+=,-=,*=,和/=。此外,還有取模運(yùn)算:%和%=也可以作用于浮點(diǎn)數(shù),例如:a%b和a-((int)(a/b)*b)的語義相同。這表示a%b的結(jié)果是除完后剩下的浮點(diǎn)數(shù)部分。只有單精度操作數(shù)的浮點(diǎn)表達(dá)式按照單精度運(yùn)算求值,產(chǎn)生單精度結(jié)果。如果浮點(diǎn)表達(dá)式中含有一個(gè)或一個(gè)以上的雙精度操作數(shù),則按雙精度運(yùn)算,結(jié)果是雙精度浮點(diǎn)數(shù)。數(shù)組運(yùn)算符數(shù)組運(yùn)算符形式如下:
[]可給出數(shù)組中某個(gè)元素的值。合法的取值范圍是從0到數(shù)組的長度減1。取值范圍的檢查只在運(yùn)行時(shí)刻實(shí)。運(yùn)算符以String對(duì)象實(shí)現(xiàn)。運(yùn)算符“+”完成并操作,如果必要?jiǎng)t自動(dòng)把操作數(shù)轉(zhuǎn)換為String型。如果操作數(shù)是一個(gè)對(duì)象,它可定義一個(gè)方法toString()返回該對(duì)象的String方式,例如floata=1.0print(“Thevalueofais”+a+“");+運(yùn)算符用到例子Strings=”a=“+a;+=運(yùn)算符也可以用于String。注意,左邊(下例中的s1)僅求值一次。s1+=a;//s1=s1+a//若a非String型,自動(dòng)轉(zhuǎn)換為String型。對(duì)象運(yùn)算符雙目運(yùn)算符instanceof測試某個(gè)對(duì)象是否是指定類或其子類的實(shí)例。例如:if(myObjectinstanceofMyClass){MyClassanothermyObject=(MyClass)myObject;?}是判定myObject是否是MyClass的實(shí)例或是其子類的實(shí)例。強(qiáng)制和轉(zhuǎn)換Java語言和解釋器限制使用強(qiáng)制和轉(zhuǎn)換,以防止出錯(cuò)導(dǎo)致系統(tǒng)崩潰。整數(shù)和浮點(diǎn)數(shù)之間可以來回
強(qiáng)制轉(zhuǎn)換,但整數(shù)不能強(qiáng)制轉(zhuǎn)換成數(shù)組或?qū)ο蟆?duì)象不能被強(qiáng)制為基本類型。
1.6Java流控制
下面幾個(gè)控制結(jié)構(gòu)是從C語言借鑒的。分支結(jié)構(gòu) if/else分支結(jié)構(gòu)if(Boolean){statemanets;}else{statements;} switch分支結(jié)構(gòu)switch(expr1){caseexpr2:statements;break;caseexpr3:statements;break;default:statements;break;} 循環(huán)結(jié)構(gòu)for循環(huán)結(jié)構(gòu)for(initexpr1;testexpr2;incrementexpr3){statements;} While循環(huán)結(jié)構(gòu)While(Boolean){statements;} Do循環(huán)結(jié)構(gòu)do{statements;}while(Boolean);一般順序控制break[label]continue[label]reutrnexpr;label:statement;for循環(huán)例子下面是一個(gè)程序例子,畫幾條線,分別用紅,綠,藍(lán)顏色,這段程序可能是Java函數(shù)的一部分:intcount;for(count=1;count 2.Java變量和函數(shù)的實(shí)例
Java的類包含變量和函數(shù)。數(shù)據(jù)變量可以是一些原始的類型,如int,char等。成員函數(shù)是一些可執(zhí)行的過程。例如,下面程序里:publicclassClassOne{inti;publicClassOne(){i=10;}publicvoidAdd_i(intj){i=i+j;}}ClassOne包含一個(gè)變量i和兩個(gè)成員函數(shù),ClassOne(intfirst)和Add_i(intj)。成員函數(shù)成員函數(shù)是一些可被其它類或自己類調(diào)用的處理子程序。一個(gè)特殊的成員函數(shù)叫構(gòu)造函數(shù),這個(gè)函數(shù)名稱一般與本類名程相同。它沒有返回值。構(gòu)造函數(shù)和成員函數(shù)當(dāng)你在Java里定義一個(gè)類時(shí),你可定義一個(gè)或多個(gè)可選的構(gòu)造函數(shù),當(dāng)創(chuàng)建本類的一個(gè)對(duì)象時(shí)用某一個(gè)構(gòu)造函數(shù)來初始化本對(duì)象。用前面的程序例子來說明,當(dāng)ClassOne類創(chuàng)建一個(gè)新實(shí)例時(shí),所有成員函數(shù)和變量被創(chuàng)建(創(chuàng)建實(shí)例)。構(gòu)造函數(shù)被調(diào)用。ClassOnemc:mc=newClassOne();關(guān)鍵詞new用來創(chuàng)建一個(gè)類的實(shí)例,一個(gè)類用new初始化前并不占用內(nèi)存,它只是一個(gè)類型定義,當(dāng)mc對(duì)象初始化后,mc對(duì)象里的i變量等于10。你可以通過對(duì)象名來引用變量i。(有時(shí)稱為實(shí)例變量)mc.i++;//mc實(shí)例變量加1因?yàn)閙c有ClassOne類的所有變量和成員函數(shù),我們可以使用同樣的語法來調(diào)用成員函數(shù)Add_i:Add_i(10);現(xiàn)在mc.i變量等于21.結(jié)束函數(shù)Java并不支持析構(gòu)函數(shù)(C++里的定義),因?yàn)閖ava本身提供對(duì)象無用時(shí)自動(dòng)清除的功能,同時(shí)它也提供了一個(gè)自動(dòng)拉圾箱的成員函數(shù),在清除對(duì)象時(shí)被調(diào)用:Protectedvoidfinalize(){close();} 3.對(duì)象
有效范圍和廢物自動(dòng)回收對(duì)象有一定的生命期并在它的生命期間使用資源,當(dāng)一個(gè)對(duì)象不再被使用時(shí),它應(yīng)釋放內(nèi)存,避免內(nèi)存溢出。在Java里,收集和釋放內(nèi)存是一個(gè)叫自動(dòng)廢品回收站的線程的責(zé)任。這個(gè)線程監(jiān)視對(duì)象有效范圍并給一個(gè)走出有效范圍的對(duì)象作上標(biāo)識(shí)。
例如:Strings;//沒有分配內(nèi)存s=newString(”oldstring“);//分配內(nèi)存s=”newstring“;//重新分配內(nèi)存(創(chuàng)建新對(duì)象)我們將在以后訪問String類時(shí)將更加明白它的工作過程,但它的快速工作過程是這樣的:1.創(chuàng)建一個(gè)新的String類對(duì)象并填充以”oldstring“2.創(chuàng)建另一個(gè)String對(duì)象并填充以”newstring“注意我們創(chuàng)建了兩個(gè)對(duì)象。Stirng對(duì)象”oldstring“Stirng對(duì)象”newstring“在第三條語句里,第一個(gè)包括”oldstring“的叫做s的對(duì)象已走出了有效范圍,沒有任何方法可以再訪問他,我們現(xiàn)在有一個(gè)新的對(duì)象也叫s,包含”newstring“。在下一個(gè)廢品回收線程,前一個(gè)對(duì)象將被標(biāo)識(shí)并清除。
4.子類
子類是利用存在的對(duì)象創(chuàng)建一個(gè)新對(duì)象的機(jī)制,比如,如果你有一個(gè)Horse類,你可以創(chuàng)建一個(gè)Zebra子類,Zebra是Horse的一種。
classZebraextendsHorse{intnumber_OF_stripes:}關(guān)鍵詞extends來定義對(duì)象有的子類.Zebra是Horse的子類。Horse類里的所有特征都將拷貝到Zebra類里,而Zebra類里可以定義自己的成員函數(shù)和實(shí)例變量。Zebra稱為Horse的派生類或繼承。另外,你也許還想覆蓋基類的成員函數(shù)。用ClassOne說明,下面是一個(gè)派生類覆蓋Add_i功能的例子.importClassOne;publicclassNewClassextendsClassOne{publicvoid Add_i(intj){i=i+(j/2);}} 當(dāng)NewClass類的實(shí)例創(chuàng)建時(shí),變量i初始化值為10,但調(diào)用Add_i產(chǎn)生不同的結(jié)果。NewClassmnc;mnc=newNewClass();mnc.Add_i(10);訪問控制Java里當(dāng)你創(chuàng)建一個(gè)新類時(shí),你可以標(biāo)明變量和成員函數(shù)的訪問層次。
publicpublicvoidAnyOneCanAccess(){}public實(shí)例變量和成員函數(shù)可以任意其它類調(diào)用。protectedprotectedvoidOnlySubClasses(){}protected實(shí)例變量和成員函數(shù)只能被其子類調(diào)用.privateprivateStringCreditCardNumber;private實(shí)例變量和成員函數(shù)只能在本類里調(diào)用.friendlyvoidMyPackageMethod(){}缺省的,如果沒有定義任何防火控制,實(shí)例變量或函數(shù)缺省定義成friendly,意味著可以被本包里的任意對(duì)象訪問,但其它包里的對(duì)象不可訪問。所有這個(gè)類的對(duì)象都只有實(shí)例變量的同一個(gè)拷貝,這種方法的關(guān)鍵詞是static,例如:classBlock{staticintnumber=50;} 所有從Block類創(chuàng)建的對(duì)象的number變量值都是相同的。無任在哪個(gè)對(duì)象里改變了number的值,所有對(duì)象的number都跟著改變。同樣的,你可以定義static成員函數(shù),但這個(gè)成員函數(shù)不能訪問非static函數(shù)和變量。classBlock{staticintnumber=50;intlocalvalue;staticvoidadd_local(){localvalue++;//沒有運(yùn)行}staticvoidadd_static(){number++;//運(yùn)行}} 5.this和super 訪問一個(gè)類的實(shí)例變量時(shí),this關(guān)鍵詞是指向這個(gè)類本身的指針,在前面ClassOne例子中,我們可以增加構(gòu)造函數(shù)如下:
publicclassClassOne{inti;publicClassOne(){i=10;} publicClassOne(intvalue)this.i=value;} publicvoidAdd_i(intj){i=i+j;}} 這里,this指向ClassOne類的指針。如果在一個(gè)子類里覆蓋了父類的某個(gè)成員函數(shù),但又想調(diào)用父類的成員函數(shù),你可以用super關(guān)鍵詞指向父類的成員函數(shù)。
importClassOne;publicclassNewClassextendsClassOne{publicvoidAdd_i(intj){i=i+(j/2);super.Add_i(j);}} 下面程序里,i變量被構(gòu)造函數(shù)設(shè)成10,然后15,最后被父類(ClassOne)設(shè)成25。NewClassmnc;mnc=newNewClass();mnc.Add_i(10);6.類的類型
至今為止,我用在類前面只用了一個(gè)public關(guān)鍵詞,其實(shí)它有下面4種選擇:abstract一個(gè)abstract類必須至少有一個(gè)虛擬函數(shù),一個(gè)abstract類不能直接創(chuàng)建對(duì)象,必須繼承子類后才能。
final一個(gè)final類聲明了子類鏈的結(jié)尾,用final聲明的類不能再派生子類。publicpublic類能被其它的類訪問。在其它包里,如果想使用這個(gè)類必須先import,則它只能在它定義的package里使用。
7.抽象類
面向?qū)ο蟮囊粋€(gè)最大優(yōu)點(diǎn)就是能夠定義怎樣使用這個(gè)類而不必真正定義好成員函數(shù)。如果程序由不同的用戶實(shí)現(xiàn)時(shí)是很有用的,這不需用戶使用相同的成員函數(shù)名。
在java里Graphics類里一個(gè)abstract類的例子如下:publicabstractclassGraphics{publicabstractvoiddrawLine(intx1,inty1,intx2,inty2);publicabstractvoiddrawOval(intx,inty,intwidth,intheight);publicabstractvoiddrawRect(intx,inty,intwidth,intheight);...} 在Graphics類里聲明了幾個(gè)成員函數(shù),但成員函數(shù)的實(shí)際代碼是在另外一處地方實(shí)現(xiàn)的。publicclassMyClassextendsGraphics{publicvoiddrawLine(intx1,inty1,intx2,inty2){}} 當(dāng)一個(gè)類包含一個(gè)abstract成員函數(shù),這個(gè)類必須定義為abstract類。然而并不是abstract類的所有的成員函數(shù)都是abstract的。Abstract類不能有私有成員函數(shù)(它們不能被實(shí)現(xiàn)),也不能有靜態(tài)成員函數(shù)。
8.包(Packages)包(Package)由一組類(class)和界面(interface)組成。它是管理大型名字空間,避免名字沖突的工具。每一個(gè)類和界面的名字都包含在某個(gè)包中。按照一般的習(xí)慣,它的名字是由”.“號(hào)分隔的單詞構(gòu)成,第一個(gè)單詞通常是開發(fā)這個(gè)包的組織的名稱。
定義一個(gè)編譯單元的包編譯單元的包由package語句定義。如果使用package語句,編譯單元的第一行必須無空格,也無注釋。其格式如下:packagepackageName;若編譯單元無package語句,則該單元被置于一個(gè)缺省的無名的包中。使用其它包中的類和界面在Java語言里提供;一個(gè)包可以使用另一個(gè)包中類和界面的定義和實(shí)現(xiàn)的機(jī)制。用import關(guān)鍵詞來標(biāo)明來自其它包中的類。一個(gè)編譯單元可以自動(dòng)把指定的類和界面輸入到它自己的包中。在一個(gè)包中的代碼可以有兩種方式來定義來自其它包中的類和界面:*在每個(gè)引用的類和界面前面給出它們所在的包的名字;//前綴包名法acme.project.FooBarobj=newacme.project.FooBar();*使用import語句,引入一個(gè)類或一個(gè)界面,或包含它們的包。引入的類和界面的名字在當(dāng)前的名字空間可用。引入一個(gè)包時(shí),則該包所有的公有類和界面均可用。其形式如下://從acme.project引入所有類importacme.project.*;這個(gè)語句表示acme.project中所有的公有類被引入當(dāng)前包。以下語句從acme.project包中進(jìn)入一個(gè)類Employec_List。//從acme.project而引入Employee_Listimportacme.project.Employee_list;Employee_Listobj=newEmployee _List();在使用一個(gè)外部類或界面時(shí),必須要聲明該類或界面所在的包,否則會(huì)產(chǎn)生編譯錯(cuò)誤。import(引用)類包(classpackage)用import關(guān)鍵詞調(diào)入,指定package名字如路徑和類名,用*匹配符可以調(diào)入多于一個(gè)類名。
importjava.Date;importjava.awt.*;如果java源文件不包含package,它放在缺省的無名package。這與源文件同目錄,類可以這樣引入:importMyClass。
Java系統(tǒng)包:Java語言提供了一個(gè)包含窗口工具箱,實(shí)用程序,一般I/O,工具和網(wǎng)絡(luò)功能的包。
java.applet這個(gè)包包含量了設(shè)計(jì)applet的類,用一個(gè)類Applet和三個(gè)接口.AppletContext;AppletStub;和AudioClip.java.awt另一個(gè)窗口工具箱包.awt,包含了產(chǎn)生裝飾物和GUI成員的類。這個(gè)package包括:
Button,Checkbox,Choice,Component,Graphics,Menu,Pane1,TextArea和TextField。java.ioI/Opackage包含文件輸入/輸出類,F(xiàn)ileInputStream和FileOutputStream.java.lang這個(gè)包包含Java語言類,包含:對(duì)象,線程,異常出口,系統(tǒng),整數(shù),原點(diǎn),數(shù)學(xué),字符等。java.net這個(gè)類支持TCP/IP網(wǎng)絡(luò)協(xié)議,并包含Socket類,URL和URL相聯(lián)系的類。java.util這個(gè)類包含程序的同步類,它包含Date,Dictionary類等。
四、Java程序編寫
象其它編程語言一樣,Java 編程語言也被用來創(chuàng)建應(yīng)用程序。一個(gè)共同的應(yīng)用程序范例是在屏幕上顯示字串“Hello World!”。下列代碼給出了這個(gè) Java 應(yīng)用程序。
雖然很多你可能都不明白,沒有關(guān)系,主要是來體會(huì)一下 Java 程序是什么樣子,你可以先看看,有個(gè)印象,然后可以先模仿著做。1.HelloWorldApp 1.// 2.// HelloWorld 應(yīng)用示例 3.// 4.public class HelloWorldApp{ 5.public static void main(String args[]){ 6.System.out.println(”Hello World!“);7.} 8.} 以上程序行是在你的屏幕上打印“Hello World!”所需的最少代碼。
2.描述HelloWorldApp 第 1-3 行
程序中的 1-3 行是注釋行 1 // 2 // HelloWorld 應(yīng)用示例 3 // 第 4 行
第 4 行聲明類名為 HelloWorldApp。類名(Classname)是在源文件中指明的,它可在與源代碼相同的目錄上創(chuàng)建一個(gè) classname · class 文件。在本例題中,編譯器創(chuàng)建了一個(gè)稱為HelloWorldApp.class的文件, 它包含了公共類HelloWorldApp的編譯代碼。public class HelloWorldApp{ 第 5 行
第 5 行是程序執(zhí)行的起始點(diǎn)。Java 解釋器必須發(fā)現(xiàn)這一嚴(yán)格定義的點(diǎn),否則將拒絕運(yùn)行程序。
其它程序語言(特別是 C 和 C++)也采用 main()聲明作為程序執(zhí)行的起始點(diǎn)。此聲明的不同部分將在本課程的后幾部分介紹。如果在程序的命令行中給出了任何自變量(命令行參數(shù)),它們將被傳遞給 main()方法中被稱作 args 的 String 數(shù)組。在本例題中,未使用自變量。
public static void main(String args[]){ public-方法 main()可被任何程序訪問,包括 Java 解釋器。
static-是一個(gè)告知編譯器 main()是用于類 HelloWorldApp 中的方法的關(guān)鍵字。為使 main()在程序做其它事之前就開始運(yùn)行,這一關(guān)鍵字是必要的。
void-表明 main()不返回任何信息。這一點(diǎn)是重要的,因?yàn)?Java 編程語言要進(jìn)行謹(jǐn)慎的類型檢查,包括檢查調(diào)用的方法確實(shí)返回了這些方法所聲明的類型。
String args[]使代碼更好維護(hù) 封裝迫使用戶通過方法訪問數(shù)據(jù)能保護(hù)對(duì)象的數(shù)據(jù)不被誤修改,還能使對(duì)象的重用變得更簡單。數(shù)據(jù)隱藏通常指的就是封裝。它將對(duì)象的外部界面與對(duì)象的實(shí)現(xiàn)區(qū)分開來,隱藏實(shí)現(xiàn)細(xì)節(jié)。迫使用戶去使用外部界面,即使實(shí)現(xiàn)細(xì)節(jié)改變,還可通過界面承擔(dān)其功能而保留原樣,確保調(diào)用它的代碼還繼續(xù)工作。封裝使代碼維護(hù)更簡單。
2.繼承
is a 關(guān)系—— 子對(duì)象
在面向?qū)ο笫澜缋锩妫3R獎(jiǎng)?chuàng)建某對(duì)象(如:一個(gè)職員對(duì)象),然后需要一個(gè)該基本對(duì)象的更專業(yè)化的版本,比如,可能需要一個(gè)經(jīng)理的對(duì)象。顯然經(jīng)理實(shí)際上是一個(gè)職員,經(jīng)理和職員具有 is a 的關(guān)系,經(jīng)理只是一個(gè)帶有附加特征的職員。因此,需要有一種辦法從現(xiàn)有對(duì)象來創(chuàng)建一個(gè)新對(duì)象。這個(gè)方式就是繼承。
“繼承”是面向?qū)ο筌浖夹g(shù)當(dāng)中的一個(gè)概念。如果一個(gè) 對(duì)象 A 繼承自另一個(gè) 對(duì)象 B,就把這個(gè) A 稱為”B 的子 對(duì)象 “,而把 B 稱為”A 的父 對(duì)象 "。繼承可以使得子 對(duì)象 具有父 對(duì)象 的各種屬性和方法,而不需要再次編寫相同的代碼。在令子 對(duì)象 繼承父 對(duì)象 的同時(shí),可以重新定義某些屬性,并重寫某些方法,即覆蓋父 對(duì)象 的原有屬性和方法,使其獲得與父對(duì)象不同的功能。
3.多態(tài)
同一行為的多種不同表達(dá),或者同一行為的多種不同實(shí)現(xiàn)就叫做多態(tài)。
還是用剛才經(jīng)理和職員這個(gè)例子來舉例:人事部門需要對(duì)公司所有職員統(tǒng)一制作胸卡(一般也就是門禁卡,進(jìn)出公司證明身份使用),制作的師傅說,只要告訴我一個(gè)人員的信息,就可以制作出一份胸卡,簡化一下就是:一位職員的信息對(duì)應(yīng)一份胸卡。
這個(gè)時(shí)候,對(duì)胸卡制作的師傅而言,所有的人都是職員,無所謂是經(jīng)理還是普通職員。也就是說,對(duì)于傳遞職員信息這樣一個(gè)行為,存在多種不同的實(shí)現(xiàn),既可以傳遞經(jīng)理的信息,也可以傳遞普通職員的信息。這就是多態(tài)的表現(xiàn)。
再舉一個(gè)例子:比如我們說“筆”這個(gè)對(duì)象,它就有很多不同的表達(dá)或?qū)崿F(xiàn),比如有鋼筆、鉛筆、圓珠筆等等。那么我說“請(qǐng)給我一支筆”,你給我鋼筆、鉛筆或者圓珠筆都可以,這里的“筆”這個(gè)對(duì)象就具備多態(tài)。
八、Java類的基本構(gòu)成
1.Java類的定義形式
一個(gè)完整的 Java 類通常由下面六個(gè)部分組成: 包定義語句 import 語句 類定義{ 成員變量 構(gòu)造方法 成員方法 } 其中:只有類定義和“{}”是不可或缺的,其余部分都可以根據(jù)需要來定義。下面分別來學(xué)習(xí)各個(gè)部分的基本規(guī)則,看看如何寫 Java 的類。
2.包
2.1.包是什么
在 Java 中,包是類、接口或其它包的集合,包主要用來將類組織起來成為組,從而對(duì)類進(jìn)行管理。
2.2.包能干什么
包對(duì)于下列工作非常有用:
(1):包允許您將包含類代碼的文件組織起來,易于查找和使用適當(dāng)?shù)念悺?2):包不止是包含類和接口,還能夠包含其它包。形成層次的包空間。
(3):它有助于避免命名沖突。當(dāng)您使用很多類時(shí),確保類和方法名稱的唯一性是非常困難的。包能夠形成層次命名空間,縮小了名稱沖突的范圍,易于管理名稱。
為便于管理數(shù)目眾多的類,Java 語言中引入了“包”的概念,可以說是對(duì)定義的 Java類進(jìn)行“分組”,將多個(gè)功能相關(guān)的類定義到一個(gè)“包”中,以解決命名沖突、引用不方便、安全性等問題。就好似當(dāng)今的戶籍制度,每個(gè)公民除有自己的名字“張三”、“李四”外還被規(guī)定了他的戶籍地。假定有兩個(gè)人都叫張三,只稱呼名字就無法區(qū)分他們,但如果事先登記他們的戶籍分別在北京和上海,就可以很容易的用“北京的張三”、“上海的張三”將他們區(qū)分開來。如果北京市仍有多個(gè)張三,還可以細(xì)分為“北京市.海淀區(qū)的張三”、“北京市.西城區(qū).平安大街的張三”等等,直到能惟一標(biāo)識(shí)每個(gè)“張三”為止。
JDK 中定義的類就采用了“包”機(jī)制進(jìn)行層次式管理,下圖顯示了其組織結(jié)構(gòu)的一部分:
從圖中可以看出,一個(gè)名為 java 的包中又包含了兩個(gè)子包:io 包和 lang 包。lang 包中包含了 System, String, Object 三個(gè)類的定義。事實(shí)上,Java 包中既可以包含類的定義,也可以包含子包,或同時(shí)包含兩者。
簡而言之:從邏輯上講,包是一組相關(guān)類的集合;從物理上講,同包即同目錄。
2.1.JDK中常用的包
java.lang----包含一些 Java 語言的核心類,包含構(gòu)成 Java 語言設(shè)計(jì)基礎(chǔ)的類。在此包中定義的最重要的一個(gè)類是“Object”,代表類層次的根,Java 是一個(gè)單根系統(tǒng),最終的根就是“Object”,這個(gè)類會(huì)在后面講到。
Java 并不具有“自由”的方法,例如,不屬于任何類的方法,Java 中的所有方法必須始終屬于某個(gè)類。經(jīng)常需要使用數(shù)據(jù)類型轉(zhuǎn)換方法。Java 在 Java.lang 包中定義了“包裝對(duì)象”類,使我們能夠?qū)崿F(xiàn)數(shù)據(jù)類型轉(zhuǎn)換。如 Boolean、Character、Integer、Long、Float 和Double,這些在后面會(huì)講到。
此包中的其它類包括:
? Math——封裝最常用的數(shù)學(xué)方法,如正弦、余弦和平方根。? String,StringBuffer——封裝最常用的字符串操作。你不必顯示導(dǎo)入該包,該 Java 包通常已經(jīng)導(dǎo)入。
java.awt----包含了構(gòu)成抽象窗口工具集(abstract window toolkits)的多個(gè)類,這些類被用來構(gòu)建和管理應(yīng)用程序的圖形用戶界面(GUI)。
javax.swing----完全 Java 版的圖形用戶界面(GUI)解決方案,提供了很多完備的組件,可以應(yīng)對(duì)復(fù)雜的桌面系統(tǒng)構(gòu)建。
java.net----包含執(zhí)行與網(wǎng)絡(luò)相關(guān)的操作的類,如 URL, Socket, ServerSocket 等。java.io----包含能提供多種輸入/輸出功能的類。java.util----包含一些實(shí)用工具類,如定義系統(tǒng)特性、使用與日期日歷相關(guān)的方法。還有重要的集合框架。
2.2.Java中如何表達(dá)包——package語句
Java 語言使用 package 語句來實(shí)現(xiàn)包的定義。package 語句必須作為 Java 源文件的第一條語句,指明該文件中定義的類所在的包。若缺省該語句,則指定為無名包,其語法格式為:
package pkg1[.pkg2[.pkg3?]];//“[]”表示可選Java 編譯 器 把包對(duì) 應(yīng) 于 文 件系 統(tǒng) 的目 錄管 理,因此包也可以嵌套使用,即一個(gè)包中可以含有類的定義也可以含有子包,其嵌套層數(shù)沒有限制。package 語句中,用‘.’來指明包的層次;Java 語言要求包聲明的層次和實(shí)際保存類的字節(jié)碼文件的目錄結(jié)構(gòu)存在對(duì)應(yīng)關(guān)系,以便將來使用該類時(shí)能通過包名(也就是目錄名)查找到所需要的類文件。簡單地說就是包的層次結(jié)構(gòu)需要和文件夾的層次對(duì)應(yīng)。
注意:每個(gè)源文件只有一個(gè)包的聲明,而且包名應(yīng)該全部小寫。具體來說,程序員要做以下工作:
2.3.編譯和生成包
如果在程序 Test.java 中已定義了包 p1,就必須將編譯生成的字節(jié)碼文件 Test.class 保存在與包名同名的子目錄中,可以選用下述兩種方式之一:
采用下述命令編譯: javac Test.java 則編譯器會(huì)在當(dāng)前目錄下生成 Test.class 文件,再在適合位置手動(dòng)創(chuàng)建一個(gè)名為 p1 的子目錄,將 Test.class 復(fù)制到該 p1 目錄下。
采用簡化的編譯命令,就是可以帶包編譯 javac-d destpath Test.java 歸入該包的類的字節(jié)代碼文件應(yīng)放在 java 的類庫所在路徑的 destpath 子目錄下?,F(xiàn)在包的相對(duì)位置已經(jīng)決定了,但 java 類庫的路徑還是不定的。事實(shí)上,java 可以有多個(gè)存放類庫的目錄,其中的缺省路徑為 java 目錄下的 lib 子目錄,你可以通過使用-classpath 選項(xiàng)來確定你當(dāng)前想選擇的類庫路徑。除此之外,你還可以在 CLASSPATH 環(huán)境變量中設(shè)置類庫路徑。destpath 為目標(biāo)路徑,可以是本地的任何絕對(duì)或相對(duì)路徑。則編譯器會(huì)自動(dòng)在 destpath目錄下建立一個(gè)子目錄 p1,并將生成的.class 文件自動(dòng)保存到 destpath/p1 下。例如: javac-d.Test.java javac-d C:test Test.java 2.4.帶包運(yùn)行
運(yùn)行帶包的程序,需要使用類的全路徑,也就是帶包的路徑,比如上面的那個(gè)程序,就使用如下的代碼進(jìn)行運(yùn)行:
java p1.Test 3.import 為了能夠使用某一個(gè)包的成員,我們需要在 Java 程序中明確導(dǎo)入該包。使用“import”語句可完成此功能。在 java 源文件中 import 語句應(yīng)位于 package 語句之后,所有類的定義之前,可以有 0~多條,其語法格式為:
import package1[.package2?].(classname|*);java 運(yùn)行時(shí)環(huán)境將到 CLASSPATH + package1.[package2?]路徑下尋找并載入相應(yīng)的字節(jié)碼文件 classname.class?!?”號(hào)為通配符,代表所有的類。也就是說 import 語句為編譯器指明了尋找類的途徑。
例,使用 import 語句引入類程序:TestPackage.java
java 編譯器默認(rèn)為所有的 java 程序引入了 JDK 的 java.lang 包中所有的類(import java.lang.*;),其中定義了一些常用類:System、String、Object、Math 等。因此我們可以直接使用這些類而不必顯式引入。但使用其它非無名包中的類則必須先引入、后使用。
3.1.Java類搜尋方式
程序中的 import 語句標(biāo)明要引入 p1 包中的 Test 類,假定環(huán)境變量 CLASSPATH 的值為
“.;C:jdk6lib;D:ex”,java 運(yùn)行環(huán)境將依次到下述可能的位置尋找并載入該字節(jié)碼 文件 Test.class:.p1Test.class C:jdk6libp1Test.class D:exp1Test.class 其中,“.”代表當(dāng)前路徑,如果在第一個(gè)路徑下就找到了所需的類文件,則停止搜索。否則依次搜索后續(xù)路徑,如果在所有的路徑中都未找到所需的類文件,則編譯或運(yùn)行出錯(cuò)。
4.訪問修飾符
Java 語言允許對(duì)類中定義的各種屬性和方法進(jìn)行訪問控制,即規(guī)定不同的保護(hù)等級(jí)來限制對(duì)它們的使用。為什么要這樣做?Java 語言引入類似訪問控制機(jī)制的 目的 在 于實(shí) 現(xiàn) 信息的 封 裝 和 隱藏。Java 語言為對(duì)類中的屬性和方法進(jìn)行有效地訪問控制,將它們分為四個(gè)等級(jí):private, 無修飾符, protected, public,具體規(guī)則如下:
變量和方法可以處于四個(gè)訪問級(jí)別中的一個(gè):公共,受保護(hù),無修飾符或私有。類可以在公共或無修飾級(jí)別。
變量、方法或類有缺省(無修飾符)訪問性,如果它沒有顯式受保護(hù)修飾符作為它的聲明的一部分的話。這種訪問性意味著,訪問可以來自任何方法,當(dāng)然這些方法只能在作為對(duì)象的同一個(gè)包中的成員類當(dāng)中。
以修飾符 protected 標(biāo)記的變量或方法實(shí)際上比以缺省訪問控制標(biāo)記的更易訪問。一個(gè)protected 方法或變量可以從同一個(gè)包中的類當(dāng)中的任何方法進(jìn)行訪問,也可以是從任何子類中的任何方法進(jìn)行訪問。當(dāng)它適合于一個(gè)類的子類但不是不相關(guān)的類時(shí),就可以使用這種受保護(hù)訪問來訪問成員。5.類定義
Java 程序的基本單位是類,你建立類之后,就可用它來建立許多你需要的對(duì)象。Java把每一個(gè)可執(zhí)行的成分都變成類。
類的定義形式如下:
這里,類名要是合法的標(biāo)識(shí)符。在類定義的開始與結(jié)束處必須使用花括號(hào)。你也許想建立一個(gè)矩形類,那么可以用如下代碼:
6.構(gòu)造方法
6.1.什么是構(gòu)造方法
類有一個(gè)特殊的成員方法叫作構(gòu)造方法,它的作用是創(chuàng)建對(duì)象并初始化成員變量。在創(chuàng)建對(duì)象時(shí),會(huì)自動(dòng)調(diào)用類的構(gòu)造方法。
6.2.構(gòu)造方法定義規(guī)則
Java 中的構(gòu)造方法必須與該類具有相同的名字,并且沒有方法的返回類型(包括沒有void)。另外,構(gòu)造方法一般都應(yīng)用 public 類型來說明,這樣才能在程序任意的位置創(chuàng)建類的實(shí)例--對(duì)象。
6.3.示例
下面是一個(gè) Rectangle 類的構(gòu)造方法,它帶有兩個(gè)參數(shù),分別表示矩形的長和寬:
6.4.說明
每個(gè)類至少有一個(gè)構(gòu)造方法。如果不寫一個(gè)構(gòu)造方法,Java 編程語言將提供一個(gè)默認(rèn)的,該構(gòu)造方法沒有參數(shù),而且方法體為空。
注意:如果一個(gè)類中已經(jīng)定義了構(gòu)造方法則系統(tǒng)不再提供默認(rèn)的構(gòu)造方
7.析構(gòu)方法
析構(gòu)方法 finalize 的功能是: 當(dāng)對(duì)象被從內(nèi)存中刪除時(shí),該成員方法將會(huì)被 自動(dòng)調(diào)用。通常,在析構(gòu)方法內(nèi),你可以填寫用來回收對(duì)象內(nèi)部的動(dòng)態(tài)空間的代碼。
特別注意:當(dāng)我們?nèi)フ{(diào)用析構(gòu)方法的時(shí)候,并不會(huì)引起該對(duì)象實(shí)例從內(nèi)存中刪除,而是不會(huì)起到任何作用。
在 Java 編程里面,一般不需要我們?nèi)懳鰳?gòu)方法,這里只是了解一下就可以了。
8.屬性
8.1.屬性是什么
簡單點(diǎn)說,屬性就是對(duì)象所具有的靜態(tài)屬性。
8.2.定義規(guī)則
Java 類中屬性的聲明采用如下格式: 訪問修飾符 修飾符 類型 屬性名稱=初始值;訪問修飾符:可以使用四種不同的訪問修飾符中的一種,包括 public(公共的)、protected(受保護(hù)的),無修飾符和 private(私有的)。public 訪問修飾符表示屬性可以從任何其它代碼調(diào)用。private 表示屬性只可以由該類中的其它方法來調(diào)用。protected 將在以后的課程中討論。
修飾符:是對(duì)屬性特性的描述,例如后面會(huì)學(xué)習(xí)到的:static、final 等等。類型:屬性的數(shù)據(jù)類型,可以是任意的類型。屬性名稱:任何合法標(biāo)識(shí)符
初始值:賦值給屬性的初始值。如果不設(shè)置,那么會(huì)自動(dòng)進(jìn)行初始化,基本類型使用缺省值,對(duì)象類型自動(dòng)初始化為 null。
8.3.說明
屬性有時(shí)候也被稱為成員變量、實(shí)例變量、域,它們經(jīng)常被互換使用。
9.方法
9.1.方法是什么
方法就是對(duì)象所具有的動(dòng)態(tài)功能。
9.2.定義規(guī)則
Java 類中方法的聲明采用以下格式:訪問修飾符 修飾符 返回值類型 方法名稱(參數(shù)列表)throws 異常列表 {方法體} 訪問修飾符:可以使用四種不同的訪問修飾符中的一種,包括 public(公共的)、protected(受保護(hù)的),無修飾符和 private(私有的)。public 訪問修飾符表示方法可以從任何其它代碼調(diào)用。private 表示方法只可以由該類中的其它方法來調(diào)用。protected 將在以后的課程中討論。
修飾符:是對(duì)方法特性的描述,例如后面會(huì)學(xué)習(xí)到的:static、final、abstract、synchronized 等等。
返回值類型::表示方法返回值的類型。如果方法不返回任何值,它必須聲明為 void(空)。
Java 技術(shù)對(duì)返回值是很嚴(yán)格的,例如,如果聲明某方法返回一個(gè) int 值,那么方法必須從所有可能的返回路徑中返回一個(gè) int 值(只能在等待返回該 int 值的上下文中被調(diào)用。)方法名稱:可以是任何合法標(biāo)識(shí)符,并帶有用已經(jīng)使用的名稱為基礎(chǔ)的某些限制條件。參數(shù)列表:允許將參數(shù)值傳遞到方法中。列舉的元素由逗號(hào)分開,而每一個(gè)元素包含一個(gè)類型和一個(gè)標(biāo)識(shí)符。在下面的方法中只有一個(gè)形式參數(shù),用 int 類型和標(biāo)識(shí)符 days 來聲明:public void test(int days){} throws 異常列表:子句導(dǎo)致一個(gè)運(yùn)行時(shí)錯(cuò)誤(異常)被報(bào)告到調(diào)用的方法中,以便以合適的方式處理它。異常在后面的課程中介紹。
花括號(hào)內(nèi)是方法體,即方法的具體語句序列。9.3.示例
比如現(xiàn)在有一個(gè)“車”的類——Car,“車”具有一些基本的屬性,比如四個(gè)輪子,一個(gè)方向盤,車的品牌等等。當(dāng)然,車也具有自己的功能,也就是方法,比如車能夠“開動(dòng)”——run。要想車子能夠開動(dòng),需要給車子添加汽油,也就是說,需要為 run 方法傳遞一些參數(shù)“油”進(jìn)去。車子跑起來過后,我們需要知道當(dāng)前車輛運(yùn)行的速度,就需要 run 方法具有返回值“當(dāng)前的速度”。
9.4.形參和實(shí)參
形參:就是形式參數(shù)的意思。是在定義方法名的時(shí)候使用的參數(shù),用來標(biāo)識(shí)方法接收的參數(shù)類型,在調(diào)用該方法時(shí)傳入。
實(shí)參:就是實(shí)際參數(shù)的意思。是在調(diào)用方法時(shí)傳遞給該方法的實(shí)際參數(shù)。
比如:上面的例子中“int oil”就是個(gè)形式參數(shù),這里只是表示需要加入汽油,這個(gè)方法才能正常運(yùn)行,但具體加入多少,要到真正使用的時(shí)候,也就是調(diào)用這個(gè)方法的時(shí)候才具體確定,加入調(diào)用的時(shí)候傳入“80”,這就是個(gè)實(shí)際參數(shù)。
形參和實(shí)參有如下基本規(guī)則:
(1):形參和實(shí)參的類型必須要一致,或者要符合隱含轉(zhuǎn)換規(guī)則(2):形參類型不是引用類型時(shí),在調(diào)用該方法時(shí),是按值傳遞的。在該方法運(yùn)行時(shí),形參和實(shí)參是不同的變量,它們在內(nèi)存中位于不同的位置,形參將實(shí)參的值復(fù)制一份,在該方法運(yùn)行結(jié)束的時(shí)候形參被釋放,而實(shí)參內(nèi)容不會(huì)改變。
(3):形參類型是引用類型時(shí),在調(diào)用該方法時(shí),是按引用傳遞的。運(yùn)行時(shí),傳給方法的是實(shí)參的地址,在方法體內(nèi)部使用的也是實(shí)參的地址,即使用的就是實(shí)參本身對(duì)應(yīng)的內(nèi)存空間。所以在函數(shù)體內(nèi)部可以改變實(shí)參的值。
9.5.參數(shù)可變的方法
從 JDK5.0 開始,提供了參數(shù)可變的方法。
當(dāng)不能確定一個(gè)方法的入口參數(shù)的個(gè)數(shù)時(shí),5.0 以前版本的 Java 中,通常的做法是將多個(gè)參數(shù)放在一個(gè)數(shù)組或者對(duì)象集合中作為參數(shù)來傳遞,5.0 版本以前的寫法是:
int sum(Integer[] numbers){?} //在別處調(diào)用該方法
sum(new Integer[] {12,13,20});而在 5.0 版本中可以寫為:
int sum(Integer...numbers){//方法內(nèi)的操作} 注意:方法定義中是三個(gè)點(diǎn) //在別處調(diào)用該方法 sum(12,13,20);//正確 sum(10,11);//正確
也就是說,傳入?yún)?shù)的個(gè)數(shù)并不確定。但請(qǐng)注意:傳入?yún)?shù)的類型必須是一致的,究其本質(zhì),就是一個(gè)數(shù)組。
顯然,JDK5.0 版本的寫法更為簡易,也更為直觀,尤其是方法的調(diào)用語句,不僅簡化很多,而且更符合通常的思維方式,更易于理解。
第三篇:JAVA總結(jié)專題
在這忙忙碌碌的這段時(shí)間里,經(jīng)過老師的輔導(dǎo),迅速的將一點(diǎn)沒有學(xué)的JAVA基礎(chǔ)搞定了!有了基礎(chǔ)學(xué)習(xí)還是好,萬事開頭難這句話說的太對(duì)了,學(xué)計(jì)算機(jī)語言我覺得記憶好的方法就是多打代碼,課前預(yù)習(xí),課堂上認(rèn)真聽講,把現(xiàn)學(xué)的方法把以前所做的作業(yè)用最簡便的方法再一次鞏固,創(chuàng)新最重要,在后續(xù)的學(xué)習(xí)中,得要加倍努力學(xué)習(xí)。
其實(shí)學(xué)java有不懂,要先自己思考。想清楚這句代碼是什么意思。為什么要寫在這,等等之類的。等你真的搞不明白的時(shí)候,就一定要向老師咨詢,不要感到有什么丟人的。因?yàn)椴粫?huì)是很正常的事。并不是每個(gè)人都是天才,一學(xué)就會(huì),一學(xué)就能運(yùn)用自如的。學(xué)java有一點(diǎn)是非常重要的,就是練習(xí)。一段代碼要不停的敲,多敲幾遍,尤其是自己不熟悉或者不熟練的代碼,更要敲。不要感覺到厭煩,其實(shí)我感覺敲代碼挺好玩的,并不是一件很枯燥的事。
老師平常布置的課后上機(jī)練習(xí)題一定要做,課后的練習(xí)題能夠讓你把新學(xué)到的知識(shí)鞏固一遍,能夠加深記憶,不會(huì)讓你在以后做題的時(shí)候感到?jīng)]一點(diǎn)思路。
當(dāng)感覺到不會(huì)的時(shí)候,千萬不要?dú)怵H,因?yàn)檫@很正常,現(xiàn)在的學(xué)習(xí)就是為了培養(yǎng)你有一個(gè)邏輯思維,為了以后開發(fā)軟件的時(shí)候有個(gè)完整,清晰的思路。
其實(shí),總體來說。學(xué)習(xí)java很快樂。尤其是當(dāng)你遇到一道自己不會(huì)的題,然后,又通過自己的努力解決了,那時(shí)候,那種心情不是用言語來表達(dá)的。就好像你遇到一個(gè)數(shù)學(xué)難題,自己解決了之后那種成就感一樣。
學(xué)java的時(shí)候一定要,放松心情,輕輕松松的來學(xué),隨時(shí)讓自己快樂著,這樣能夠讓你能夠更快的接受java,千萬不要有什么心理負(fù)擔(dān),因?yàn)閖ava的特點(diǎn)之一就是--簡單易懂。只要自己努力到了,就一定能夠?qū)W好java。
學(xué)完了JAVA今天我們用項(xiàng)目案例:迷你DVD管理器來鞏固了我們所學(xué)的所有內(nèi)容,通過這項(xiàng)目的操練,首先,1、項(xiàng)目用到了會(huì)使用順序、分支、循環(huán)、跳轉(zhuǎn)語句編寫程序,2、要會(huì)使用數(shù)組、操作字符串,3、會(huì)使用帶參的方法;
4、會(huì)定義類、創(chuàng)建和使用對(duì)象,看到這些腦袋里一片迷茫?。〔恢涝鯓訉懀缓笙氲皆鐚懲韺懚家粯樱驼罩鴷蠈懫饋砹?,到現(xiàn)在還是弄不懂的就是那個(gè)對(duì)象數(shù)組,不知道怎樣去理解,抽象的把我抽暈了,有望老師來給我們補(bǔ)補(bǔ)這一章,在實(shí)現(xiàn)DVD的業(yè)務(wù)處理時(shí),計(jì)算時(shí)差還是不懂,照著書上打了一遍,可還是得不到想要的結(jié)果,經(jīng)過網(wǎng)上的搜尋與老師講解,現(xiàn)在已略懂一二了,在做完這項(xiàng)目后,真不知道當(dāng)時(shí)是怎樣敲出來的,難道這就是所說的靈感!感覺很高興,現(xiàn)在已習(xí)慣了代碼報(bào)錯(cuò),其實(shí)代碼報(bào)錯(cuò)是一件值得鼓勵(lì)的事,因?yàn)闆]有錯(cuò)就覺得自己什么都懂了,在學(xué)習(xí)中相信每一個(gè)人都遇到過挫折吧!但一定要想方法戰(zhàn)勝挫折!我的戰(zhàn)勝挫折方法就是不懂思考后還不懂就問,懂了以后就筆記本記下當(dāng)時(shí)的解決方案!學(xué)習(xí)剛開始!后面的路很長,慢慢的去磨煉了!總結(jié)完畢!
第四篇:Java總結(jié)
Java實(shí)驗(yàn)
1.調(diào)試HelloWorld程序
2.this,super,get ,set,把課本90頁程序4.7中的name改成私有變量
3.繼承,重寫,父類引用指向子類對(duì)象
4.驗(yàn)證數(shù)組Arrays類和Collection類
5.編寫一個(gè)自己的異常類并捕獲之。
6.編寫一個(gè)類,將該類的幾個(gè)對(duì)象裝入TreeSet容器中,并將該容器的內(nèi)容通過輸出流寫入文件中。
前三章重點(diǎn)
0.java的數(shù)據(jù)類型:四類八種-(1)布爾類型Boolean;(2)字符類型char;(3)整數(shù)byte,short,int,long;(4)浮點(diǎn)類型:float,double;1.面向?qū)ο蟮?個(gè)基本特征:封裝,繼承,多態(tài)。
2.構(gòu)造方法和普通方法的區(qū)別:對(duì)構(gòu)造方法而言,它有以下特性---(1)方法名必須與要?jiǎng)?chuàng)建對(duì)象的類名相同。(2)不允許聲明返回類型,即使聲明為void也不被允許。
3.this關(guān)鍵字:是一個(gè)引用,this引用指向的是其本身所在方法的當(dāng)前對(duì)象。this的使用方法:(1)調(diào)用成員變量;(2)可以用this()調(diào)用其他構(gòu)造函數(shù)。
4.java中只對(duì)類成員變量進(jìn)行自動(dòng)初始化,而方法內(nèi)部的局部變量在使用前必須手動(dòng)初始化。
5.static 關(guān)鍵字:可用來修飾類的成員變量和成員方法,需要注意兩點(diǎn)--(1)靜態(tài)方法不能調(diào)用類的非靜態(tài)方法,不能訪問類的非靜態(tài)變量。(2)靜態(tài)方法和靜態(tài)變量(非私有的)可以有兩種調(diào)用方式,一是實(shí)例對(duì)象調(diào)用,二是類名直接調(diào)用。
6.類成員訪問控制修飾符public、private、default(可不寫,即缺省狀態(tài))、protected的使用:public-公用的;private-私有的,只在定義它的類內(nèi)部使用;default-可以被同一包中的類訪問;protected-既可以被同一包中的類訪問,也可以被不在同一包中的子類訪問。
7.方法的重載:指方法名相同,而方法的參數(shù)列表不相同。參數(shù)列表不同有三層意思:(1)參數(shù)類型不同。(2)參數(shù)順序不同。(3)參數(shù)個(gè)數(shù)不同。另外需注意,在同一個(gè)類中,當(dāng)方法名和參數(shù)列表都相同時(shí),訪問控制修飾符或方法返回類型不相同并不是方法的重載,而且這種情況在java中是不被允許的。
第四五章重點(diǎn)
1.繼承:需使用關(guān)鍵字extends.在使用繼承時(shí)需注意--(1)每個(gè)子類只能定義一個(gè)超類(父類),即extends后面應(yīng)且僅應(yīng)跟一個(gè)類名作為該類的父類。(2)父類中的私有屬性和私有方法不能被繼承。
2.方法的重寫:即子類對(duì)超類中的方法保持方法名、返回類型和參數(shù)列表不變,重寫了方法體,使子類和超類完成不同的工作。重寫需注意下面幾個(gè)關(guān)鍵點(diǎn):(1)超類中的私有方法不能被重寫。(2)訪問限制符強(qiáng)度由低到高依次是:public、protected、default、private,在重寫過程中,如果子類和父類中方法的返回值、方法名及方法的參數(shù)列表都相同,這時(shí),要求子類中該方法的訪問限制符強(qiáng)度不能超過父類的。即如果父類中為public時(shí),子類也只能為public,而不能是余下的三種。
3.重載(overload)和覆蓋(override)的區(qū)別:(1)重載—發(fā)生在一個(gè)類的內(nèi)部或子類與父類之間,要求方法名相同而參數(shù)列表不一樣。(2)覆蓋—只能發(fā)生在繼承過程中,要求子類方法的返回類型,方法名和參數(shù)列表同父類的都相同,而方法體不一樣。
4.構(gòu)造器的調(diào)用順序:先祖先,再客人,最后自己。
5.多態(tài):指在類繼承中子類和父類中可以有同名但意義或?qū)崿F(xiàn)方式不同的屬性和方法。分為:覆蓋和重載。多態(tài)的優(yōu)點(diǎn):因?yàn)槎鄳B(tài),可以在程序中對(duì)類進(jìn)行擴(kuò)展,而不需改變那些操作基類接口的方法。
6.動(dòng)態(tài)綁定:指在代碼執(zhí)行期間,判斷所引用對(duì)象的實(shí)際類型,根據(jù)其實(shí)際類型調(diào)用相應(yīng)方法。動(dòng)態(tài)綁定存在的三個(gè)必要條件--(1)要有繼承;(2)要有重寫(覆蓋);(3)父類引用指向子類對(duì)象(向上轉(zhuǎn)型)。
7.Object中常用的方法總結(jié):toString();wait();equals();notify();notifyAll();hashCode();getClass();clone();finalize();(呵呵,盡可能記幾個(gè),以防老師讓咱們列舉)注:java中Object類是所有類的父類,即java中所有的類都有上述9種方法。
8.對(duì)象的比較:注意關(guān)鍵字instanceof的使用。
9.抽象類:
抽象方法—用關(guān)鍵字abstract修飾的方法,該方法只需方法的聲明,而不需方法的實(shí)現(xiàn)(即無方法體)。
抽象類——至少包含一個(gè)抽象方法的類,也用abstract關(guān)鍵字聲明。(注:(1)抽象類中可以有一些具體方法。(2)抽象類不能實(shí)例化。(3)子類繼承抽象類必須實(shí)現(xiàn)其抽象方法。)
10.接口:
(1)可以看成是高度抽象的抽象類,但是接口不是類。
(2)用關(guān)鍵字interface來聲明接口,用關(guān)鍵字imlpements來實(shí)現(xiàn)接口。
(3)接口不能有具體方法,不能有實(shí)例數(shù)據(jù),但可以定義常量。
(4)實(shí)現(xiàn)接口的非抽象類必須實(shí)現(xiàn)接口的所有方法。
(5)每個(gè)類可以實(shí)現(xiàn)多個(gè)接口,這些接口用逗號(hào)隔開,同時(shí),一個(gè)接口可以被多個(gè)類實(shí)現(xiàn)。
第六章:重點(diǎn)看一下實(shí)驗(yàn)四
1.容器——Collection(接口)和Map(接口).Collection——Set(接口)和List(接口)。其中,List必須保持元素的特定順序,常見的實(shí)現(xiàn)類有ArrayList和LinkedList;Set不能有重復(fù)元素,常見的實(shí)現(xiàn)類有HashSet和TreeSet。
Map——一組成對(duì)的“鍵值對(duì)”對(duì)象,即其元素是成對(duì)的對(duì)象,常見的實(shí)現(xiàn)類有HashMap和TreeMap。
第七章 1.異常類的根類是Throwable類,它的兩個(gè)直接子類是Error類和Exception類。
2.異常中常用的5個(gè)關(guān)鍵字為:try,catch,finally,throw,throws.其中,try和catch:用于捕獲異常;finally:無論try塊中的異常是否拋出,finally中的代碼塊總能被執(zhí)行;throw:拋出異常;throws:聲明異常。
3.“未被檢查的異常(Unchecked Exceptions)”和“受檢查的異常(Checked Exceptions)”——
Unchecked Exceptions :編譯器不檢查方法是否處理或拋出的異常,即不做處理,編譯時(shí)不報(bào)錯(cuò)。
Checked Exceptions:受編譯器檢查的異常,即不做處理編譯時(shí)通不過。
4.常見的幾種Checked Exceptions:ClassNotFoundExceptionIOExceptionInterruptedExceptionFileNotFoundException.(盡可能的記幾個(gè)吧,以防不測)第八章
1.流--字節(jié)流和字符流;
流--節(jié)點(diǎn)流和處理流。
2.所有的輸入流都是從抽象類InputStream和Reader繼承而來。所有輸出流都是從抽象類OutputStream和Writer繼承而來。3.字節(jié)流:InputStream和OutputStream;字符流:Reader和Writer;
4.節(jié)點(diǎn)流:直接與文件等底層打交道,如FileInputStreamFileOutputStreamFileReaderFileWriter.處理流:相當(dāng)于包裝流,套在節(jié)點(diǎn)流上,方便數(shù)據(jù)處理。相關(guān)一些用法,具體參考最后一次實(shí)驗(yàn)。
第五篇:java總結(jié)
調(diào)用父類構(gòu)造方法
? 在子類的構(gòu)造方法中可使用super(argument_list)語句調(diào)用父類的構(gòu)造方法
? 如果子類的構(gòu)造方法中沒有顯示地調(diào)用父類構(gòu)造方法,也沒有使用this關(guān)鍵字調(diào)用重載的其它構(gòu)造方法,則系統(tǒng)默認(rèn)調(diào)用父類無參數(shù)的構(gòu)造方法
? 如果子類構(gòu)造方法中既未顯式調(diào)用父類構(gòu)造方法,而父類中又沒有無參的構(gòu)造方法,則編譯出錯(cuò)
1public class Person {
3private String name;
4private int age;private Date birthDate;
7public Person(String name, int age, Date d){ 8this.name = name;
9this.age = age;
10this.birthDate = d;
11}
12public Person(String name, int age){ 13this(name, age, null);
14}
15public Person(String name, Date d){ 16this(name, 30, d);
17}
18public Person(String name){
19this(name, 30);}
21// ……
22}
1public class Student extends Person {
2private String school;
4public Student(String name, int age, String s){ 5super(name, age);
6school = s;
7}
8public Student(String name, String s){
9super(name);
10school = s;
11}
12public Student(String s){ // 編譯出錯(cuò): no super()13school = s;
14}
15}
對(duì)象構(gòu)造和初始化細(xì)節(jié)
? 分配存儲(chǔ)空間并進(jìn)行默認(rèn)的初始化
? 按下述步驟初始化實(shí)例變量
1.綁定構(gòu)造方法參數(shù)
2.如有this()調(diào)用,則調(diào)用相應(yīng)的重載構(gòu)造方法,然后跳轉(zhuǎn)到步驟5
3.顯式或隱式追溯調(diào)用父類的構(gòu)造方法(Object類除外)
4.進(jìn)行實(shí)例變量的顯式初始化操作
5.執(zhí)行當(dāng)前構(gòu)造方法的方法體
==操作符與equals方法
==操作符與equals方法的區(qū)別:
? 引用類型比較引用;基本類型比較值;
? equals()方法只能比較引用類型,“==”可以比較引用類型及基本類型;
? 特例:當(dāng)用equals()方法進(jìn)行比較時(shí),對(duì)類File、String、Date及封裝類(Wrapper Class)來說,是比較類型及內(nèi)容而不考慮引用的是否是同一個(gè)實(shí)例;
? 用“==”進(jìn)行比較時(shí),符號(hào)兩邊的數(shù)據(jù)類型必須一致(可自動(dòng)轉(zhuǎn)換的基本數(shù)據(jù)類型除外),否則編譯出錯(cuò);
由裝箱引發(fā)的——Integer比較的來龍去脈
前置知識(shí): 眾所周之,java是保留了int,char等基本數(shù)據(jù)類型的,也就是說int類型的并不是對(duì)象,然而有些方法卻需要object 類型的變量,所以java使用了裝箱機(jī)制,我們可一自豪的這樣聲明一個(gè)整型變量:Integer a = new Integer(10);那么整型的a也就是對(duì)象了,那這句是什么意思呢:Integer a= 10;java中可以這樣聲明一個(gè)對(duì)象嗎?當(dāng)然不是,從jdk1.5后,java實(shí)現(xiàn)了自動(dòng)裝箱,也就是自動(dòng)將Integer a =10 中的int類型的10轉(zhuǎn)化為了 Integer類型。好,有了前面的只是我們且先看一個(gè)題目:
Integer a = 127;
Integer b = 127;
Integer c = 128;
Integer d = 128;
System.out.println(a==b);
System.out.println(c==d);
答案是什么呢? 如果您回答true,false,那么很遺憾的告訴你,哈哈,其實(shí)你答對(duì)了?。?/p>
那我們暈了就相差1的兩個(gè)數(shù)為啥走向了“反目成仇”的地步呢?憑啥127等于127,我128就不等于128呢?且聽我慢慢道來,Integer a =127,Integer a=128。
127,128應(yīng)該不會(huì)造成什么差異吧,難道是自動(dòng)裝箱的過程有貓膩?找下源碼看看:
private static class IntegerCache {
private IntegerCache(){}
static final Integer cache[] = new Integer[-(-128)+ 127 + 1];static {
for(int i = 0;i < cache.length;i++)
cache[i] = new Integer(i128);
}
這是用一個(gè)for循環(huán)對(duì)數(shù)組cache賦值,cache[255] = new Integer(255-128),也就是newl一個(gè)Integer(127),并把引用賦值給cache[255],好了,然后是Integer b= 127,流程基本一樣,最后又到了cache[255] = new Integer(255-128),這一句,那我們迷糊了,這不是又new了一個(gè)對(duì)象127嗎,然后把引用賦值給cache[255],我們比較這兩個(gè)引用(前面聲明a的時(shí)候也有一個(gè)),由于是不同的地址,所以肯定不會(huì)相等,應(yīng)該返回false??!呵呵,這么想你就錯(cuò)了,請(qǐng)注意看for語句給cache[i]初始化的時(shí)候外面還一個(gè){}呢,{}前面一個(gè)大大的static關(guān)鍵字大咧咧的杵在哪呢,對(duì)靜態(tài)的,那么我們就可以回想下static有什么特性了,只能初始化一次,在對(duì)象間共享,也就是不同的對(duì)象共享同一個(gè)static數(shù)據(jù),那么當(dāng)我們Integer b = 127的時(shí)候,并沒有new出一個(gè)新對(duì)象
來,而是共享了a這個(gè)對(duì)象的引用,記住,他們共享了同一個(gè)引用??!,那么我們進(jìn)行比較a==b時(shí),由于是同一個(gè)對(duì)象的引用(她們在堆中的地址相同),那當(dāng)然返回true了??!
然后我們在看Integer c = 128;Integer d = 128;這兩句?,F(xiàn)在不用我說就應(yīng)該能明白了吧,當(dāng)數(shù)據(jù)不再-128到127之間時(shí),是不執(zhí)行return
IntegerCache.cache[i + offset];這句的,也就是不會(huì)返回一個(gè)static的引用,而是執(zhí)行了return new Integer(i);于是當(dāng) Integer d = 128 時(shí),又會(huì)重新返回一個(gè)引用,兩個(gè)不同的引用
在做c==d 的比較時(shí)當(dāng)然返回false了!
下面附上本程序的字節(jié)碼以供喜歡底層的讀者參考:
Compiled from “CompareInteger.java”
public class CompareInteger extends java.lang.Object{
public CompareInteger();
Code:
0:aload_0
1:invokespecial#1;//Method java/lang/Object.“
public static void main(java.lang.String[]);
Code:
0:bipush 127
2:invokestatic#2;//Method
java/lang/Integer.valueOf:(I)Ljava/lang/Int
eger;
5:astore_1
6:bipush 127
8:invokestatic#2;//Method
java/lang/Integer.valueOf:(I)Ljava/lang/Int
eger;
11: astore_2
12: sipush 128
15: invokestatic#2;//Method
java/lang/Integer.valueOf:(I)Ljava/lang/Int
eger;
18: astore_3
19: sipush 128
22: invokestatic#2;//Method
java/lang/Integer.valueOf:(I)Ljava/lang/Int
eger;
25: astore 4
27: getstatic#3;//Field
java/lang/System.out:Ljava/io/PrintStream;
30: aload_1
31: aload_2
32: if_acmpne39
35: iconst_1
36: goto40
39: iconst_0
40: invokevirtual#4;//Method java/io/PrintStream.println:(Z)V43: getstatic#3;//Field
java/lang/System.out:Ljava/io/PrintStream;
46: aload_3
47: aload4
49: if_acmpne56
52: iconst_1
53: goto57
56: iconst_0
57: invokevirtual#4;//Method java/io/PrintStream.println:(Z)V60: return
}
評(píng)論:呵呵,這么想你就錯(cuò)了,請(qǐng)注意看for語句給cache[i]初始化的時(shí)候外面還一個(gè){}呢,{}前面一個(gè)大大的static關(guān)鍵字大咧咧的杵在哪呢,對(duì)靜態(tài)的,那么我們就可以回想下static有什么特性了,只能初始化一次,在對(duì)象間共享,也就是不同的對(duì)象共享同一個(gè)static數(shù)據(jù),那么當(dāng)我們Integer b = 127的時(shí)候,并沒有new出一個(gè)新對(duì)象來,而是共享了a這個(gè)對(duì)象的引用,記住,他們共享了同一個(gè)引用!!
呵呵,博主我被你這句話小小的誤導(dǎo)了一下,其實(shí)你這里說的原理沒錯(cuò),但是把位置說錯(cuò)了,這段代碼只是初始化cache:
static {
for(int i = 0;i < cache.length;i++)
cache[i] = new Integer(i-128);
}
但真正讓cache[i]為static變量的是這句代碼:
static final Integer cache[] = new Integer[-(-128)+ 127 + 1];