Java基礎(chǔ)筆記(一) 面向?qū)ο?/h1>
[TOC]
1、定義類
[修飾符] class 類名
{
零到多個構(gòu)造器定義
零到多個Field
零到多個方法
}
其中的修飾符可以是public
狼电、final
浪默、abstract
或省略。
- 類也是引用數(shù)據(jù)類型救恨,用類定義的變量也只是一個引用(或者說指針)贸辈,里面只是存放了一個地址值。
-
static
修飾的方法不能直接訪問沒有static
修飾的成員。(理由很簡單:靜態(tài)成員是獨立于具體對象而存在擎淤,屬于類本身奢啥,而非靜態(tài)成員是依賴于具體的對象的) - Java里方法的參數(shù)傳遞方式只有一種:值傳遞∽炻#基本數(shù)據(jù)類型和引用數(shù)據(jù)類型都是將實參的一個副本傳給形參桩盲,只不過引用數(shù)據(jù)類型拷貝的是地址值!
2席吴、可變參數(shù)函數(shù)
JDK 1.5之后赌结,Java允許為方法指定數(shù)量不確定的形參,通過在最后一個形參的類型后增加三個點(…)孝冒,代碼實例如下:
public class MyClass {
/**
* 可變參數(shù)的方法
*/
public static void func(int a, String... str) {
for(String s : str) {
System.out.println(s);
}
System.out.println(a);
}
/**
* 程序入口-main
*/
public static void main(String[] args) {
func(15, "第一個字符串","第二個字符串","第三個字符串");
}
}
當然柬姚,如果你覺得這樣麻煩,可以直接用一個數(shù)組代替
3庄涡、方法重載
Java允許同一個類里定義多個同名方法量承,只要形參列表不同就行。
在Java中穴店,根據(jù)變量定義位置的不同撕捍,可以將變量分為兩大類:成員變量 和 局部變量
1、成員變量的初始化和內(nèi)存中的運行機制
- 當系統(tǒng)加載類泣洞、或者創(chuàng)建該類的實例時忧风,系統(tǒng)自動為成員變量分配內(nèi)存空間,并自動指定初始值斜棚。
- 類 Field(靜態(tài)成員變量),系統(tǒng)會在類加載時為其分配內(nèi)存空間该窗,并指定默認初始值弟蚀。
- 實例 Field 是在創(chuàng)建實例時分配內(nèi)存空間并指定初始值的,注意:實例變量指向的是這部分內(nèi)存酗失。
2义钉、局部變量的初始化和內(nèi)存中的運行機制
- 局部變量定義后,必須經(jīng)過顯式初始化后才能使用规肴,系統(tǒng)不會為局部變量執(zhí)行初始化捶闸。
- 也就是說,定義局部變量后拖刃,系統(tǒng)并未為這個變量分配內(nèi)存空間删壮,直到等到程序為這個變量賦初值時才分配,并將初值保存在這塊內(nèi)存中兑牡。
- 局部變量總是保存在其所在方法的棧內(nèi)存中央碟,所以它不屬于任何類或?qū)嵗?/li>
- 如果是基本類型的局部變量,則棧內(nèi)存中是變量的值均函;如果是引用類型的局部變量亿虽,則棧內(nèi)存中存放的是地址菱涤,引用堆內(nèi)存中的實際對象。
4洛勉、類的封裝
封裝是面向?qū)ο蟮娜筇卣髦徽掣选榱藢崿F(xiàn)良好的封裝,需要:
- 將 Field 和實現(xiàn)細節(jié)隱藏起來收毫,不允許外部直接訪問攻走。
- 把方法作為外部接口暴露出來,讓方法來控制對 Field 進行安全的訪問和操作牛哺。
Java中提供了4個訪問控制級別:private
陋气、protected
、public
和不加任何訪問控制符(default
)引润,它們的訪問控制級別由小到大:
package巩趁、import 和 import static
包(package):為了解決類的命名沖突,Java引入了包機制淳附,提供了類的多層命名空間议慰。
如果一個類被放于某個包中,則我們應(yīng)該在該Java源文件的第一個非注釋行添加如下代碼:
package packageName;
import
語句可以導(dǎo)入指定包下某個類或全部類奴曙,但import
語句并不是必需的别凹,只要堅持在類里面使用其他類的全名,則可以無須使用import
語句洽糟。
注意:在JDK 1.5以后增加了一種靜態(tài)導(dǎo)入(import static
)的語法炉菲,用于導(dǎo)入指定類的某個靜態(tài) Field、方法或該類全部的靜態(tài) Field坤溃、方法拍霜。
import static package.subpackage...className.fieldName; // 導(dǎo)入某一靜態(tài)變量
import static package.subpackage...className.methodName; // 導(dǎo)入某一靜態(tài)方法
import static package.subpackage...className.*; // 導(dǎo)入該類的所有靜態(tài)Field、方法
用一句話歸納import
和import static
的作用:使用import可以省略寫包名薪介,而使用import static則可以連類名都省略祠饺。
4、Java的常用包
Java的核心類都放在java
這個包及其子包下汁政,Java擴展的許多類都放在javax
包及其子包下道偷。下面幾個包是Java語言中的常用包:
-
java.lang
:這個包下包含了Java語言的核心類,如 String记劈、Math勺鸦、System 和 Thread 類等,使用這個包下的類無須使用 import 語句導(dǎo)入目木,系統(tǒng)會自動導(dǎo)入這個包下的所有類祝旷。 -
java.util
:這個包下包含了Java的大量工具類/接口和集合框架類/接口,例如 Arrays、List 和 Set 等怀跛。 -
java.net
:這個包下包含了一些Java網(wǎng)絡(luò)編程相關(guān)的類/接口距贷。 -
java.io
:這個包下包含了一些Java輸入/輸出編程相關(guān)的類/接口。 -
java.text
:這個包下包含了一些Java格式化相關(guān)的類吻谋。 -
java.sql
:這個包下包含了Java進行 JDBC 數(shù)據(jù)庫編程的相關(guān)類/接口忠蝗。 -
java.awt
:這個包下包含了抽象窗口工具集(Abstract Window Toolkits)的相關(guān)類/接口,這些類主要用于構(gòu)建 GUI 程序漓拾。 -
java.swing
:這個包下包含了 Swing 圖形用戶界面編程的相關(guān)類/接口阁最,這些類可用于構(gòu)建平臺無關(guān)的 GUI 程序。
5骇两、構(gòu)造器
構(gòu)造器也就是構(gòu)造函數(shù)K僦帧!低千!
Java類可以包含一個或一個以上的構(gòu)造器配阵。一旦程序員提供了自定義的構(gòu)造器,系統(tǒng)就不再提供默認的無參構(gòu)造器了示血。(所以如果為一個類編寫了有參數(shù)的構(gòu)造器棋傍,通常建議為該類也額外提供一個無參數(shù)的構(gòu)造器)
6、類的繼承
繼承是面向?qū)ο蟮娜筇卣髦荒焉蟆ava的繼承具有單繼承的特點瘫拣,每個子類只有一個直接父類。
繼承的語法格式:
修飾符 class Derive extends Base
{
// 類定義部分
}
Java使用extends
作為繼承的關(guān)鍵字告喊,extends
在英文中是擴展的意思麸拄。
重寫父類的方法要遵循“兩同兩小一大”的規(guī)則:
- “兩同”:方法名相同,形參列表相同黔姜。
- “兩小”:子類方法返回值類型應(yīng)比父類方法返回值類型更小或相等拢切,子類方法聲明拋出的異常類應(yīng)比父類方法聲明拋出的異常類更小或相等。
- “一大”:子類方法的訪問權(quán)限應(yīng)比父類方法的訪問權(quán)限更大或相等地淀。
如果需要在子類方法中調(diào)用父類中被覆蓋的方法失球,若被覆蓋的是實例方法岖是,使用super
作為調(diào)用者帮毁;若被覆蓋的是類方法,使用父類類名作為調(diào)用者豺撑。
7烈疚、構(gòu)造器的執(zhí)行順序
子類不會獲得父類的構(gòu)造器,但子類構(gòu)造器里可以調(diào)用父類構(gòu)造器聪轿。有如下幾種情況:
- 子類構(gòu)造器函數(shù)體的第一行使用
super
顯式調(diào)用父類構(gòu)造器爷肝。 - 子類構(gòu)造器函數(shù)體的第一行使用
this
顯示調(diào)用本類中重載的構(gòu)造器,執(zhí)行本類中另一個構(gòu)造器時即會調(diào)用父類構(gòu)造器。 - 子類構(gòu)造器函數(shù)體中既沒有
super
調(diào)用灯抛,也沒有this
調(diào)用金赦,系統(tǒng)將會在執(zhí)行子類構(gòu)造器之前,隱式調(diào)用父類無參數(shù)的構(gòu)造器对嚼。
不管上面哪種情況夹抗,當調(diào)用子類構(gòu)造器來初始化子類對象時,父類構(gòu)造器總會在子類構(gòu)造器之前執(zhí)行纵竖;不僅如此漠烧,執(zhí)行父類構(gòu)造器時,系統(tǒng)會再次上溯執(zhí)行其父類構(gòu)造器……依此類推靡砌,創(chuàng)建任何Java對象已脓,最先執(zhí)行的總是java.lang.Object
類的構(gòu)造器。
8通殃、多態(tài)
多態(tài)是面向?qū)ο蟮娜筇卣髦弧?/p>
Java引用變量有兩個類型:一個是編譯時類型度液,一個是運行時類型。編譯時類型由聲明該變量時的類型決定邓了,運行時類型由實際賦給該變量的對象決定恨诱。兩個類型不一致時,就可能出現(xiàn)多態(tài)骗炉。
當把一個子類對象直接賦給父類引用變量時照宝,這個引用變量的編譯時類型是 BaseClass,而運行時類型是 SubClass句葵,當運行時調(diào)用該引用變量的方法時厕鹃,其方法行為總是表現(xiàn)出子類方法的行為特征,而不是父類方法的行為特征乍丈。也就是說:相同類型的變量 調(diào)用同一個方法時剂碴,呈現(xiàn)出多種不同的行為特征,這就是多態(tài)轻专。
多態(tài)的兩個前提: 要有繼承(inheritance)忆矛,要有方法重寫(override)。
9请垛、instanceof 運算符
instanceof
是Java中的一個二元運算符催训,它的作用是在運行時判斷左邊對象是否是右邊類(或其子類)的實例。如果是宗收,返回true
漫拭,否則返回false
。
public class MyClass {
public static void main(String[] args) {
String str = ""; // str 是String類型引用變量
Object obj = ""; // obj 的編譯時類型是 Object混稽,但實際類型是 String
System.out.println("str 是 String 的實例:" + (str instanceof String)); // true
System.out.println("str 是 Object 的實例:" + (str instanceof Object)); // true
System.out.println("obj 是 String 的實例:" + (obj instanceof String)); // true
System.out.println("obj 是 Object 的實例:" + (obj instanceof Object)); // true
System.out.println("obj 是 Math 的實例:" + (obj instanceof Math)); // false
}
}
需要注意:instanceof
運算符前面操作數(shù)的編譯時類型要么與后面的類相同采驻,要么與后面的類具有父子繼承關(guān)系审胚,否則會引起編譯錯誤。
instanceof
運算符的常用之處:在進行強制類型轉(zhuǎn)換之前礼旅,首先判斷前一個對象是否是后一個類的實例膳叨,是否可以成功轉(zhuǎn)換,從而保證代碼更加健壯痘系。
10懒鉴、初始化塊
初始化塊是Java類里可出現(xiàn)的第4種成員(前面依次有 Field、方法和構(gòu)造器)碎浇。與構(gòu)造器的作用類似临谱,初始化塊也可以對Java對象進行初始化操作。
初始化塊的語法格式如下:
[修飾符] {
// 可執(zhí)行代碼
...
}
初始化塊的修飾符只能是static
奴璃,使用 static 修飾的初始化塊被稱為靜態(tài)初始化塊悉默。
一個類里可以有多個初始化塊,先定義的初始化塊先執(zhí)行苟穆,后定義的初始化塊后執(zhí)行抄课,下面是一個例子:
public class MyClass {
{
int a = 5;
System.out.println("第一個初始化塊!");
}
{
System.out.println("第二個初始化塊雳旅!");
}
public MyClass() {
System.out.println("類的無參數(shù)構(gòu)造器跟磨!");
}
public static void main(String[] args) {
new MyClass(); // 創(chuàng)建一個對象
}
}
控制臺輸出結(jié)果:
第一個初始化塊!
第二個初始化塊攒盈!
類的無參數(shù)構(gòu)造器抵拘!
可以看出,初始化塊是在構(gòu)造器之前執(zhí)行的型豁。創(chuàng)建一個 Java 對象時僵蛛,不僅會執(zhí)行該類的普通初始化塊和構(gòu)造器,而且系統(tǒng)會一直上溯到java.lang.Object
類迎变,先執(zhí)行 java.lang.Object 類的初始化塊充尉,開始執(zhí)行 java.lang.Object 的構(gòu)造器,依次向下執(zhí)行其父類的初始化塊衣形,開始執(zhí)行其父類的構(gòu)造器……最后才執(zhí)行該類的初始化塊和構(gòu)造器驼侠,返回該類的對象。
雖然 Java 允許一個類中定義多個的普通初始化塊谆吴,但這沒有任何意義倒源,所以如果要使用初始化塊的話定義一個就行了。
11纪铺、初始化塊和構(gòu)造器的區(qū)別
初始化塊總是在構(gòu)造器之前執(zhí)行相速。雖然它們的作用非常相似碟渺,但依然存在一些差異的鲜锚。
與構(gòu)造器不同的是突诬,初始化塊是一段固定執(zhí)行的代碼,它不能接受任何參數(shù)芜繁。因此旺隙,如果有一段初始化的代碼對所有對象完全相同,且無須接收任何參數(shù)骏令,就可以把這段初始化代碼提取到初始化塊中蔬捷。
通過把多個構(gòu)造器中的相同代碼提取到初始化塊中,能更好地提高初始化代碼的復(fù)用榔袋,提高整個應(yīng)用的可維護性周拐。
12、靜態(tài)初始化塊
初始化塊的修飾符只能是static
凰兑,使用 static 修飾的初始化塊被稱為靜態(tài)初始化塊妥粟。
靜態(tài)初始化塊,也屬于類的靜態(tài)成員吏够,因此靜態(tài)初始化塊不能訪問非靜態(tài)成員(包括實例Field和實例方法)勾给。靜態(tài)初始化塊用于對整個類進行初始化處理,通常用于對類Field執(zhí)行初始化處理锅知。
系統(tǒng)將在類初始化階段執(zhí)行靜態(tài)初始化塊播急,而不是在創(chuàng)建對象時才執(zhí)行。因此售睹,靜態(tài)初始化塊總是比普通初始化塊先執(zhí)行桩警。與普通初始化塊類似的是,系統(tǒng)在類初始化階段不僅會執(zhí)行本類的靜態(tài)初始化塊昌妹,還會一直上溯到 java.lang.Object 類(如果它包含靜態(tài)初始化塊)生真,從上往下依次執(zhí)行其父類的靜態(tài)初始化塊……最后才執(zhí)行該類的靜態(tài)初始化塊。經(jīng)過這個過程捺宗,才完成了該類的初始化柱蟀。而只有類完成初始化以后,才可以在系統(tǒng)中使用這個類蚜厉,包括訪問這個類的類Field长已、類方法,或者用這個類來創(chuàng)建實例昼牛。
13术瓮、包裝類
Java 是面向?qū)ο蟮木幊陶Z言,但它也包含了 8 種基本數(shù)據(jù)類型贰健“模基本數(shù)據(jù)類型的數(shù)據(jù)不具備“對象”的特性:沒有Field、方法可以被調(diào)用伶椿。
所有引用類型的變量都繼承了Object
類辜伟,都可當成 Object 類型變量使用氓侧,但基本數(shù)據(jù)類型的變量卻不可以。為了解決這個問題导狡,Java 提供了包裝類(Wrapper Class)约巷,可以把 8 個基本類型的值包裝成對象使用。
把基本數(shù)據(jù)類型變量 包裝成 對應(yīng)的包裝類對象 是通過對應(yīng)包裝類的構(gòu)造器來實現(xiàn)的旱捧,不僅如此独郎,8個包裝類中除了 Character 之外,還可以通過傳入一個字符串來構(gòu)建包裝類對象枚赡。
public class MyClass {
public static void main(String[] args) {
boolean b1 = true;
int i1 = 5;
Boolean _b = new Boolean(b1);
Integer _i = new Integer(i1);
Float _f = new Float("3.14");
// 取出包裝類對象里的值
boolean b2 = _b.booleanValue();
int i2 = _i.intValue();
float f2 = _f.floatValue();
}
}
可能你會覺得氓癌,這樣的轉(zhuǎn)換有些繁瑣。但從 JDK 1.5 開始提供了自動裝箱(Autoboxing) 和 自動拆箱(AutoUnboxing)功能贫橙,即可以把一個基本類型變量直接賦給對應(yīng)的包裝類變量或 Object 變量(自動裝箱)顽铸,也可以把包裝類對象直接賦給一個對應(yīng)的基本類型變量。
14料皇、基本類型變量與字符串的轉(zhuǎn)換
15谓松、toString( )方法
toString()
方法是 Object 類里的一個實例方法,而所有的 Java 類都是 Object 類的子類践剂,因此所有的 Java 對象都具有 toString() 方法鬼譬。
不僅如此,所有的 Java 對象都可以和字符串進行連接運算逊脯,也可以使用System.out.println()
進行輸出优质。當進行上面的操作時,系統(tǒng)會自動調(diào)用 Java 對象的 toString()
方法军洼,使用其返回的字符串巩螃。
Object 類的toString
方法是一個“自我描述”的方法,它總是返回該對象實現(xiàn)類的“類名@hashCode”值匕争。但是這個返回值并不能真正實現(xiàn)“自我描述”的功能避乏,這時可以對這個方法進行重寫。
16甘桑、==和equals的區(qū)別
Java 程序中判斷兩個變量是否相等有兩種方式:一種是使用==
運算符拍皮,另一種是使用equals
方法。
- 對于基本類型變量來說跑杭,它們并沒有
equals
方法铆帽,只能使用==
判斷兩個變量的值是否相等。 - 對于引用類型變量來說德谅,
==
運算符是判斷兩個引用變量是否指向內(nèi)存中的同一個對象爹橱,也就是比較對象的內(nèi)存地址;而equals
是比較兩個對象的值是否相等(String類窄做,Integer類等等)愧驱。
需要知道的是慰技,equals 方法是 Object 類的一個實例方法。在 Object 類中equals
方法和==
沒有任何區(qū)別冯键,都是判斷兩個變量是否指向同一個對象。<u>而String類庸汗,Integer類等等一些類惫确,是重寫了equals方法,才使得equals和“==”不同蚯舱。</u>
所以改化,當自己創(chuàng)建類時,想要自定義相等的標準枉昏,必須重寫equals方法陈肛。
17、final修飾符
Java 提供了final
關(guān)鍵字來修飾變量兄裂、方法和類句旱。系統(tǒng)不允許為 final
變量重新賦值,子類不允許覆蓋父類的final
方法晰奖,不允許繼承final
類谈撒。
- final 成員變量必須由程序員顯式地指定初始值,系統(tǒng)不會對 final 成員變量進行隱式初始化匾南。對于 final 修飾的類 Field啃匿,必須在聲明該Field時或在靜態(tài)初始化塊中指定初始值;對于 final 修飾的實例 Field蛆楞,必須在聲明該Field時溯乒、普通初始化塊或構(gòu)造器中指定初始值。
- 前面說過豹爹,系統(tǒng)不會為局部變量執(zhí)行隱式初始化裆悄,必須由程序員顯式指定。對于 final 修飾的局部變量臂聋,可以在聲明時指定初始值灯帮,也可以在后面的代碼中對其賦值,但只能一次逻住。
- final 修飾基本類型變量時钟哥,表示變量的值不能被改變;final 修飾引用類型變量時瞎访,表示該變量所引用的地址不能被改變腻贰,即一直引用同一個對象,但這個對象是可以改變的扒秸。
- 當定義 final 變量時就為該變量指定了初始值播演,而且該初始值可以在編譯時就被確定下來冀瓦,那么這個變量就變成了“宏變量”。編譯器會把程序中所有用到該變量的地方直接替換成該變量的值写烤。
18翼闽、抽象類與抽象方法
Java 中使用abstract
修飾符來定義抽象類和抽象方法。有抽象方法的類必須定義成抽象類洲炊,但抽象類里可以沒有抽象方法感局。
抽象類不能被實例化,只能當作父類被其他子類繼承暂衡。抽象方法沒有函數(shù)體询微,必須由子類提供實現(xiàn)(即重寫)。
與abstract
不能同時使用的關(guān)鍵字:
- final和abstract不能同時使用狂巢,因為它們是對立的撑毛。
- static和abstract不能同時修飾某個方法,因為如果一個抽象方法被定義成靜態(tài)方法唧领,通過類名調(diào)用該方法將出現(xiàn)錯誤藻雌。
- private和abstract不能同時修飾某個方法,因為抽象方法必須被子類重寫才有意義斩个,而子類不能訪問和重寫父類的 private 方法蹦疑。
19、接口(interface)
上面說到萨驶,抽象類既可以包含抽象方法歉摧,也可以普通方法。而接口(interface)是一種更徹底的抽象腔呜,接口里的所有方法都是抽象方法叁温。
接口定義的是多個類共同的公共行為規(guī)范,故它里面通常是定義一組公用方法核畴∠サ基本語法如下:
[修飾符] interface 接口名 extends 父接口1,父接口2...
{
零個到多個常量定義...
零個到多個抽象方法定義...
}
修飾符可以是 public 或者省略,如果省略了 public 訪問控制符谤草,則默認采用包權(quán)限訪問控制符跟束。另外,與類繼承不同的是丑孩,接口繼承中一個接口可以有多個直接父接口(接口只能繼承接口而不能繼承類)冀宴。
由于接口是一種規(guī)范,因此接口里不能包含構(gòu)造器和初始化塊温学。接口里可以包含3種成員: Field(只能是常量)略贮、方法(只能是抽象方法)、內(nèi)部類(包括內(nèi)部接口、枚舉)逃延。
- 接口里所有成員都是
public
訪問權(quán)限览妖。 - 接口里的常量 Field 是使用
public static final
修飾符來修飾,不管定義時是否指定揽祥。 - 接口里的方法是自動使用
public abstract
修飾符修飾讽膏,不管定義方法時是否指定。 - 接口里的內(nèi)部類(接口拄丰、枚舉類)是自動使用
public static
修飾符修飾府树,不管定義時是否指定。
接口不能用于創(chuàng)建實例愈案,其主要用途是被實現(xiàn)類實現(xiàn)挺尾。實現(xiàn)使用implements
關(guān)鍵字:
[修飾符] class 類名 extends 父類 implements 接口1,接口2...
{
// 類體部分
}
一個類只能有一個直接父類鹅搪,但一個類可以實現(xiàn)多個接口站绪。實現(xiàn)接口與繼承父類相似,也可以獲得所實現(xiàn)的接口里定義的成員丽柿,因此可以把實現(xiàn)接口理解為一種特殊的繼承恢准。
20、接口與抽象類的比較
相同點:
- 接口和抽象類都不能被實例化甫题,它們都用于被其他類實現(xiàn)或繼承馁筐。
- 接口和抽象類都可以包含抽象方法,實現(xiàn)接口或繼承抽象類的普通子類都必須實現(xiàn)這些抽象方法坠非。
不同點:
- 接口里只能包含抽象方法敏沉,而抽象類既可以抽象方法也可以包含普通方法,還可以沒有抽象方法炎码。
- 接口里不能定義靜態(tài)方法(因為全部是抽象方法)盟迟,抽象類里可以定義靜態(tài)方法。
- 接口里只能定義靜態(tài)常量 Field潦闲,而抽象類既可以定義普通 Field攒菠,也可以定義靜態(tài)常量 Field。
- 接口里不包含構(gòu)造器和初始化塊歉闰,而抽象類里完全可以包含辖众。
- 一個類最多只能有一個直接父類,但卻可以直接實現(xiàn)多個接口(彌補Java單繼承的不足)和敬。
21凹炸、內(nèi)部類
在Java類里只能包含5種成員:Field、方法昼弟、構(gòu)造器还惠、初始化塊左冬、內(nèi)部類(包括接口和枚舉類)舷嗡。前四種類成員已經(jīng)介紹過了,下面介紹一下內(nèi)部類。
內(nèi)部類也叫嵌套類婶熬,語法格式:
public class OuterClass
{
// 此處可以定義內(nèi)部類
}
通常,我們把內(nèi)部類作為成員內(nèi)部類來定義炉爆,而不是作為局部內(nèi)部類(在方法里定義的內(nèi)部類)蔬浙。
非靜態(tài)內(nèi)部類里不允許定義靜態(tài)成員,而靜態(tài)內(nèi)部類里可以定義靜態(tài)成員誊爹,也可以定義非靜態(tài)成員蹬刷。
根據(jù)靜態(tài)成員不能訪問非靜態(tài)成員的規(guī)則,外部類的靜態(tài)方法不能使用非靜態(tài)內(nèi)部類频丘,靜態(tài)內(nèi)部類也不能訪問外部類的非static成員办成。
22、枚舉類
枚舉類是一種不能自由創(chuàng)建對象的類搂漠,它的對象在定義類時已經(jīng)固定下來迂卢。枚舉類特別適合定義像行星、季節(jié)這樣的類桐汤,它們能創(chuàng)建的實例是有限且確定的而克。
在 Java 1.5 以前,要定義一個枚舉類怔毛,必須手動去實現(xiàn)员萍。下面就是一個 Season 枚舉類的例子:
public class Season {
private final String name;
private final String description;
public static final Season SPRING = new Season("春天","春暖花開");
public static final Season SUMMER = new Season("夏天","夏日炎炎");
public static final Season FALL = new Season("秋天","秋高氣爽");
public static final Season WINTER = new Season("冬天","圍爐賞雪");
// 私有化構(gòu)造器
private Season(String name, String description) {
this.name = name;
this.description = description;
}
// 只為兩個 Field 提供 getter 方法
public String getName() {
return name;
}
public String getDescription() {
return description;
}
}
上面的 Season 類是一個不可變類,它只能創(chuàng)建4種對象拣度,可以通過Season.SPRING的方式來取得 Season 對象碎绎。
Java 1.5 新增了一個enum
關(guān)鍵字,用以定義枚舉類:
public enum Season {
SPRING,SUMMER,FALL,WINTER;
}
枚舉類(enum)是一種特殊的類抗果,它一樣可以有自己的 Field筋帖、方法和構(gòu)造器,可以實現(xiàn)一個或者多個接口窖张。因為它特殊幕随,所以有幾點需要注意:
- 用
enum
定義的枚舉類默認繼承了java.lang.Enum
類,而不是繼承 Object 類宿接。 - 用
enum
定義的非抽象的枚舉類默認使用 final 修飾赘淮,因此枚舉類不能派生子類。 - 枚舉類的構(gòu)造器默認使用且只能使用
private
訪問控制符修飾睦霎。 - 枚舉類的所有實例必須在枚舉類的第一行顯式列出梢卸,并且系統(tǒng)會自動添加
public static final
修飾。