Core Java筆記(一)

sun考試: SCJP:只考core java SCJD:+jdbc+swing
SCWCD:+servlet+jsp(JAVA EE) SCEA:+EJB+Webserver(架構師)

必須養成優秀程序員的編寫習慣:縮進(用空格)、註釋、命名約定。
大小寫敏感。
單獨的“;”代表一條空語句。
main函數是我們整個程序的執行入口所以必須是靜態公開的。
必須寫成這樣: public static void main(String[]args){…}

生成jar包:
在eclipse裏,選中要打包的幾個文件,右鍵-Export-寫文件名-Next-Next-選main方法的class-finish
在jar包的同一文件夾下,新建一個空文檔,寫“java -jar ./文件名.jar”,再把這文檔改成“文件名.sh”
把這sh的屬性-權限 改成“允許以程序執行文件”。以後雙擊這個sh即可運行

文本註釋 Comments:
註釋必須寫上,以便其他人閱讀、引用和維護。
單行註釋 //…
多行註釋 /* ….*/
文檔註釋 /* … /
文檔註釋,可以使用JDK的javadoc工具從原文件中抽取這種註釋形成程序的幫助文檔。
使用javadoc命令建立HTML格式的程序文檔:
javadoc[options][packagenames][sourcefiles][@files]

標示符:
用來給一個類、變量或方法命名的符號
標示符命名規則:
1. 以字母,“_”和“ ”。
2. 大小寫敏感
3. 不能與保留關鍵字衝突
4. 沒有長度限制(暗示使用長的標示符,以便閱讀。長名字可使用工具輸入)
5. 建議使用JavaBeans規則命名,並根據方法的目的,以 set、get、is、add 或 remove 開頭。
標示符命名約定:
1. 類名、接口名:每個單詞的首字母應該大寫,尤其第一個單詞的首字母應該大寫。(駝峯規則)
class MyFirstClass
interface Weapon
2. 字段、方法以及對象:第一個單詞首字母應小寫,其他單詞首字母大寫。(以便跟上面的有所區別)
boolean isWoman
void setName(String name)
3. 常量:全部用大寫字母表示。如果由幾個單詞組成,則由下畫線連接。
public final int GREEN
public final int HEAD_ COUNT
4. Java包(Package):全部用小寫字母。
package java.awt.event

java.lang.System.gc(); / java.lang.Runtime.gc();
垃圾回收的建議語句,只能建議而不能強制回收
注意: System.gc(); 是靜態方法,可直接調用。
java.lang.Runtime.gc(); 不是靜態方法,不能直接在main方法裏調用

package 包
目的:命名衝突,便於管理類
運行時,先找到包所在目錄,再執行“ 包名.類名”
import 導入。導入包內的類
定義包之後,執行時:javac -d 包的路徑 類名.java
java 包名.類名
import java.util.; //表示導入java.util裏面的所有類;但 import java.; 則什麼類都導不進
用“*”表示導入當前包的類,不包括子包的類(可把包看作目錄)。

聲明規則
* 一個源代碼文件最多隻能有一個公共(public)類。
* 如果源文件包含公共類,則該文件名稱應該與公共類名稱相同。
* 一個文件只能有一個包語句,但是,可以有多個導入語句。
* 包語句(如果有的話)必須位於源文件的第一行。
* 導入語句(如果有的話)必須位於包之後,並且在類聲明之前。
* 如果沒有包語句,則導入語句必須是源文件最前面的語句。
* 包和導入語句應用於該文件中的所有類。
* 一個文件能夠擁有多個非公共類。
* 沒有公共類的文件沒有任何命名限制。

輸入:使用Scanner 獲取輸入
在J2SE 5.0中,可以使用java.util.Scanner類別取得使用者的輸入
可以使用這個工具的 next() 功能,來獲取用戶的輸入
Scanner s = new Scanner(System.in);
System.out.printf(“您輸入了字符: %s \n”, s.next());
System.out.printf(“您輸入了數字: %d \n”, s.nextInt());
輸入:使用 BufferedReader 取得輸入//5.0之前的讀取鍵盤的方法
BufferedReader建構時接受java.io.Reader物件
可使用java.io.InputStreamReader
例: import java.io.InputStreamReader;
import java.io.BufferedReader;
class n{
public static void main(String[] args){
System.out.println(“請輸入一列文字,包括空格:”);
BufferedReader s = new BufferedReader(new InputStreamReader(System.in));
String next;
try{next = s.readLine();//此語句會拋異常,需處理
System.out.println(“您輸入了文字:” + next);
}catch(Exception e){}
}}

數值保存方式:
正數= 二進制
負數= 補碼
補碼= 反碼 +1 正數=負數的補碼(反碼+1)
反碼= 非(二進制數)

八進制數,零開頭 011(八進制)=9(十進制)
十六進制數,零x開頭 0x55(十六進制)=5*16+5(十進制)

類型:數據都必須有類型
boolean (8bit,不定的)只有true和false兩個值
char 16bit, 0~2^16-1 (2^16=6萬6)
byte 8bit, -2^7~2^7-1 (2^7=128; 注意:兩個 byte 數相加,變 int 型)
short 16bit, -2^15~2^15-1 (2^15=32768)
int 32bit, -2^31~2^31-1 (2147483648,20億,10位有效數字)
long 64bit, -2^63~2^63-1 (900億億,20位有效數字)
float 32bit, 9位有效數字,含小數(四捨五入)(小數點算一位,正負號不算)
double 64bit, 18位有效數字
注:float 和 double 的小數部分不可能精確,只能近似。
比較小數時,用 double i=0.01; if ( i - 0.01 < 1E-6) …
不能直接 if (i==0.01)…

默認,整數是int類型,小數是double類型
long類型值,需跟L或l在數據後;float類型要跟f或F;或強制類型轉換
科學計數法:12.5E3

類型轉換默認序列:
byte  >  short   > int  >  long   >  float  >  double
               char 」
注意:默認類型轉換(自動類型提升)會丟失精度,但只有三種情況:
int>float; long>float; long>double.   看一下他們的有效位就明白。
二進制是無法精確的表示 0.1 的。
進行高精度運算可以用java.math包中BigDecimal類中的方法。
自動類型提升又稱作隱式類型轉換。

強制類型轉換:int ti;  (byte) ti ;
強制轉換,丟棄高位

宣告變量名稱的同時,加上“final”關鍵詞來限定,這個變量一但指定了值,就不可以再改變它的值
如:final int n1= 10;   n1=20;  這就會報錯

輸出命令:
System.out.println() 會自動換行的打印
System.out.print() 直接打印,不會自動換行
System.out.printf() 可插入帶 % 的輸入類型,前兩種只可以插入轉義符, 不能插入 % 的數據或字符串
在 printf 裏面,輸出有5個部分 %[argument_index][flags][width][.precision]conversion[ ][flags][寬度][.精確度][格式]
printf()的引入是爲了照顧c語言程序員的感情需要
格式化輸出 Formatter;格式化輸入 Scanner;正則表達式

輸出格式控制:
轉義符:
\ddd 1到3位8進制數指定Unicode字符輸出(ddd)
\uxxxx 1到4位16進制數指定Unicode字符輸出(xxxx)
\ \
\’ ’
\” ”
\b 退格(光標向左走一格)
\f 走紙轉頁,換頁
\n 換行
\r 光標回到行首,不換行
\t 跳格

%% %
%d 輸出10進位整數,只能輸出Byte、Short、 Integer、Long、或BigInteger類型。(輸出其他類型會拋異常)
%f 以10進位輸出浮點數,提供的數必須是Float、Double或 BigDecimal (輸出Integer類型也拋異常)
%e,%E 以10進位輸出浮點數,並使用科學記號,提供的數必須是Float、 Double或BigDecimal
%a,%A 用科學記號輸出浮點數,以16進位輸出整數部份,以10進位輸出指數部份,數據類型要求同上。
%o (字母o)以8進位整數方式輸出,限數據類型:Byte,Short,Integer,Long或BigInteger
%x,%X 將浮點數以16進位方式輸出,數據類型要求同上
%s,%S 將字符串格式化輸出(可輸出任何類型)
%c,%C 以字符方式輸出,提供的數必須是Byte、Short、Character或 Integer
%b,%B 輸出”true”或”false”(%B輸出”TRUE”或”FALSE”);另外,非空值輸出true,空值輸出 false
%t,%T 輸出日期/時間的前置,詳請看在線API文件

/找出各字符的Unicode值***********/
class Test{
public static void main(String[] args) {
String s= “”+0+’a’; //0=48,9=57
//A=65,Z=90;a=97,z=122;空格=32
int i = s.codePointAt(0);
int j = s.codePointAt(1);
//利用這codePointAt(int index)方法
System.out.printf(“%d %d”,i,j);
}}
/************************************/

字符串的拼接:
字符串+數值=字符串
數值+字符串=字符串
如:str+10+20 ==str1020 而 10+20+str ==30str
“+” 和 “+=” 都被重載了,具有合併字符串的能力,相當於 String 類裏的 concat();

運算:
算術運算: 加( +) 減(-) 乘( * ) 除( / ) 取餘( % )
% 取餘運算: 2%3=2 100%3=1
賦值運算符:
= += -= *= /= %=
(先運行完右邊的,再跟左邊的進行賦值運算;如 int i=10;i-=3*5;結果-5)
<<= >>=
比較、條件運算:
大於> 不小於>= 小於< 不大於<= 等於== 不等於 !=
邏輯運算:
短路運算(且 && 或 || ) 非短路運算(& | ) 反相 !
短路運算:當前面一個表達式可以決定結果時,後面的語句不用再判斷。非短路運算時,還照樣判斷後面的
位運算:
&(AND) |(OR) ^(XOR異或) ~(補碼)按位取反 = 加1再取反(全 1 的補碼是-1)
移位運算:

<< >>>

 >>右移:全部向右移動,移到右段的低位被捨棄,最高位則移入原來最高位的值。右移一位相當於除2取商。
 >>>同上,只是最高位移入0(不帶符號)。因爲最高位是符號位,所以負數跟 >> 有區別,正數沒區別。
 12>>>33  爲12>>(33%32) = 12>>1  =6;因爲int 型只有32位,認爲全移走後就沒意義
 1 <<32 爲1
instanceof():用戶判斷某一個對象是否屬於某一個類的實例。
“==”雙等於號,比較數值是否相等。還可以用於比較兩個引用,看他們引用的地址是否相等。
在 Object 類裏 equals() 跟“==”功能一樣;但可以重載定義一個比較兩者意義是否相等的方法。
在java裏可以把賦值語句連在一起寫,如: x=y=z=5;   這樣就x,y,z都得到同樣的數值 5

兩個數相運算時,默認是 int 類型
如果有更高級的,就按高級的那個類型
if(其中一個是double型)double型;
else if(其中一個是float型)float型;
else if(其中一個是long型)long型;
else int 型。

選擇:
if(…){…}else{…}
if(…){…}else if(…){…}
if(…){… if(…){…}}

三重以上的選擇,建議使用 switch
switch(char c){
    case c1: ...; break;
    case c2: ...; break;
    ...
    default :...;
} /*switch的括號裏只能用 int 和 枚舉類型
    能隱式轉換爲 int 的也可以:byte,short,char,Integer,Short,Character,Byte等。
    不能用 long、小數類型(float,double) 和 String。
    case後的值必須是常量。而包裝類變量(Integer,Character)不會被視作常量。*/

循環:
for(初始表達式; 布爾表達式 ; 步進 ) 循環語句;
跟C的 for 一樣,for 的初始化條件、結束條件、增量都可以不寫。
但條件判斷部分只能是boolean值,所以只能是一條條件判斷語句。
for 循環一般用在循環次數已知的情況。
while ()…;
do…; while (); 注意:do 後最好用“{}”,while 後的分號不可忘。

break 和 continue
break 退出當前的循環體,在嵌套循環中,只退出當前的一層循環。
continue 結束當前本次循環,繼續進行下一輪的循環。可以說,只是本次忽略循環內後面的語句。
continue 只能在循環體內用。break 可以用在任意代碼塊中,表示退出當前程序塊(配合標籤使用,很好用)
這兩個相當於JAVA裏的 goto 語句。

注意:(個人歸結的)
循環體內申明的變量,在循環體結束後立即釋放,循環體外無法使用。
但在另外一個循環體內可以再次申明一個跟前面同名的變量,互相不影響。
如for內定義的 i: for(int i=0;i<10;i++){…}
則在上式 for 循環結束後無法再調用 i 值,還會報錯。
for(int i=0;i<10;i++){…} 和後面的 for(int i=0;i<3;i++){…} 互不影響
若想循環體外還可以調用 for 循環體內的值,應先在體外定義。
如: int i; for (i=0; i<10; i++){…} 則for 循環後再調用 i 值,其值爲10

關鍵字列表:
abstract boolean break byte case catch char class
continue default do double else extends enum false
final finally float for if implements import instanceof
int interface long native new null package private
protected public return short static super switch synchronized
this throw throws transient true try void volatile while
Java 中 true、false不是關鍵字,而是boolean類型的字面量。但也不能當作變量用。
所有的關鍵字都是小寫,friendly,sizeof不是java的關鍵字
保留字:const,goto :這兩個已經削去意義,但同樣不能用作變量名。

第三章 對象
名詞
對象:
類: 一類屬性相同的對象
屬性:是什麼樣
方法:能做什麼(C 中叫作函數)

對象:
聲明:Student s ;
這時我們只是說明s是一個能夠指向Student類型的引用(相當於C++中的指針),並沒有創建一個對象。
所以我們此時不能對s做任何操作。
初始化:s = new Student();
向系統申請一塊存儲空間(地址空間),該地址空間保存的是一個Student類型的數據。
而s中保存的就是該地址空間的首地址。
變量:內存空間中一塊具有固定長度的,用來保存數據的地址空間。(s也是一個變量)
一個對象可以有多個引用指向。
Student[] s = new Student[3] 只是相當於聲明一個長度爲 3 的Student類型的數組。

實例變量和局部變量
實例變量:
1、在一個類中,任何方法之外定義的變量;
2、從面向對象的思想來說我們又把實例變量看成一個類的屬性。
3、實例變量在沒有符初值時系統會自動幫我們做初始化:
整型數據初始化爲 0,布爾型數據初始化爲 false,對象類型初始化爲 null。
實例變量的作用域在本類中完全有效,當被其他的類調用的時候也可能有效。
局部變量:
1、在方法內定義的變量叫局部變量。
2、局部變量使用前必須初始化,系統不會自動給局部變量做初始化。
3、局部變量的生命範圍在他所在的代碼塊,在重合的作用域範圍內不允許兩個局部變量命名衝突。
注:局部變量與實例變量允許同名,在局部變量的作用域內,其優先級高於實例變量。
我們可以用 this.實例變量名 以區分局部變量。

第四章  數組

數組:
數組也是對象
數組中保存着多個相同類型的元素
數組中的每一個元素都是變量
可以創建數組對象,但數組裏只能放對象的引用,不能直接放對象進去

數組的創建:
1. 聲明一個int數組變量,數組變量是數組對象的遙控器
int[] nums;
2. 創建大小爲7的數組,並將它賦值給變量nums
nums = new int[7];
3. 賦於int數組每一個元素一個int值
nums[0] = 6; nums[1] = 34; nums[2] = 23; nums[3] = 4;
多維數組:
1. 定義方式:type 維數 arrayName;
如: int[][] b = new int [2] [1];
2. 分配內存空間,有兩種方法:
直接爲每一維分配空間: int[][] a = new int[2][3];
分別爲每一維分配空間 int[][] a = new int[2][ ]; //列數可以沒有,行數則一定要有
a[0] = new int[3]; a[1] = new int[5]; //a[][] 看成一維數組
可以爲每行設置爲空間大小不同的數組。
3. 初始化,有兩種方式:
先定義數組,分配空間,然後直接對每個元素進行賦值(一個個寫,或用for函數)
在定義數組的同時進行初始化。
如:int a[][] = {{2,3}, {1,5}, {3,4}};
java實質上把多維數組看作一維數組,但數組裏的元素也是一個數組,即數組的數組
多維數組的長度 = 行數; (a.length=行數; a[0].length=列數)

創建數組對象的另外幾種方式:
Int[] nums = {6,34,23,4,15,0, 57}; (java 形式)
這方法只能在初始化定義的時候可以,以後再想定義nums={…}就不行了
Int[] nums = new int[] {6,34,23,4,15,0, 57};
這句的後一個 int[] 內不能填數字,怕人弄錯數目;
這句可以先 int[] nums;以後再另外定義 nums = new int[]{…}
[]可以換換位置,如:
Int nums[]; (C 和 C++ 形式)
注意: short [] z [] []; //這是合法的,定義一個三維數組
聲明數組時,不能定義其大小;只有 new 數組時可以定大小。

數組元素的默認值:
byte short int long 爲 0
float double 爲 0.0
char 爲 ‘\0’
boolean 爲 false
引用類型爲null

數組的 length 屬性:
表示數組的長度,是指這個數組最多能保存的元素個數
length屬性只能被讀取,不能被修改
java.lang.ArrayIndexOutOfBoundsException: (這是數組下標越界的報錯)

隨機數:
Math.random(); //可以產生隨機的0~1 的小數,不需導包
java.util.Random; //可以產生更加多種的隨機數
0~100的一個隨機整數(包括0,但不包括100):
Double d = 100*Math.random(); int r = d.intValue(); //方法一
Random r = new Random(); int num = r.nextInt(100); //方法二;需要 import java.util.Random;
可以直接在程序中寫這句,而臨時導入 int i = new java.util.Random().nextInt(100);

Arrays.sort(數組名)
排序算法。需導入 impor java.util.Arrays;

數組的拷貝:
1. 用 for 語句,將數組的元素逐個賦值。直接如果直接將數組 a = 數組b;則是將b的指針賦給a
2. 用System.arraycopy();
arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
src - 源數組。
srcPos - 源數組中的起始位置。
dest - 目標數組。
destPos - 目標數據中的起始位置。
length - 要複製的數組元素的數量。
如:System.arraycopy(a, 0, b, 0, a.length); //把數組 a 全部複製到數組 b 中

在java中對面向對象(OO)的要求
1.對象是客觀存在的,萬物皆對象。
(注:看不見的對象並不表示該對象不存在,比如說事件);
2.簡單性:採用面向對象方法可以使系統各部分各司其職各盡所能。
3.複用性:對象的功能越簡單其可重用性越高。
4.弱耦合性:各司其職各盡所能。
5.高內聚性:一個對象獨立完成一個功能的能力
6.類是一類事務的共性,是人類主觀認識的一種抽象,是對象的模板。

面向過程與面向對象的對比
面向過程:先有算法,後有數據結構。先考慮怎麼做。
面向對象:先有數據結構,後有算法。先考慮用什麼做。

第六章 構造方法
方法的聲明(分爲五個部分)
1.方法的修飾符(可以有多個,且順序無關)
2.方法的返回值類型
3.方法名
4.方法的參數列表
如果方法有參數,一定要以正確的數量、類型、和順序傳遞參數;可以將變量當作參數傳入,但要類型相符
5.方法允許拋出的例外(異常)
注:編譯器只能做語法上的檢查,而不能進行邏輯上的檢查。
Java中不允許有廢話,永遠不會執行的語句不允許寫。
1. 聲明格式:
([argument_list>])[throws ]{}
例如:public String getName(){return name;}
2. 當沒有返回值時,返回類型必須被定義爲 void。
3. 構造方法沒有返回類型。
4. 返回類型必須與方法名相鄰,其他修飾符號可以調換位置。

參數傳遞
在java方法傳參過程中簡單類型是按值傳遞,對象類型是按引用傳遞。
按值傳遞傳遞的是數據的副本。
按引用傳遞 傳遞的是保存該數據的地址
Java語言總是使用傳值調用,這意味着方法得到的只是所有參數值的拷貝。
因此,方法不能修改傳遞給它的任何參數變量的內容。
對象類型的參數傳遞的也是該對象的引用值
方法中並不能改變對象變量,但能通過該變量調用對象的方法或修改對象的成員。

方法的參數基本上與局部變量相同,但你不需要直接初始化它
編譯器會確保方法調用時會有與聲明相符的參數傳進來,且參數會自動被賦值

形參 VS 實參:
形參(形式參數):相當於函數(Java中也把函數稱之爲方法)中的局部變量
在函數被調用時創建,並以傳入的實參作爲起始值,函數調用結束時被釋放
不會影響主程序中其他的變量(即使有變量跟他們同名),因爲他們是不同作用域的變量,互不干擾。
實參:調用函數時,實際傳給函數形式參數的數據。

重載(Overload)
在同一個類中,允許同時存在一個以上的同名函數,只要他們的參數列表不同即可。
參數列表不同,可以是參數的類型或個數不同,也可以是不同類型參數的順序不同。
1、相同方法名,不同參數表。
2、方法重載時,對於參數的匹配有個向上就近原則。(這樣可以節省棧空間資源);
3、爲什麼面向對象中要有方法重載?
方法的重載使同一類方法由於參數造成的差異對於對象的使用者是透明的。
對象的使用者只負責把參數交給對象,而具體怎麼實現由對象內部決定。
4、Java中的運算符重載
java中唯一重載的運算符是String類型的“+”號,任何類型+String類型結果都爲Stirng類型。
5、注意點:重載不僅出現在同一個類中,也可以出現在父子類中。
重載的方法只是剛好有相同名字的不同方法

方法的覆蓋 (Override) 重寫
繼承之後,想改變由父類繼承下來的方法。
1. 同樣的方法名、參數列表、返回類型(從Java 5 起,返回類型可以是子類型)
2. 訪問權限不能更小
3. 異常不能更寬 (可以拋出更少或是更窄的檢查異常,或者任何非檢查異常)

重構 (extract Method)
消除代碼的重複,提高代碼的可維護性。整理凌亂的代碼,把可重用的代碼塊包裝起來。
常用重複的方法封裝成工具類(工具類太多則做成工具箱),一般都是靜態方法和常量,沒有屬性。
在eclipse裏,選中要重構的代碼,右鍵Refactor-Extract Mathod 或(Shift+Alt+M)

創建對象的步驟
1、分配空間
2、初始化屬性
3、調用構造方法
注:構造方法不能手工調用,在對象的生命週期內構造方法只調用一次。

構造方法 (參考day05的 TestCat.java)
構造方法是在生成對象的過程中調用的方法,但構造方法並不能創建對象。
new 對象的時候需要調用構造方法。
1、特點:沒有返回值(連void也沒有),方法名與類名相同。(如果加上 void 會變成普通方法。)
2、在不寫構造方法時,系統會自動生成一個無參的構造方法。
3、請養成在每個類中自己加上無參構造方法的習慣。

格式爲:public ClassName(){}
    構造方法也可以是其他的限制符――private protected default
  private 一般用在 singleton 模式中。
在一個對象的生成周期中構造方法只用一次,一旦這個對象生成,那麼這個構造方法失效。
* 接口不能創建實例,因爲沒有構造方法

可以構造多個構造方法,但多個構造方法的參數表一定不同,或參數順序不同
即屬於不同的構造方法:-----------------------> 構造方法的重載

使用構造方法來初始化對象的狀態:把初始化代碼放到構造方法中,並且把構造方法設定成需要參數的
編譯器一定會幫你寫出沒有參數的構造方法嗎?不會
    如果你已經寫了一個有參數的構造方法,並且你需要一個沒有參數的構造方法,則你必須自己動手寫
    如果類有一個以上的構造方法,則參數列表一定要不一樣,我們可以認爲這幾個構造方法形成重載關係
    如果我們提供了有參的構造方法,那麼系統不會再提供無參的構造方法了。
    這樣當被子類繼承時,如果子類構造方法不人爲調用父類的有參構造方法就會出現異常。
構造方法可以通過 this 調用另外一個構造方法(this 此時必須在第一行語句)

匿名對象:
創建對象時,直接調用對象的方法而不定義對象的句柄。
如: person p1 = new person; p1.shout();
改寫成: new person.shout(); //此方法執行完,此匿名對象也就變成了垃圾。
使用匿名對象的情況:
1. 此對象只需要一次方法調用。
2. 此對象作爲實參傳給一個函數調用。

this 當前對象 (參考day05 的TestThis.java)
誰調用該方法,在這一時刻誰就是該方法的當前對象;是個隱式參數,代表被構造的對象。
用this來區分實例變量和局部變量。
this.實例變量名 = 局部變量名 (將局部變量賦值給實例變量)
this()表示調用本類的其他構造方法,且只能放在一個方法中的第一行第一句。
構造方法可以通過this調用另外一個構造方法(this此時必須在第一行語句)
*super 關鍵字也是個隱形參數,代表被構造對象的父類。
同樣也必須在構造方法的第一行

對象和對象引用的區別
對象好比一臺電視機,對象引用好比電視機遙控。對象引用 中存的是對象的地址。
多個對象引用中存放的是同一個地址,表示該對象被多個對象引用所引用。

面向對象的三大特性:
封裝(Encapsulation)、繼承(Inheritance)、多態polymiorphism

封裝:
1.定義:指一個對象的內部狀態對外界是透明的,對象與對象之間只關心對方有什麼方法,而不關心屬性。
封裝使實現的改變對架構的影響最小化。封裝後的代碼更具有安全性、可擴展性和可維護性。
2.原則:封裝使對象的屬性儘可能的私有,根據需要配上相應的get/set方法,對象的方法儘可能的公開。
該隱藏的一定要隱藏,該公開的一定要公開。
3.方法公開的是聲明而不是實現。使方法實現的改變對架構的影響最小化。
4.訪問權限控制從嚴到寬
private :僅本類成員可見
default :本類+同包類可見(默認)
protected:本類+同包+不同包的子類
public :公開
注:這裏的同包指的是跟父類所在的包相同。
5、完全封裝:屬性全部私有,並提供相應的get/set方法。
優點:
1.事物的內部實現細節隱藏起來
2.對外提供一致的公共的接口――間接訪問隱藏數據
3.可維護性

一、繼承:
1 定義:基於一個已存在的類構造一個新類。
繼承已存在的類就是複用這些類的方法和屬性,在此基礎上,還可以在新類中添加一些新的方法和屬性。
2 父類到子類是從一般到特殊的關係。
3 繼承用關鍵字extends
dog extends Animal :表示狗類繼承了動物類
4 Java中只允許單繼承(java簡單性的體現)
父子類之間的關係是樹狀關係。(而多繼承是網狀關係)
5 父類中的私有屬性可以繼承但是不能訪問。
也可以說父類中的私有屬性子類不能繼承。
6 原則:父類放共性,子類放個性。
7 構造方法不能被子類繼承。

父類的成員能否繼承到子類?
  private:本類內部可以訪問  不能繼承到子類
 (default):本類內部可以訪問,同包其他類也可以訪問
        能否繼承到子類? 不一定:同包的可繼承,不同包則不可繼承。
  protected:本類內部可以訪問,不同包的子類也可以訪問, 同包其他類也可以訪問
        能繼承到子類       
  public:任何地方都可以訪問  能繼承到子類

繼承的意義:
1. 避免了重複的程序代碼,提高了程序的可重用性
2. 定義出共同的協議

二、帶繼承關係的對象創建的過程
1.遞歸的構造父類對象
2.分配空間
3.初始化屬性
4.調用本類的構造方法

三、super 關鍵字
1.super()表示調用父類的構造方法
2.super()也和this一樣必須放在構造方法的第一行第一句。不是構造方法則不用第一行。
3.super.表示調用父類的方法或屬性。例:super.m();
4.super 可以屏蔽子類屬性和父類屬性重名時帶來的衝突
5.在子類的構造函數中如果沒有指定調用父類的哪一個構造方法,就會調用父類的無參構造方法,即super()

指向父類的引用
 super.age
 super.addAge()
調用父類的構造方法
 super();
 super(“wangcai”,8);

一個對象的創建過程
1. 當構造一個對象的時候,系統先構造父類對象,再構造子類對象。
2. 構造一個對象的順序:(注意:構造父類對象的時候也是這幾步)
遞歸地創建父類的 static 成員(即使只調用其子類靜態成員,也會先創建父類靜態成員);
順序地創建本類的 static 成員(只要調用這個類的屬性或方法都需創建一次);
遞歸地創建父類對象(先創建父類非靜態成員,再調用父類構造方法);
順序地創建本類非靜態成員(包括屬性和方法);
調用本類的構造方法(它可調用本類或父類的成員,也可調用本類的其他構造方法)。
創建完成了(更多詳情參看下面:類加載的順序)

四、白箱複用和黑箱複用
1.白箱複用:又叫繼承複用,子類會繼承父類所有的東西,
從某種程度上說白箱複用破壞了封裝。是一種 is a 的關係。
例:class Liucy{
public void teachCpp(){System.out.println(“Teach Cpp”);}
public void chimogu(){ }
}
class Huxy extends Liucy{}

2、黑箱複用:又叫組合複用,是一種 has a 的關係。
例:class Liucy{
      public void teachCpp(){System.out.println("Teach Cpp");}
      public void chimogu(){    }
    }
   class Huxy {
      private Liucy liucy = new Liucy();
      public void teachCpp(){liucy.teachCpp();}
    }
原則:組合複用取代繼承複用原則。
     使我們可以有機會選擇該複用的功能。

多態
1.定義:是指一個對象可以有多種形態,換句話說多態使我們可以把一個子類對象看作是一個父類對象類型
(例:father A = new child() )。
多態指的是編譯時的類型變化,而運行時類型不變。
2.多態分爲兩種:編譯時多態和運行時多態。
編譯時類型:定義時類型(主觀概念)把它看作什麼。
運行時類型:真實類型(客觀概念) 實際上他是什麼。
重載是編譯時多態,覆蓋是運行時多態。在方法重載的情況下,參數類型決定於編譯時類型。
3.作用:在需要一類對象的共性時,可以很容易的抽取。並且可以屏蔽不同子類對象之間所不關心的差異。
多態方便寫出更通用的代碼,以適應需求的不斷變化
4.多態常見的用法:
(1)、多態用在方法的參數上
(2)、多態用在方法的返回類型上
5.運行時多態的三原則:
(1)、對象不變(改變的是主觀認識)
(2)、對於對象的調用只能限於編譯時類型的方法。
(3)、在程序的運行時,動態類型判定。運行時調用運行時類型,即他調用覆蓋後的方法。
注意:多態時,只有一般方法是動態調用的;而 static 方法和 final 方法依然是靜態調用的;屬性全是靜態調用的。
如:father A = new child(); 則A的一般方法是child的方法;但A的屬性是father的屬性。
同樣:child C = new child(); 則 (father)C 的一般方法還是child的方法,但屬性是father的屬性。

if(cat instanceof Animal){ … } //如果cat屬於Animal類型則執行
強制類型轉換,在迫不得已的時候再用。因爲很容易出錯。

第八章:高級語言特性
靜態變量 static
一個類只有一個靜態變量,跟對象沒有關係。被類的所有實例共享;如果子類沒有覆蓋,也共享父類的靜態成員。
一般直接使用類名來訪問 “類名.靜態變量名”。可以在沒有任何實例時調用。
在某種意義上類似於全局變量(Java裏沒有全局變量,這只是C和C++的說法)
不能在 static 方法或代碼塊裏訪問非 static 成員(變量或方法)
能繼承和覆蓋,但覆蓋 static 方法必須也是 static 的方法。

1.可以修飾屬性、方法、初始代碼塊,成爲類變量、靜態方法、靜態初始化代碼塊。
   注:初始代碼塊是在類中而不是在任何方法之內的代碼塊。
2.類變量、靜態方法、靜態初始化代碼塊與具體的某個對象無關,只與類相關,是全類公有的。 在類加載時初始化。
3.類加載:JVM通過CLASSPATH找到字節碼文件,並將字節碼文件中的內容通過I/O流讀到JVM並保存的過程
   在虛擬機的生命週期中一個類只被加載一次。
   注:Java命令的作用是啓動JVM (Java Virtual Mechine)。
4.tatic 定義的是一塊爲整個類共有的一塊存儲區域,其發生變化時訪問到的數據都是經過變化的。
5.爲什麼主方法必須是靜態的?
   主方法是整個應用程序的入口,JVM只能通過類名去調用主方法。
6.類變量和靜態方法可以在沒有對象的情況下用:類名.方法名(或屬性名)來訪問。
7.靜態方法不可被覆蓋(允許在子類中定義同名的靜態方法,但是沒有多態)
   父類如果是靜態方法,子類不能覆蓋爲非靜態方法。父類如果是非靜態方法,子類不能覆蓋爲靜態方法。
   爭論:靜態方法可以覆蓋但是沒有多態。
   思考:沒有多態的覆蓋叫覆蓋嗎?
   在靜態方法中不允許調用本類中的非靜態成員。
8.靜態初始化代碼塊只在類加載的時候運行一次,以再也不執行了。所以靜態代碼塊一般被用來初始化靜態成員。
9.不加static爲動態初始化代碼塊,在創建對象時被調用(在構造函數之前)。
10.最後要注意的一點就是 static 不能修飾局部變量。

什麼時候類加載
第一次需要使用類信息時加載。
類加載的原則:延遲加載,能不加載就不加載。

觸發類加載的幾種情況:
(1)、調用靜態成員時,會加載靜態成員真正所在的類及其父類。
通過子類調用父類的靜態成員時,只會加載父類而不會加載子類。
(2)、第一次 new 對象的時候 加載(第二次再 new 同一個類時,不需再加載)。
(3)、加載子類會先加載父類。
注:如果靜態屬性有 final 修飾時,則不會加載,當成常量使用。
例:public static final int a =123;
但是如果上面的等式右值改成表達式(且該表達式在編譯時不能確定其值)時則會加載類。
例:public static final int a = math.PI
如果訪問的是類的公開靜態常量,那麼如果編譯器在編譯的時候能確定這個常量的值,就不會被加載;
如果編譯時不能確定其值的話,則運行時加載

類加載的順序:
1.加載靜態成員/代碼塊:
先遞歸地加載父類的靜態成員/代碼塊(Object的最先);再依次加載到本類的靜態成員。
同一個類裏的靜態成員/代碼塊,按寫代碼的順序加載。
如果其間調用靜態方法,則調用時會先運行靜態方法,再繼續加載。同一個類裏調用靜態方法時,可以不理會寫代碼的順序。
調用父類的靜態成員,可以像調用自己的一樣;但調用其子類的靜態成員,必須使用“子類名.成員名”來調用。
2.加載非靜態成員/代碼塊:
先遞歸地加載父類的非靜態成員/代碼塊(Object的最先);再依次加載到本類的非靜態成員。
同一個類裏的非靜態成員/代碼塊,按寫代碼的順序加載。同一個類裏調用方法時,可以不理會寫代碼的順序。
但調用屬性時,必須注意加載順序。一般編譯不通過,如果能在加載前調用,值爲默認初始值(如:null 或者 0)。
調用父類的非靜態成員(private 除外),也可以像調用自己的一樣。
3.調用構造方法:
先遞歸地調用父類的構造方法(Object的最先);默認調用父類空參的,也可在第一行寫明調用父類某個帶參的。
再依次到本類的構造方法;構造方法內,也可在第一行寫明調用某個本類其它的構造方法。
注意:如果加載時遇到 override 的成員,可看作是所需創建的類型賦值給當前類型。
其調用按多態用法:只有非靜態方法有多態;而靜態方法、靜態屬性、非靜態屬性都沒有多態。
假設子類override父類的所有成員,包括靜態成員、非靜態屬性和非靜態方法。
由於構造子類時會先構造父類;而構造父類時,其所用的靜態成員和非靜態屬性是父類的,但非靜態方法卻是子類的;
由於構造父類時,子類並未加載;如果此時所調用的非靜態方法裏有成員,則這個成員是子類的,且非靜態屬性是默認初始值的。

成員,包括變量和方法
成員變量,包括實例變量和靜態變量

final 修飾符
(最終的、最後的)當final修飾時,不能被改變,不能被繼承
1.final 可以用來修飾類、屬性和方法、局部變量。
2.final 修飾一個屬性時,該屬性成爲常量。
(1)對於在構造方法中利用final進行賦值時,此時在構造之前系統設置的默認值相對於構造方法失效。
(2)對於實例常量的賦值有兩次機會
在初始化的時候通過聲明賦值
在構造的時候(構造方法裏)賦值
注:不能在聲明時賦值一次,在構造時再賦值一次。
注意:當final修飾實例變量時,實例變量不會自動初始化爲0;但必須給他賦值才能通過編譯。
3.final 修飾方法時,該方法成爲一個不可覆蓋的方法。這樣可以保持方法的穩定性。
如果一個方法前有修飾詞private或static,則系統會自動在前面加上final。
即 private 和 static 方法默認均爲 final 方法。
4.final 常常和 static、public 配合來修飾一個實例變量,表示爲一個全類公有的公開靜態常量。
例: public static final int a = 33;
在這種情況下屬性雖然公開了,但由於是一個靜態常量所以並不算破壞類的封裝。
5.final 修飾類時,此類不可被繼承,即final類沒有子類。
一個 final 類中的所有方法默認全是final方法。
final 不能修飾構造方法,構造方法不能被繼承更談不上被子類方法覆蓋。

關於 final 的設計模式:不變模式
1、不變模式:一個對象一旦產生就不可能再修改( string 就是典型的不變模式);
通過不變模式可以做到對象共享;
2、池化思想:用一個存儲區域來存放一些公用資源以減少存儲空間的開銷。
有池的類型:boolean,byte,int,short,long,char,(池範圍在-127~128之間)
(float,double 等小數沒有池)
例:在String類中有個串池(在代碼區)。
池:堆裏的一片獨立空間。目的是拿空間換時間,讓運算效率更高。
(1)如果用Stirng str = “abc” 來創建一個對象時,則系統會先在“串池”中尋找有沒有“abc”這個字符串
如果有則直接將對象指向串池中對應的地址,如果沒有則在串池中創建一個“abc”字符串。
所以:String str1 = “abc”;
String str2 = “abc”;
Str1 == str2 返回值是ture;他們的地址是一樣的。
也就是說str1和str2都指向了代碼空間中相同的一個地址,而這個地址空間保存就是是字符串”abc”
字符串是不可改變的類型,所以可以共享。所以串池裏不會有相同的兩個字符串。

 (2)如果用String str = new String("abc")則直接開闢一塊內存放"abc"這個字符串。
     所以上面這語句,創建兩個"abc",一個在池,一個是對象
     String str2 = new String("abc");
     Str == str2 返回值是false;他們的地址是不一樣的。
     即是說str和str2分別指向了堆空間中不同的兩個地址,而這兩個地址空間保存的都是字符串"abc"

StringBuffer 類(java.lang下的)。
對於字符串連接
String str=”1”+”2”+”3”+”4”;
產生:
12 123 1234
這在串池中產生多餘對象,而我們真正需要的只有最後一個對象,這種方式在時間和空間上都造成相當大的浪費。
所以我們應該使用 StringBuffer(線程安全的) 或者 StringBuilder(線程不安全的)來解決
解決方案:
StringBuffer sb = new StringBuffer(“1”);
Sb.append(“2”);
Sb.append(“3”);
Sb.append(“4”);
S = sb.toString();
解決後的方案比解決前在運行的時間上快2個數量級。
StringBuilder (1.5版本後出現的)
線程不安全的,在多線程併發時會出現問題。但仍是字符串合併的首選。
運行效率比 StringBuffer 快一倍。

abstract 抽象
1.可用來修飾類、方法
2.abstract 修飾類時,則該類成爲一個抽象類。
抽象類不可生成對象(但可以有構造方法留給子類使用),必須被繼承使用。
抽象類可以聲明,作爲編譯時類型,但不能作爲運行時類型。
abstract 永遠不會和 private,static,final 同時出現。( 因爲抽象必須被繼承。)
3.abstract 修飾方法時,則該方法成爲一個抽象方法,抽象方法不能有實現;由子類覆蓋後實現。
比較:private void print(){};表示方法的空實現
abstract void print();表示方法爲抽象方法,沒有實現
4.抽象方法從某中意義上來說是制定了一個標準,父類並不實現,留給子類去實現。
注:抽象類中不一定要有抽象方法,但有抽象方法的類一定是抽象類。
抽象類可以有抽象方法和非抽象方法。實現抽象類的第一個具體類必須實現其所有抽象方法。
5.關於抽象類的設計模式:模板方法
靈活性和不變性

interface 接口
1、定義:接口不是類,而是一組對類需求的描述,這些類要遵從接口描述的統一格式進行定義。
定義一個接口用關鍵字 interface。
例:public interface a{……}
2、接口是一種特殊的抽象類。
在一個接口中,所有的方法爲公開、抽象的方法,所有的屬性都是公開、靜態、常量。
所以接口中的所有屬性可省略修飾符:public static final。也只能用這三個修飾符。
接口中所有的方法可省略修飾符:public abstract。但這些都是默認存在的。
3、一個類實現一個接口必須實現接口中所有的方法,否則其爲一抽象類。而且實現類的方法需要 public
實現接口用關鍵字 implements.
所謂實現一個接口就是實現接口中所有的方法。
例:class Aimple implements A{……..};
4、一個類除了繼承另一個類外(且只能繼承一個類),還可以實現多個接口(接口之間用逗號分割)。
接口可以實現變相的多繼承。
例:class Aimple extends Arrylist implements A,B,C{…}
5、不能用“new 接口名”來實例化一個接口,但可以聲明一個接口。
6、接口與接口之間可以多繼承。
例:interface face1 extends face2,face3{}
接口的繼承相當於接口的合併
7、接口的作用
(1)、間接實現多繼承。
用接口來實現多繼承並不會增加類關係的複雜度。因爲接口不是類,是在類的基礎上的再次抽象。
父類:主類型 接口:副類型
典例:父親(主) 和 老師(副)
(2)、允許我們爲一個類定義出混合類型。
(3)、通過接口制定標準
接 口:標準的定義 定義標準
接口的調用者:標準的使用 使用標準
接口的實現類:標準的實現 實現標準
接口的回調:先有接口的使用者,再有接口的實現者,最後把接口的實現者的對象傳到接口的使用者中,
並由接口的使用者通過接口來調用接口實現者的方法。
例:sun公司提供一套訪問數據庫的接口(標準),java程序員訪問數據庫時針對數據庫接口編程。
接口由各個數據庫廠商負責實現。
(4)、解耦合作用:採用接口可以最大限度的做到弱耦合,將標準的實現者與標準的制定者隔離
(例:我們通過JDBC接口來屏蔽底層數據庫的差異)
8、接口的編程設計原則
(1)、儘量針對接口編程(能用接口就儘量用接口)
(2)、接口隔離原則(用若干個小接口取代一個大接口)
這樣可以只暴露想暴露的方法,實現一個更高層次的封裝。
9、注意點:
(1)、一個文件只能有一個 public 接口,且與文件名相同。
(2)、在一個文件中不能同時定義一個 public 接口和一個 public 類。
(3)、接口與實體類之間只有實現關係,沒有繼承關係;
抽象類與類之間只有繼承關係沒有實現關係。接口與接口之間只有繼承關係,且允許多繼承。
(4)、接口中可以不寫 public,但在子類實現接口的過程中 public 不可省略。

接口 VS 抽象類
1、接口中不能有具體的實現,但抽象類可以。
2、一個類要實現一個接口必須實現其裏面所有的方法,而抽象類不必。
3、通過接口可以實現多繼承,而抽象類做不到。
4、接口不能有構造方法,而抽象類可以。
5、實體類與接口之間只有實現關係,而實體類與抽象類只有繼承關係
抽象類與接口之間既有實現關係又有繼承關係。
6、接口中的方法默認都是公開抽象方法,屬性默認都是公開靜態常量,而抽象類不是。

修飾符的使用情況:
(Y表可用;不寫表示不可用)
修飾符 類 屬性 方法 局部變量(所有局部變量都不能用修飾符)
public Y Y Y
protected Y Y
(default) Y Y Y
private Y Y
static Y Y
final Y Y Y Y
abstract Y Y

訪問權限控制:
修飾符 同一個類 同一個包 (不同包)子類 其他包
public Y Y Y Y
protected Y Y Y
(default) Y Y
private Y

Object類
1、object類是類層次結構的根類,他是所有類默認的父類。
2、object類中的其中三個方法。
(1)、finalize()
當一個對象被垃圾收集的時候,最後會由JVM調用這個對象的finalize方法;
注意:這個方法一般不用,也不能將釋放資源的代碼放在這個方法裏;只有調用C程序時,纔可能要用到

(2)、toString()
存放對象地址的哈希碼值。
返回一個對象的字符串表示形式。打印一個對象其實就是打印這個對象toString方法的返回值。
可以覆蓋類的toString()方法,從而打印我們需要的數據。 Public String toString(){……}

(3)、equals(Object obj)
    用來判斷對象的值是否相等。前提是覆蓋了equals方法。Object類中的equals方法判斷的依然是地址
    注意:String類已經覆蓋了equals方法,所以能用equals來判斷String對象的值是否相等。

下面是覆蓋equals方法的標準流程:
/***************************************************************/
public boolean equals(Object obj){
//第一步:現判斷兩個對象地址是否相等
if(this == obj) return true;
//第二步:如果參數是null的話直接返回false;
if(obj == null) return false;
//第三步:如果兩個對象不是同一個類型直接返回false
if (getClass() != obj.getClass()) return false;
//?? if(!(this.getClass.getName().equals(o.getClass.getName())) return false;
//第四步:將待比較對象強轉成指定類型,然後自定義比較規則
Student s = (Student) obj;
if(s.name.equals(this.name)&&s.age==this.age) return true;
else return false;
}
/***************************************************************/
覆蓋equals的原則: 1.自反性(自己=自己)、 2.對稱性(y=x則x=y)、
3.一致性(多次調用,結果一致)、 4.傳遞性(A=B,B=C則A=C)。
非空原則: t1.equals(Null)返回False;(如果t1不等於空)

(4)、clone 克隆,拷貝
    一個對象參與序列化過程,那麼對象流會記錄該對象的狀態,當再次序列化時,
    會重複序列化前面記錄的對象初始狀態,我們可以用對象克隆技術來解決這個問題
     1 類中覆蓋父類的clone方法,提升protected爲public
     2 類實現Cloneable接口
    淺拷貝:只簡單複製對象的屬性
    深拷貝:如果被複制對象的屬性也是一個對象,則還會複製這個屬性對象
           這種複製是一個遞歸的過程,通過對象序列化實現

《Java5.0新特性》
四大點(枚舉、泛型、註釋、..);5 小點(包裝類、靜態應用、可變長參數、for-each、..)
一、自動裝箱 和 自動解箱技術
裝箱Autoboxing,也翻譯作 封箱;解箱Unautoboxing(也譯作 解封)
1、自動裝箱技術:編譯器會自動將簡單類型轉換成封裝類型。
2、編譯器會自動將封裝類型轉換成簡單類型
3、注意:自動裝箱和自動解箱只會在必要的情況下執行。
int 能隱式提升成 long;但Integer不能隱式提升成Long,只能提升成Number
封裝之後就成類,只能由子類轉成父類;而Integer和Long是Number的不同子類。
如: int i; short s; Integer II; Short SS;
可以 i=SS; 但不可以 II=s; //賦值時,右邊的數先轉成左邊數的對應類型,再進行隱式類型提升

二、靜態引用概念:
用 import static 節省以後的書寫。
引入靜態屬性 import static java.lang.System.out;
引入靜態方法 import static java.lang.Math.random;
import static 只能引入靜態的方法或屬性;不能只引入類或非靜態的方法。
如:import static java.lang.System.*;
out.println(“a”); //等於System.out.println(“a”); 由於out是一個字段,所以不能更節省了
如果 import static java.lang.System.gc; 則可以直接在程序中用 gc(); //等於System.gc();

三、可變長參數
一個方法的參數列表中最多隻能有一個可變長參數,而且這個變長參數必須是最後一個參數
方法調用時只在必要時去匹配變長參數。
/**變長參數的例子*****************************/
import static java.lang.System.*;//節省書寫,System.out直接寫out
public class TestVararg {
public static void main(String… args){
m();
m(“Liucy”);
m(“Liucy”,”Hiloo”);
}
static void m(String… s){out.println(“m(String…)”);}
//s可以看作是一個字符串數組String[] s
static void m(){out.println(“m()”);}
static void m(String s){out.println(“m(String)”);}
} //m(String… s) 是最後匹配的
/************************************************/

四、枚舉 enum
1、定義:枚舉是一個具有特定值的類型,對用戶來說只能任取其一。
對於面向對象來說時一個類的對象已經創建好,用戶不能新生枚舉對象,只能選擇一個已經生成的對象。
2、枚舉本質上也是一個類。枚舉值之間用逗號分開,以分號結束(如果後面沒有其他語句,分號可不寫)。
3、枚舉分爲兩種:類型安全的枚舉模式和類型不安全的枚舉模式
4、枚舉的超類(父類)是:Java.lang.Enum。枚舉是 final 類所以不能繼承或被繼承。但可以實現接口。
枚舉中可以寫構造方法,但構造方法必需是私有的,而且默認也是 私有的 private
5、一個枚舉值實際上是一個公開靜態的常量,也是這個類的一個對象。
6、枚舉中可以定義抽象方法,但實現在各個枚舉值中(匿名內部類的方式隱含繼承)
由於枚舉默認是 final 型,不能被繼承,所以不能直接用抽象方法(抽象方法必須被繼承)
在枚舉中定義抽象方法後,需要在自己的每個枚舉值中實現抽象方法。

枚舉是編譯期語法,編譯後生成類型安全的普通類
values()靜態方法,返回枚舉的元素數組
name方法

/************************************************/
final class Season1{ //用 final 不讓人繼承
private Season1(){} //用 private 構造方法,不讓人 new 出來
public static final Season1 SPRING=new Season1(“春”);
public static final Season1 SUMMER=new Season1(“夏”);
public static final Season1 AUTUMN=new Season1(“秋”);
public static final Season1 WINTER=new Season1(“冬”);
String name; //將”春夏秋冬”設爲本類型,而不是24種基本類型,爲防止值被更改
private Season1(String name){
this.name=name;
}
public String getName(){
return this.name;
}}
/上面是以前版本時自定義的枚舉,下面是新版的枚舉寫法/
enum Season2{
SPRING(“春”), SUMMER(“夏”), AUTUMN(“秋”), WINTER(“冬”);
String name;
Season2(String name){ this.name=name; }
public String getName(){return this.name;}
}//注意:枚舉類是有序的;如:Season2.SPRING.ordinal()
/************************************************/
/*關於枚舉的例子******************************/
import static java.lang.System.*;
public class TestTeacher {
public static void main(String[] args) {
for(TarenaTeacher t:TarenaTeacher.values()){
t.teach();
}}}
enum TarenaTeacher{
LIUCY(“liuchunyang”){void teach(){out.println(name+” teach UC”);}},
CHENZQ(“chenzongquan”){void teach(){out.println(name+” teach C++”);}},
HAIGE(“wanghaige”){void teach(){out.println(name+” teach OOAD”);}};
String name;
TarenaTeacher(String name){this.name=name;}
abstract void teach();
}
/************************************************/
enum Animals {
DOG (“WangWang”) , CAT(“meow”) , FISH(“burble”);
String sound;
Animals ( String s ) { sound = s; }
}
class TestEnum {
static Animals a;
public static void main ( String[] args ) {
System.out.println ( a.DOG.sound + ” ” + a.FISH.sound );
}}
/************************************************/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章