● 用帶標(biāo)號(hào)(label)的break和continue代替goto,使得break可以直接跳出到循環(huán)外的某個(gè)位置,continue跳到當(dāng)前循環(huán)外的循環(huán)
label起給給循環(huán)命名的作用,在程序中引用label表示跳出label所標(biāo)示的循環(huán)
● 初始化和清除是程序設(shè)計(jì)安全性的兩個(gè)最重要的問題
● 創(chuàng)建對(duì)象時(shí):1.分配空間 2.調(diào)用構(gòu)造函數(shù)對(duì)這個(gè)對(duì)象進(jìn)行初始化 3.然后把初始化完了對(duì)象交給那個(gè)引用
● 重載
在日常生活中,我們用相同的詞表達(dá)多種不同的含義,即詞的“重載”。
大多數(shù)程序設(shè)計(jì)語言要求我們?yōu)槊總€(gè)函數(shù)都設(shè)定一個(gè)獨(dú)一無二的標(biāo)識(shí)符。
但是構(gòu)造函數(shù)的出現(xiàn)要求函數(shù)名也要能夠“重載”。
即函數(shù)名相同,參數(shù)不同的構(gòu)造函數(shù)
使用時(shí)各自調(diào)用不同的參數(shù)構(gòu)造函數(shù)。
構(gòu)造函數(shù)名與類名相同
● 缺省構(gòu)造函數(shù)
如果一個(gè)類沒有定義構(gòu)造函數(shù),則編譯程序會(huì)幫我們自動(dòng)創(chuàng)建一個(gè)缺省構(gòu)造函數(shù)。
但是一旦定義了一個(gè),就不會(huì)幫我們自動(dòng)生成一個(gè)。
● this
this關(guān)鍵字可以為已調(diào)用了其方法的那個(gè)對(duì)象生成相應(yīng)的句柄。
調(diào)用這個(gè)函數(shù)的那個(gè)對(duì)象--this,即這個(gè)函數(shù)要作用在哪個(gè)對(duì)象之上。
在一個(gè)構(gòu)造函數(shù)中可以調(diào)用一次另一個(gè)構(gòu)造函數(shù),用this(參數(shù))
● 垃圾收集機(jī)制
垃圾收集機(jī)制只知道怎樣釋放由new分配的內(nèi)存,所以它不知道如何釋放對(duì)象的“特殊”內(nèi)存。一旦垃圾收集機(jī)制準(zhǔn)備好釋放對(duì)象中占用的存儲(chǔ)空間,他首先調(diào)用finalize()。
finalize() 由Object定義
在構(gòu)造函數(shù)內(nèi)只進(jìn)行基本的初始化
定義初始化:
一個(gè)直接的做法是在定義數(shù)據(jù)成員的同時(shí)也為其賦值
可以調(diào)用一個(gè)方法進(jìn)行初始化
在構(gòu)造函數(shù)之前就進(jìn)行定義初始化
用一個(gè)類創(chuàng)建類的對(duì)象時(shí),先分配一個(gè)空間,依次做成員變量的定義初始化,再調(diào)用構(gòu)造函數(shù)。
● 靜態(tài)數(shù)據(jù)初始化
靜態(tài)的東西屬于類。
類Class與類對(duì)象。
如果一個(gè)變量是一個(gè)靜態(tài)變量的話,所有對(duì)象里的這個(gè)變量的值是同一個(gè)。
靜態(tài)數(shù)據(jù)成員只在這個(gè)類的第一個(gè)對(duì)象要?jiǎng)?chuàng)建的時(shí)候初始化(裝載這個(gè)類的時(shí)候)。
運(yùn)行java命令后,啟動(dòng)jvm,找到類的定義文件,找到類的定義文件之后,裝載;裝載完成之后在內(nèi)存里形成了一個(gè)類對(duì)象來代表這個(gè)類,然后要對(duì)這個(gè)類對(duì)象里的靜態(tài)成員變量進(jìn)行初始化
初始化順序
1.類型為Dog的一個(gè)對(duì)象首次創(chuàng)建時(shí),或者Dog類的靜態(tài)方法/數(shù)據(jù)首次訪問時(shí),Java解釋器必須找到Dog.class。
2.找到Dog.class后,它的所有的靜態(tài)初始化模塊都會(huì)運(yùn)行。因此,靜態(tài)初始化僅發(fā)生一次。
3.創(chuàng)建一個(gè)new Dog()時(shí),new語句首先會(huì)在堆里分配一個(gè)足夠的空間。
4.這個(gè)空間將會(huì)被清除為零,因此Dog中所有的數(shù)據(jù)成員都得到了缺省值。
5.執(zhí)行定義初始化。
6.執(zhí)行構(gòu)造函數(shù)。
先靜態(tài)后動(dòng)態(tài);先定義初始化后構(gòu)造函數(shù)。
● 顯式初始化
靜態(tài)初始化塊,地位相當(dāng)于一條靜態(tài)初始化語句
定義初始化塊,地位相當(dāng)于一條定義初始化語句
● 數(shù)組
數(shù)組代表一系列對(duì)象或者基本數(shù)據(jù)類型,所有相同類型的對(duì)象都封裝在一起——采用一個(gè)統(tǒng)一的標(biāo)識(shí)符名稱。
數(shù)組變量實(shí)際上是一個(gè)指向數(shù)組的句柄(引用),所以推薦使用int[] a這樣的書寫方式
通常情況下java的數(shù)組通過new出來: a1=new int[5],表示a1是一個(gè)引用,指向一個(gè)int型數(shù)組
使用length
對(duì)象數(shù)組
對(duì)于對(duì)象數(shù)組,數(shù)組的成員實(shí)際上是句柄(對(duì)象的引用)
對(duì)象數(shù)組也可以定義初始化
Integer i; i 為對(duì)對(duì)象的引用
● 隱藏實(shí)施過程——訪問控制
面向?qū)ο蟪绦蛟O(shè)計(jì)的一個(gè)概念:隱藏盡可能多的東西
庫創(chuàng)建者應(yīng)聲明哪些是客戶程序員可以使用的,哪些是不可一使用的
● 包:庫單元
用import來引入包或包里的成員。
import java.util.*; java.util 表示包名 *號(hào)表示包里的所有類
import java.util.Vector; 類的全名
目的是在所有對(duì)象范圍內(nèi)唯一的標(biāo)識(shí)一個(gè)類
之所以要這樣的引入,是為了提供一種特殊的機(jī)制,來實(shí)現(xiàn)命名空間的管理
● 編譯單元
每個(gè)編譯單元必須是以.java結(jié)尾的文件名稱,在一個(gè)編譯單元里,可以有一個(gè) public的類,這個(gè)類的名字必須與文件的名字相同。在一個(gè)單元內(nèi),可以有多個(gè)類,但只能有一個(gè)public的類。
編譯一個(gè).java文件時(shí),對(duì)應(yīng)于文件中的每一個(gè)類,會(huì)得到一個(gè).class文件,文件名與類的名字相同。一個(gè)程序是一堆.class文件。
● 定義包
一個(gè)庫是一堆這樣的.class文件,它們被定義為一個(gè)包,但是并不真正地合并在一個(gè)文件中。
包沒有什么管理機(jī)制,包只要聲明就可以了
package mypackage;
public class MyClass; //MyClass這個(gè)類就屬于mypackage這個(gè)包
現(xiàn)在,如果客戶程序員想要使用MyClass,就要用import來引入mypackage包,或者是使用MyClass的全名。
import mypackage; //引入mypackage包
MyClass m = new MyClass(); mypackage.MyClass m = new mypackage.MyClass();
//使用MyClass的全名
rt.jar java基礎(chǔ)類庫的所有包
使用jar命令來查看 |more
● CLASSPATH
- .表示當(dāng)前目錄 d:";. d盤根下是一個(gè)搜索的根
- CLASSPATH包含一個(gè)或多個(gè)目錄,它們作為一種特殊的根使用,從這里展開對(duì).class文件的搜索
● 類成員的訪問屬性
“Friendly” (缺省包)
public: 界面訪問 (accessor/mutator)
private: 不能接觸!
protected: "某種友好" 包內(nèi)可以訪問,子類也可以訪問。子類和父類不在一個(gè)包的情況下。
● 類的訪問控制
一個(gè)編譯單元(文件)中只能有一個(gè)public的類。因此一個(gè)編譯單元只有一個(gè)唯一的公共界面,其余的類都是"friendly"的。 public類的名字必須和文件的名字一樣。
可以,盡管很少見,一個(gè)編譯單元沒有一個(gè)public類,所有的類都是"friendly"的,那么文件名可以任意起。
● 繼承
class ThisClass extends SuperClass {
??? //??? class body
}
ThisClass是第三人稱彈數(shù),extend要加s---extends
● 傳遞構(gòu)造參數(shù)
先初始化父類的部分,在初始化自己的
-缺省構(gòu)造函數(shù)
-super(…) 調(diào)用父類的一個(gè)構(gòu)造函數(shù)并且傳遞參數(shù)
● 初始化和類的裝載
-先父類靜態(tài),后子類靜態(tài)
-先父類定義初始化,父類構(gòu)造函數(shù)
-后子類定義初始化,子類構(gòu)造函數(shù)
● Upcasting
-子類和父類之間的關(guān)系是: The new class is a type of the existing class.
-Upcasting是安全的.
● Method call binding
-早綁定(靜態(tài)綁定)) 晚綁定(動(dòng)態(tài)綁定)
-Java中所有的綁定都是晚綁定,除了final的方法
-早綁定有早綁定的優(yōu)點(diǎn),晚綁定有晚綁定的優(yōu)點(diǎn)。但是,晚綁定帶來了多態(tài)性。
-多態(tài)性就是把一個(gè)子類的對(duì)象當(dāng)作父類的對(duì)象來看待,然后讓它執(zhí)行父類所能執(zhí)行的函數(shù)。
靜態(tài)綁定:若方法類型為priavte static final 編譯器會(huì)準(zhǔn)確知道該調(diào)用哪個(gè)方法
動(dòng)態(tài)綁定:是很重要的特性,它能使程序變得可擴(kuò)展而不需要重編譯已存代碼
● 多態(tài)性
多態(tài)性就是指父類的某個(gè)方法被其子類重寫時(shí),可以各自產(chǎn)生自己的功能行為
● final
final : This cannot be changed
-final for data
-final for methods
-final for a class
● Final data
-只能被賦值一次的變量
-可以看作是常量
final Value v2 -- final的Value類的引用v2,final保護(hù)了對(duì)象的引用v2不被改變(這個(gè)引用的本身不能被改變)但是Value所指的對(duì)象是可以改變的
● Final Methods
-有兩種final方法:
1.在方法上加上一把鎖,防止繼承者改變它的意義。
2.編譯器把對(duì)該方法的調(diào)用變成inline(嵌入)調(diào)用。
-Private is Final,不存在override問題
● Final classes
-Final classes是不允許被繼承的。為防止他人從你的類上派生新類,此類是不可擴(kuò)展的。主要是安全上的作用。
● abstract類和abstract方法(抽象類和抽象方法)
可以定義某個(gè)類是抽象的(只制造概念)
-一個(gè)類的作用僅僅是表達(dá)接口,而不是具體的實(shí)現(xiàn)細(xì)節(jié)
-抽象的方法是不完全的,它只是一個(gè)聲明,沒有方法體
-包含一個(gè)抽象方法的類被稱作抽象類
-不能制造抽象類的對(duì)象
-從抽象類繼承的類必須override所有父類的抽象方法,否則子類本身成為一個(gè)抽象類
-可以聲明一個(gè)抽象類但是里面沒有一個(gè)抽象方法
關(guān)鍵字abstract定義抽象類
做這樣類的目的是禁止產(chǎn)生這樣類的對(duì)象
abstract類不能用new運(yùn)算符創(chuàng)建對(duì)象,必須產(chǎn)生其子類,由子類創(chuàng)建對(duì)象。
對(duì)于abstract方法,只允許聲明,而不允許實(shí)現(xiàn)
如果一個(gè)類是一個(gè)abstract類的子類,它必須具體實(shí)現(xiàn)父類的abstract方法
如果一個(gè)類中含有abstract方法,那么這個(gè)類必須用abstract來修飾(abstract也可以沒有abstract方法)
一個(gè)abstract類只關(guān)心它的子類是否具有某種功能,而不關(guān)心功能的具體行為,功能的具體行為由子類負(fù)責(zé)實(shí)現(xiàn)
● Interface
——totally abstract class(完全抽象的類)
-Interface在java中的地位和class一樣 可以繼承
-Interface沒有body(也沒有構(gòu)造函數(shù)),只表達(dá)概念
-在Interface中所有的方法都是public的,即使你沒有聲明它是public的。
-在Interface中所有的數(shù)據(jù)成員都是public static final的,即使你沒有聲名。但不能是blank final
使用implements,表示實(shí)現(xiàn)了什么功能
-Interface編譯后也生成一個(gè)class文件。其實(shí)Interface也是class,只不過是一種完全抽象的類
● 實(shí)現(xiàn)interface
-實(shí)現(xiàn)interface的類,其interface中所有的方法必須被“實(shí)現(xiàn)”,否則這個(gè)類成為一個(gè)抽象類。
-所有實(shí)現(xiàn)interface中的方法必須被申明為public
-Interface可以從多個(gè)Interface得到繼承,但是不能繼承類。
-為了克服單繼承的缺點(diǎn),Java使用了接口,一個(gè)類可以實(shí)現(xiàn)多個(gè)接口
-接口體中只進(jìn)行方法的聲明,不許提供方法的實(shí)現(xiàn),所以,方法的定義沒有方法體,且用分號(hào)結(jié)尾
-一個(gè)類通過使用implements聲明自己使用一個(gè)或多個(gè)接口,如使用多個(gè)接口,用逗號(hào)隔開接口名
-
要注意的是,接口中的方法被默認(rèn)是public的,所以類在實(shí)現(xiàn)接口方法時(shí),一定要用public來修飾。另外,如接口方法的返回類型不是void的,那
么在類中實(shí)現(xiàn)該接口方法時(shí),方法體至少要有一個(gè)return語句;如果是void型,類體除了兩個(gè)大括號(hào)外,也可以沒有任何語句。
-Java為我們提供的接口都在相應(yīng)的包中,通過引入包可以使用Java提供的接口,也可以自己定義接口,一個(gè)Java源文件就是由類和接口組成的。
● Inner class(內(nèi)部類)
-In Java 1.1, it is possible to place a class definition within another class definition.
-所謂內(nèi)部類就是定義在另外一個(gè)類內(nèi)部的類(某個(gè)類的定義,在另一個(gè)類的內(nèi)部)
新的消息機(jī)制需要有一個(gè)類能夠訪問另外一個(gè)類的私有成員
為了解決因?yàn)槎囝愵愅瑫r(shí)繼承一個(gè)很小的類時(shí),所帶來的命名問題。
-什么是使用一個(gè)類或訪問一個(gè)類:用這個(gè)類去制造對(duì)象
-類里面除了有成員變量、成員函數(shù),還有成員類,實(shí)際上內(nèi)部類可以稱之為成員類,成員類也具有成員函數(shù)和成員變量一樣的屬性。成員類可以訪問私有變量,成員類里面的所有的成員函數(shù)可以訪問內(nèi)部類外面那個(gè)類的所有私有變量。
-內(nèi)部類什么時(shí)候被初始化?編譯時(shí)生成幾個(gè)class文件?
每個(gè)內(nèi)部類生成一個(gè)class文件
1.一個(gè)內(nèi)部類的對(duì)象能夠訪問創(chuàng)建它的對(duì)象的實(shí)現(xiàn),包括私有數(shù)據(jù)
2.對(duì)于同一個(gè)包中的其他類來說,內(nèi)部類能夠隱藏起來
3.匿名內(nèi)部類可以很方便的定義回調(diào)
4.使用內(nèi)部類可以非常方便的編寫事件驅(qū)動(dòng)程序
● Private inner class
Inner classes可以完全被封閉起來,不被外界所看到
● Why inner classes?
兩個(gè)理由要在方法和scope中定義inner class:
-我們準(zhǔn)備實(shí)現(xiàn)某種形式的interface,使自己能創(chuàng)建和返回一個(gè)句柄。
-要解決一個(gè)復(fù)雜的問題,并希望創(chuàng)建一個(gè)類,用來輔助自己的程序,同時(shí)不愿意把類的細(xì)節(jié)公開。
在函數(shù)里面定義的類都加一個(gè)數(shù)字(序號(hào)),從1開始
有變量有函數(shù)就是一個(gè)類,這個(gè)類沒有名字,是匿名類,生成一個(gè)“父類名$序號(hào)”的class文件
子類送參數(shù)給父類的構(gòu)造函數(shù):在子類的構(gòu)造函數(shù)里用super
如何讓內(nèi)部類訪問外部類,被訪問的
匿名類沒有名字,也就沒有構(gòu)造函數(shù),定義初始化塊相當(dāng)于匿名類的構(gòu)造函數(shù)
● Outter class?
inner classer擁有訪問外部類的所有成員的能力,這是使用inner類的主要理由
父類與子類函數(shù)與函數(shù)之間的關(guān)系,如果函數(shù)名相同,參數(shù)表相同,則構(gòu)成override的關(guān)系。
私有的為靜態(tài)綁定
inner class 與 inner class 之間不會(huì)構(gòu)成override關(guān)系。
● Exception機(jī)制處理
但是如果你完全檢查任何時(shí)刻的錯(cuò)誤,你的代碼就會(huì)變成無法閱讀的夢魘。
所有的函數(shù)調(diào)用的返回值都要判斷,但是可能發(fā)生由于嵌套過多而造成代碼閱讀和維護(hù)困難,所以java里使用了try...catch,每一個(gè)catch針對(duì)一種錯(cuò)誤,將事務(wù)邏輯與錯(cuò)誤處理分開
-使用異常機(jī)制,讀、寫和調(diào)試代碼變得清晰。它把處理錯(cuò)誤的代碼和正常的代碼分開。
● Throw an exception
-throw new NullPointerException();
-throw new NullPointerException("HERE!");
異常發(fā)生時(shí),你不能解決問題,所以必須扔(throw)出一個(gè)異常。
1.一個(gè)異常對(duì)象建立起來了。
2.當(dāng)前運(yùn)行的路徑被停止,異常對(duì)象被彈出(eject)。
3.異常處理機(jī)制接管,開始尋找一個(gè)合適的地方來繼續(xù)執(zhí)行。
● Catch an exception
Java的異常機(jī)制的好處就在于它使我們在一個(gè)地方將精力集中在要解決的問題上,而在另一個(gè)地方處理來自那部分代碼的異常情況。
try { // code that may make exception
} catch ( Type1 id1) {
} catch ( Type2 id2) {
}
catch的匹配不是一種精確匹配,只要這個(gè)對(duì)象是那個(gè)類的對(duì)象就可以了
catch不管再多,只需滿足一個(gè)就結(jié)束了。
● Catch all kind of exception
一個(gè)捕捉任何異常的捕捉器是一個(gè)捕捉基本類型異常的捕捉器。
catch ( Exception e) {
System.out.println("caught an exception")
}
捕捉任何異常的catch
● Interface: Throwable
String getMessage();
String toString();
void printStackTrace();
void printStackTrace(PrintStream);
● Re-throwing
catch (Exception e) {
throw e;
}
-關(guān)于fillInStackTrace()
-也可以拋出一個(gè)與接收到的異常不同的異常
● Announce for exception
通知客戶程序員自己寫的方法中可能拋出什么樣的異常是一種文明的做法。
void f() throws tooBig, tooSmall, oldStyle { // Body of f() }
如果你要從你的方法中拋出某種異常,你必須申明。
但是你可以撒謊申明你并不真正拋出的異常。
● Override of exception
當(dāng)你override一個(gè)方法,你只能申明和拋出不比它的父類版本中申明的異常多的異常
● finally