一關(guān)鍵字
Java
標(biāo)識符的命名規(guī)則:
a)????????
應(yīng)以字母、下劃線、美元符開頭
b)????????
后跟字母、下劃線、美元符或數(shù)字
所有
Java
關(guān)鍵字都是小寫的,
TURE
、
FALSE
、
NULL
等都不是
Java
關(guān)鍵字
goto
和
const
雖然從未使用,但也作被為
Java
關(guān)鍵字保留;
?
?
關(guān)鍵字
final
:
在
Java
中聲明類、屬性和方法時,可使用關(guān)鍵字
final
來修飾。
final
標(biāo)記的類不能被繼承。
final
標(biāo)記的方法不能被子類重寫。
final
標(biāo)記的變量
(
成員變量或局部變量
)
即成為常量,只能賦值一次。
final
標(biāo)記的成員變量必須在聲明的同時或在每個構(gòu)造方法中顯式賦值,然后才能使用。
二 文件的命名規(guī)則,當(dāng)類聲明為public時,文件名必須與類名相同。
三 運(yùn)算符,結(jié)合律,按位運(yùn)算符^ | & ~ << >>? ++運(yùn)算符
短路邏輯運(yùn)算符應(yīng)用
???????? && --
第一個操作數(shù)為假則不判斷第二個操作數(shù)
????????
?|| ??? --
第一個操作數(shù)為真則不判斷第二個操作數(shù)
~6 = -7
6->00000110->11111001(
補(bǔ)碼
)->10000111(
原碼
)->-7
補(bǔ)碼變原碼:從低位第一個
1
開始,第一個
1
不變,依次將高位取反(符號位不變)。
–????????
適用數(shù)據(jù)類型
:byte
、
short
、
char
、
int
、
long
,對低于
int
型的操作數(shù)將先自動轉(zhuǎn)換為
int
型再移位
–????????
對于
int
型整數(shù)移位
a>>b
,系統(tǒng)先將
b
對
32
取模,得到的結(jié)果才是真正移位的位數(shù)
8>>65 = 4
–????????
對于
long
型整數(shù)移位時
a>>b
,則是先將移位位數(shù)
b
對
64
取模
?
四 數(shù)據(jù)類型轉(zhuǎn)換
1 數(shù)據(jù)類型轉(zhuǎn)換的種類
?? java數(shù)據(jù)類型的轉(zhuǎn)換一般分三種,分別是:
?? (1). 簡單數(shù)據(jù)類型之間的轉(zhuǎn)換
?? (2). 字符串與其它數(shù)據(jù)類型的轉(zhuǎn)換
?? (3). 其它實(shí)用數(shù)據(jù)類型轉(zhuǎn)換
2 簡單數(shù)據(jù)類型之間的轉(zhuǎn)換
?? 在Java中整型、實(shí)型、字符型被視為簡單數(shù)據(jù)類型,這些類型由低級到高級分別為
(byte,short,char)--int--long--float--double
??? 簡單數(shù)據(jù)類型之間的轉(zhuǎn)換又可以分為:
?? ●低級到高級的自動類型轉(zhuǎn)換
?? ●高級到低級的強(qiáng)制類型轉(zhuǎn)換
?? ●包裝類過渡類型能夠轉(zhuǎn)換
2.1自動類型轉(zhuǎn)換
?? 低級變量可以直接轉(zhuǎn)換為高級變量,筆者稱之為自動類型轉(zhuǎn)換,例如,下面的語句可以在Java中直接通過:
byte b;int i=b;long l=b;float f=b;double d=b;
如果低級類型為char型,向高級類型(整型)轉(zhuǎn)換時,會轉(zhuǎn)換為對應(yīng)ASCII碼值,例如 char c='c';???? int i=c;???? System.out.println("output:"+i);
輸出:output:99;
對于byte,short,char三種類型而言,他們是平級的,因此不能相互自動轉(zhuǎn)換,可以使用下述的強(qiáng)制類型轉(zhuǎn)換。
short i=99;char c=(char)i;System.out.println("output:"+c);
輸出:output:c;
2.2強(qiáng)制類型轉(zhuǎn)換
? 將高級變量轉(zhuǎn)換為低級變量時,情況會復(fù)雜一些,你可以使用強(qiáng)制類型轉(zhuǎn)換。即你必須采用下面這種語句格式:
int i=99;byte b=(byte)i;char c=(char)i;float f=(float)i;
??? 可以想象,這種轉(zhuǎn)換肯定可能會導(dǎo)致溢出或精度的下降,不推薦使用這種轉(zhuǎn)換。
? 2.3包裝類過渡類型轉(zhuǎn)換
?? 在我們討論其它變量類型之間的相互轉(zhuǎn)換時,我們需要了解一下Java的包裝類,所謂包裝類,就是可以直接將簡單類型的變量表示為一個類,在執(zhí)行變量類型的相互轉(zhuǎn)換時,我們會大量使用這些包裝類。Java共有六個包裝類,分別是Boolean、Character、Integer、Long、Float和Double,從字面上我們就可以看出它們分別對應(yīng)于 boolean、char、int、long、float和double。而String和Date本身就是類。所以也就不存在什么包裝類的概念了。
?? 在進(jìn)行簡單數(shù)據(jù)類型之間的轉(zhuǎn)換(自動轉(zhuǎn)換或強(qiáng)制轉(zhuǎn)換)時,我們總是可以利用包裝類進(jìn)行中間過渡。
?? 一般情況下,我們首先聲明一個變量,然后生成一個對應(yīng)的包裝類,就可以利用包裝類的各種方法進(jìn)行類型轉(zhuǎn)換了。例如:
? 例1,當(dāng)希望把float型轉(zhuǎn)換為double型時:
? float f1=100.00f;?? Float F1=new float(f1);?? Double d1=F1.doubleValue();//F1.doubleValue()為Float類的返回double值型的方法
當(dāng)希望把double型轉(zhuǎn)換為int型時:
?? double d1=100.00;???? Double D1=new Double(d1);???? int i1=D1.intValue();
?? 當(dāng)希望把int型轉(zhuǎn)換為double型時,自動轉(zhuǎn)換:
??? int i1=200;???? double d1=i1;
??? 簡單類型的變量轉(zhuǎn)換為相應(yīng)的包裝類,可以利用包裝類的構(gòu)造函數(shù)。即:
Boolean(boolean value)、Character(char value)、Integer(int value)、Long(long value)、Float(float value)、Double(double value)
而在各個包裝類中,總有形為××Value()的方法,來得到其對應(yīng)的簡單類型數(shù)據(jù)。利用這種方法,也可以實(shí)現(xiàn)不同數(shù)值型變量間的轉(zhuǎn)換,例如,對于一個雙精度實(shí)型類,intValue()可以得到其對應(yīng)的整型變量,而doubleValue()可以得到其對應(yīng)的雙精度實(shí)型變量。
? 3 字符串型與其它數(shù)據(jù)類型的轉(zhuǎn)換
??? 通過查閱類庫中各個類提供的成員方法可以看到,幾乎從java.lang.Object類派生的所有類提供了toString()方法,即將該類轉(zhuǎn)換為字符串。例如:Characrer,Integer,Float,Double,Boolean,Short等類的toString()方法toString()方法用于將字符、整數(shù)、浮點(diǎn)數(shù)、雙精度數(shù)、邏輯數(shù)、短整型等類轉(zhuǎn)換為字符串。如下所示:
int i1=10;float f1=3.14f;double d1=3.1415926;Integer I1=new Integer(i1);//生成Integer類\rFloat F1=new Float(f1); //生成Float類\rDouble D1=new Double(d1); //生成Double類\r//分別調(diào)用包裝類的toString()方法轉(zhuǎn)換為字符串String si1=I1.toString();String sf1=F1.toString();String sd1=D1.toString();Sysytem.out.println("si1"+si1);Sysytem.out.println("sf1"+sf1);Sysytem.out.println("sd1"+sd1);
4 將字符型直接做為數(shù)值轉(zhuǎn)換為其它數(shù)據(jù)類型
將字符型變量轉(zhuǎn)換為數(shù)值型變量實(shí)際上有兩種對應(yīng)關(guān)系,在我們在第一部分所說的那種轉(zhuǎn)換中,實(shí)際上是將其轉(zhuǎn)換成對應(yīng)的ASCII碼,但是我們有時還需要另一種轉(zhuǎn)換關(guān)系,例如,'1'就是指的數(shù)值1,而不是其ASCII碼,對于這種轉(zhuǎn)換,我們可以使用Character的getNumericValue(char ch)方法。
五 數(shù)組的操作
數(shù)組聲明:
int a[];???????????? int[] a1;
數(shù)組操作:
???????? System.arraycopy(source, 0, dest, 0, source.length);
System.arraycopy()
方法只復(fù)制元素。如果數(shù)組元素是引用型變量,則只復(fù)制引用,不復(fù)制對象實(shí)體。
六? 包機(jī)制,具有包聲明的類的編譯、運(yùn)行
在使用包的過程中有很多需要注意的小細(xì)節(jié),這里把常見的問題都列舉如下:
1
、對類路徑的設(shè)置通常有兩種方法:
i)
在系統(tǒng)的環(huán)境變量中設(shè)置,設(shè)置方法依據(jù)平臺而變;
ii)
以命令參數(shù)的形式來設(shè)置。
如:
java
c -classpath d:\jdk1.4.2\lib
d:\cjm\edu\test\TestFile.java
java -classpath .;d:\jdk1.4.2\lib; d:\cjm edu.test.TestFile
注意:
i)javac
和
java
命令有很大區(qū)別,可以這樣區(qū)分,
java
c
是一個平臺命令,它對具體的平臺文件進(jìn)行操作,要指明被編譯的文件路徑。而
java
是一個虛擬機(jī)命令,它對類操作,即對類的描述要用點(diǎn)分的描述形式,并且不能加擴(kuò)展名,還要注意類名的大小寫。
ii)
有一個很奇怪的問題,即
java
c
命令后面的
classpath
默認(rèn)包含當(dāng)前目錄(符合
windows
的習(xí)慣),可是在
java
命令后面的
classpath
卻不包含當(dāng)前目錄,所以在它的
classpath
中一定不能忘了加上當(dāng)前目錄的描述,即加上
"."
。
?
2
、類的目錄結(jié)構(gòu)一定要和類中第一句
"
包聲明
"
一致。如類
TestFile.class
對應(yīng)的
.java
文件的第一句必須包含:
package edu.test;
確保類的存放路徑和類中指明的
"
包路徑
"
一致的方法一般有兩種:
i)
編寫
.java
文件時存放的目錄事先確定好,如
TestFile.java
就直接放在
edu\test
目錄下,然后用下面的語句編譯:
java
c -classpath d:\jdk1.4.2\lib
d:\cjm\edu\test\TestFile.java
當(dāng)編譯完成后,產(chǎn)生的
TestFile.class
文件會出現(xiàn)在編譯命令中
java
文件的描述路徑中。即出現(xiàn)在
d:\test\edu\test
中
ii)
通過
-d
參數(shù)的使用來編譯程序。如使用下面的語句來編譯:
java
c -d d:\cjm d:\temp\TestFile.java
將在
-d
后指定的目錄
d:\cjm
下面自動按照
packagek
中指定的目錄結(jié)構(gòu)來創(chuàng)建目錄,并且將產(chǎn)生的
.class
文件放在這個新建的目錄下,即在
d:\cjm
下面建立
\edu\test
目錄,然后產(chǎn)生的
TestFile.class
放在
d:\cjm\edu\test
目錄下。
?
3
、為了便于工程發(fā)布,可以將自己的類樹打成
.jar
文件。如將圖
1
中的
edu
下面的所有類文件打成一個
.jar
文件,可以先轉(zhuǎn)到
d:\cjm
目錄,再用下面的命令:
jar -cvf test.jar edu\
這時會在
d:\test
下產(chǎn)生一個
test.jar
文件,此
.jar
文件中包含
edu\
下的完整目錄結(jié)構(gòu)和文件。使用這個
.jar
文件時,只需在
classpath
中指明
.jar
文件的存放路徑即可。
4
、對其它資源的使用,如圖標(biāo)文件,文本等資源文件的使用必須要注意,查找資源文件不應(yīng)從類文件所在的目錄開始,而是應(yīng)該從
package
指定的類路徑的起點(diǎn)開始。
?
七 類繼承概念,創(chuàng)建子類對象時,構(gòu)造方法的調(diào)用過程&& super、this關(guān)鍵字
八 方法重載注意的問題(略)
九 方法重寫注意的問題(訪問權(quán)限、異常拋出)
-
在子類中可以根據(jù)需要對從父類中繼承來的方法進(jìn)行改造
----
方法的重寫
-
重寫方法必須和被重寫方法具有相同的方法名稱、參數(shù)列表和返回值類型
-
在子類中創(chuàng)建的靜態(tài)方法并不會覆蓋父類中相同名字的靜態(tài)方法。
-
重寫方法不能使用比被重寫方法更嚴(yán)格的訪問權(quán)限
,
拋出的異常不能廣于父類方法拋出的異常范圍。如,
class A{
protected void test() throws IOException
{
??? …….
}
}
class B extends A
{
public
void test() throws Exception // Error! Public >protected, Exception>IOException
{
?
?? ……
}
}
十
靜態(tài)方法、抽象方法
靜態(tài)方法
:又稱類方法,即不需要通過類的實(shí)例就可以引用的方法,調(diào)用一個靜態(tài)方法就是
“
類名
.
方法名
”,
靜態(tài)方法的使用很簡單如上所示。一般來說,靜態(tài)方法常常為應(yīng)用程序中的其它類提供一些實(shí)用工具所用,在
Java
的類庫中大量的靜態(tài)方法正是出于此目的而定義的。靜態(tài)方法不能調(diào)用實(shí)例方法。
靜態(tài)變量
:靜態(tài)變量與靜態(tài)方法類似。所有此類實(shí)例共享此靜態(tài)變量,也就是說在類裝載時,只分配一塊存儲空間,所有此類的對象都可以操控此塊存儲空間。值得注意的是靜態(tài)變量的初始化問題,
static
定義的變量會優(yōu)先于任何其它非
static
變量,不論其出現(xiàn)的順序如何。在
static{
后面跟著一段代碼,這是用來進(jìn)行顯式的靜態(tài)變量初始化,這段代碼只會初始化一次,且在類被第一次裝載時。如果你能讀懂并理解這段代碼,會幫助你對
static
關(guān)鍵字的認(rèn)識。在涉及到繼承的時候,會先初始化父類的
static
變量,然后是子類的,依次類推。
抽象方法
:實(shí)際上是沒有實(shí)現(xiàn)體的虛方法。
抽象類:包含抽象方法的類。如果你覆寫所有的抽象方法
,
子類就變成一個普通的類
.
如果沒有覆寫所有方法
,
子類仍是抽象的
.
如果一個類中中包含有抽象方法
(
哪怕只有一個
),
你必須聲明這個類是抽象的
,
在
class
關(guān)鍵字前加上
abstract.
十一
Object
類中與線程操作相關(guān)的方法及多線程
wait
與
notify
首先要強(qiáng)調(diào),線程
sleep( )
的時候并不釋放對象的鎖,但是
wait( )
的時候卻會釋放對象的鎖。也就是說在線程
wait( )
期間,別的線程可以調(diào)用它的
synchronized
方法。當(dāng)線程調(diào)用了某個對象
wait( )
方法之后,它就中止運(yùn)行并釋放那個對象鎖了。
Java
有兩種
wait( )
。第一種需要一個以毫秒記的時間作參數(shù),它的意思和
sleep( )
一樣,都是
:"
暫停一段時間。
"
區(qū)別在于
:
-
wait( )
會釋放對象的鎖。
-
除了時間到了,
wait( )
還可以用
notify( )
或
notifyAll( )
來中止
第二種
wait( )
不需要任何參數(shù);它的用途更廣。線程調(diào)用了這種
wait( )
之后,會一直等下去,直到
(
有別的線程調(diào)用了這個對象的
)notify( )
或
notifyAll( )
。
和
sleep( )
屬于
Thread
不同,
wait( )
,
notify( )
,
和
notifyAll( )
是根
Object
的方法。雖然這樣做法
(
把專為多線程服務(wù)的方法放到通用的根類里面
)
看上去有些奇怪,但卻是必要的。因?yàn)樗鼈兯倏氐氖敲總€對象都會有的鎖。所以結(jié)論就是,你可以在類的
synchronized
方法里調(diào)用
wait( )
,至于它繼不繼承
Thread
,實(shí)沒實(shí)現(xiàn)
Runnable
已經(jīng)無所謂了。實(shí)際上你也只能在
synchronized
方法里或
synchronized
段里調(diào)用
wait( )
,
notify( )
或
notifyAll( )(sleep( )
則沒有這個限制,因?yàn)樗粚︽i進(jìn)行操作
)
。如果你在非
synchronized
方法里調(diào)用了這些方法,程序還是可以編譯的,但是一運(yùn)行就會出一個
IllegalMonitorStateException
。這個異常帶著一個挺讓人費(fèi)解的
"current thread not owner"
消息。這個消息的意思是,如果線程想調(diào)用對象的
wait( )
,
notify( )
,或
notifyAll( )
方法,必須先
"
擁有
"(
得到
)
這個對象的鎖。
你可以讓另一個對象來操控這個對象的鎖。要想這么做,第一步是先獲取對象的鎖。比方說要想調(diào)用對象
x
的
notify( )
,可以在
x
的
synchronized
段里:
synchronized(x) {
? x.notify();
}
通常情況下,如果條件是由方法之外的其他力量所控制的
(
最常見的就是要由其他線程修改
)
,那么你就應(yīng)該用
wait( )
。你總不希望閑著的時候還讓線程不停地作測試吧;這種
"
瞎忙活
"
是對
CPU
資源的巨大浪費(fèi)。所以
wait( )
能讓你在等待世道改變的同時讓線程休眠,當(dāng)
(
其他線程調(diào)用了對象的
)notify( )
或
notifyAll( )
的時候,線程自會醒來,然后檢查條件是不是改變了。所以說
wait( )
提供了一種同步線程間的活動的方法。
舉個例子,假設(shè)有這么一間飯店,它有一個廚師和一個服務(wù)員。服務(wù)員必須等廚師燒菜。廚師做完一道菜就通知服務(wù)員,服務(wù)員上完菜接著等。這是一個很精彩的線程合作的例子:廚師就是
producer
,而服務(wù)員就是
consumer
。下面我們用代碼來為這個故事建模:
//: c13:Restaurant.java
// The producer-consumer approach to thread cooperation.
import com.bruceeckel.simpletest.*;
class Order {
? private static int i = 0;
? private int count = i++;
? public Order() {
??? if(count == 10) {
????? System.out.println("Out of food, closing");
????? System.exit(0);
??? }
? }
? public String toString() { return "Order " + count; }
}
class WaitPerson extends Thread {
? private Restaurant restaurant;
? public WaitPerson(Restaurant r) {
??? restaurant = r;
??? start();
? }
? public void run() {
??? while(true) {
????? while(restaurant.order == null)
??????? synchronized(this) {
????????? try {
??????????? wait();
????????? } catch(InterruptedException e) {
??????????? throw new RuntimeException(e);
????????? }
??????? }
????? System.out.println(
??????? "Waitperson got " + restaurant.order);
????? restaurant.order = null;
??? }
? }
}
class Chef extends Thread {
? private Restaurant restaurant;
? private WaitPerson waitPerson;
? public Chef(Restaurant r, WaitPerson w) {
??? restaurant = r;
??? waitPerson = w;
??? start();
? }
? public void run() {
??? while(true) {
????? if(restaurant.order == null) {
??????? restaurant.order = new Order();
??????? System.out.print("Order up! ");
??????? synchronized(waitPerson) {
????????? waitPerson.notify();
??????? }
????? }
????? try {
??????? sleep(100);
????? } catch(InterruptedException e) {
??????? throw new RuntimeException(e);
????? }
??? }
? }
}
public class Restaurant {
? private static Test monitor = new Test();
? Order order; // Package access
? public static void main(String[] args) {
??? Restaurant restaurant = new Restaurant();
??? WaitPerson waitPerson = new WaitPerson(restaurant);
??? Chef chef = new Chef(restaurant, waitPerson);
??? monitor.expect(new String[] {
????? "Order up! Waitperson got Order 0",
????? "Order up! Waitperson got Order 1",
????? "Order up! Waitperson got Order 2",
????? "Order up! Waitperson got Order 3",
????? "Order up! Waitperson got Order 4",
????? "Order up! Waitperson got Order 5",
????? "Order up! Waitperson got Order 6",
????? "Order up! Waitperson got Order 7",
????? "Order up! Waitperson got Order 8",
????? "Order up! Waitperson got Order 9",
????? "Out of food, closing"
??? }, Test.WAIT);
? }
} ///:~
Order
是一個會自己計(jì)數(shù)的類,同時它還負(fù)責(zé)中止程序;數(shù)到
10
的時候,它會調(diào)用
System.exit( )
。
WaitPerson
必須知道它是為哪家
Restaurant
服務(wù)的,所以他得從那家飯店的
"
帳臺
"
,也就是
restaurant.order
,拿單子。
WaitPerson
的
run( )
調(diào)用了
wait( )
方法,所以除非
Chef
用
notify( )
叫醒他,否則他會一直等下去。這是個非常簡單的程序,所以我們知道只會有一個線程在等
WaitPerson
的鎖
:
就是
WaitPerson
線程自己,所以
notify( )
是安全的。如果情況比較復(fù)雜,有很多線程在等一個對象的鎖,那么你可能就不知道該叫醒哪個線程了。遇到這種情況,可以用
notifyAll( )
,這個方法會叫醒所有在等這個對象的鎖的線程。這樣線程就能自行判斷本次喚醒是否與自己有關(guān)。
請注意,
wait( )
所在的
while
循環(huán),它的測試條件正是
wait
要等的東西。乍看上去真有點(diǎn)奇怪
——
如果你等的是訂單,那么醒過來之后肯定會有訂單,難道不是嗎?問題在于在多線程環(huán)境下,還沒等
WaitPerson
醒過來,訂單就可能被其他線程給搶走了。所以唯一安全的做法就是套用下面這個
wait( )
定式
:
while(conditionIsNotMet)
wait(?);
?
十二
equals
方法的使用
eqauls
與
= =
之異同
1
)比較方式角度:
= =
是面向過程的操作符;
equals
是面向?qū)ο蟮牟僮鞣?/span>
= =
不屬于任何類,
equals
則是任何類(在
Java
中)的一個方法;
我們可以用這三種比較
????? 1
)
Primitive1 (
基本類型
)= = Primitive2(
基本類型
)
;
????? 2
)
Object Reference1(
對象引用
)= = Object Reference2(
對象引用
)
????? 3
)
Object Reference1 (
對象引用
) .equals(Object Reference2 (
對象引用
))
但卻不能
Primitive1 (
基本類型
).equals( Primitive2(
基本類型
))
;
2)
比較目的角度
:
1
)如果要比較兩個基本類型是否相等,請用
= =
;
2
)如果要比較兩個對象引用是否相等,請用
= =
;
3
)如果要比較兩個對象(邏輯上)是否一致,請用
equals
;
例子:
s1 = new String("null");
s2 = new String("null");
System.out.println(s1==s2);//false
System.out.println(s1.equals(s2));//true
?
s1 = "null";
s2 = "null";
System.out.println(s1==s2);//true
System.out.println(s1.equals(s2));//true
?
十三
基本類型包裝類的特點(diǎn)
P152?
,
byteValue intValue
方法(見
四數(shù)據(jù)類型轉(zhuǎn)換)
十四
集合類所在的工具包,
List
接口(
Vector
,
ArrayList
)
Set
接口(
HashSet, TreeSet
)
遍歷問題
集合類型主要有
3
種:
set(
集)、
list(
列表)和
map(
映射
)
。
集:
HashSet
:
使用
HashMap
的一個集的實(shí)現(xiàn)。雖然集定義成無序,但必須存在某種方法能相當(dāng)高效地找到一個對象。使用一個
HashMap
對象實(shí)現(xiàn)集的存儲和檢索操作是在固定時間內(nèi)實(shí)現(xiàn)的
.
TreeSet
:
在集中以升序?qū)ο笈判虻募膶?shí)現(xiàn)。這意味著從一個
TreeSet
對象獲得第一個迭代器將按升序提供對象。
TreeSet
類使用了一個
TreeMap.
列表:
Vector
:
實(shí)現(xiàn)一個類似數(shù)組一樣的表,自動增加容量來容納你所需的元素。使用下標(biāo)存儲和檢索對象就象在一個標(biāo)準(zhǔn)的數(shù)組中一樣。你也可以用一個迭代器從一個
Vector
中檢索對象。
Vector
是唯一的同步容器類
??
當(dāng)兩個或多個線程同時訪問時也是性能良好的。
Vector
類關(guān)鍵方法
:
void addElement(Object obj)
void add(int index, Object element)
Object elementAt(int index)
void insertElementAt(Object obj, int index)
Stack:
這個類從
Vector
派生而來,并且增加了方法實(shí)現(xiàn)棧的一種后進(jìn)先出的存儲結(jié)構(gòu)。
LinkedList:
實(shí)現(xiàn)一個鏈表。由這個類定義的鏈表也可以像棧或隊(duì)列一樣被使用。
ArrayList:
實(shí)現(xiàn)一個數(shù)組,它的規(guī)模可變并且能像鏈表一樣被訪問。它提供的功能類似
Vector
類但不同步。
映射:
HashTable
:
實(shí)現(xiàn)一個映象,所有的鍵必須非空。為了能高效的工作,定義鍵的類必須實(shí)現(xiàn)
hashcode()
方法和
equal()
方法。這個類是前面
java
實(shí)現(xiàn)的一個繼承,并且通常能在實(shí)現(xiàn)映象的其他類中更好的使用。
put
(Object?key, Object?value)
get
(Object?key)
keys
()
???????? Returns an enumeration of the keys in this hashtable.
elements
()???????? Returns an enumeration of the values in this hashtable.
HashMap
:
實(shí)現(xiàn)一個映象,允許存儲空對象,而且允許鍵是空(由于鍵必須是唯一的,當(dāng)然只能有一個)。
?
TreeMap
:
實(shí)現(xiàn)這樣一個映象,對象是按鍵升序排列的。
?
List list = new LinkedList();
?????? list.add(new Integer(5));
?????? list.add(new Double(3.14));
?????? list.add("123");
?????? Iterator iter = list.iterator();
?????? while(iter.hasNext()) {
?????????? System.out.println(iter.next());
?????? }
Set set = new TreeSet();
?????? set.add("nihao");
?????? set.add(new String("abcd"));
?????? set.add("xyz");
?????? set.add("1234");
?
?????? Iterator iter2 = set.iterator();
?????? while (iter2.hasNext()) {
?????????? System.out.println(iter2.next());
?????? }
?????? Map map = new HashMap();
?????? map.put("1", new Integer(1));
?????? map.put("5", new Double(32.1));
?????? map.put("2", new String("abc"));
?????? Iterator iter3 = map.keySet().iterator();
?????? while(iter3.hasNext()) {
?????????? Object key = iter3.next();
?????????? System.out.println("key: " + key + "\tvalue: " + map.get(key));
?????? }
//property and enumeration
import java.util.Properties;
import java.util.Enumeration;
public class Test9_4 {
?????? public static void main(String[] args) {
???
?????? Properties ps = System.getProperties();
???
?????? Enumeration pn = ps.propertyNames();
???
?????? while ( pn.hasMoreElements() ) {
???
??????
???? String pName = (String) pn.nextElement();
???
???????
???? String pValue = ps.getProperty(pName);
???
???????
???? System.out.println(pName + "----" + pValue);
???
?????? }
???
??? }
}
//
實(shí)現(xiàn)
Comparable
接口
,
使該類的對象可排序
import java.util.Arrays;
public class TestComparable implements Comparable {
??? //
該類的屬性
i
??? private double i = Math.random();
?
??? //
實(shí)現(xiàn)
Comparable
接口的抽象方法
,
定義排序規(guī)則
??? public int compareTo(Object o) {
??? //
定義排序規(guī)則
: TestComparable
對象里的屬性
i
大的則排序時比較
"
大
"(
排序靠后
)
??? if (o instanceof TestComparable) {
?????? if (i > ((TestComparable) o).i) {
?????????? return 1;
?????? } else {
?????????? return -1;
?????? }
?????? return 0;
??? } else {
??? //
非
TestComparable
對象與之比較
,
則拋出異常
?????? throw new ClassCastException("Can't compare");
??? }
}
十五
String
類的常用操作(
toCharArray, substring,trim
),
StringBuffer(append,toString)
,
StringTokenizer
類的應(yīng)用
(p155-p161
略
)
StringTokenizer st = new StringTokenizer("this is a test");
while (st.hasMoreTokens()) {
???????? println(st.nextToken());
}
十六
內(nèi)部類的使用,內(nèi)部類對象的創(chuàng)建
內(nèi)部類的定義和使用:
內(nèi)部類是在一個類的內(nèi)部嵌套定義的類,它可以是其它類的成員,也可以在一個語句塊的內(nèi)部定義,還可以在表達(dá)式內(nèi)部匿名定義。
內(nèi)部類有如下特性:
◇
一般用在定義它的類或語句塊之內(nèi)
,
在外部引用它時必須給出完整的名稱
.
名字不能與包含它的類名相同。
◇
可以使用包含它的類的靜態(tài)和實(shí)例成員變量
,
也可以使用它所在方法的局部變量。
◇
可以定義為
abstract
。
◇
可以聲明為
private
或
protected
。
◇
若被聲明為
static,
就變成了頂層類
,
不能再使用局部變量。
◇
若想在
Inner Class
中聲明任何
static
成員
,
則該
Inner Class
必須聲明為
static
。
十七
流操作,文件讀寫操作,隨機(jī)文件讀寫對象的創(chuàng)建,工具包
//
對象序列化
import java.io.*;
import java.util.*;
?
public class ObjectPersistence {
??? public static void main(String[] args) throws IOException,ClassNotFoundException{
?????? MyData md = new MyData();
?????? md.v = new Vector();
?????? md.v.add(new String("hi, my students,"));
?????? md.v.add(new Integer(5));
?????? FileOutputStream fos = new FileOutputStream("mydata.ser");
?????? ObjectOutputStream oos = new ObjectOutputStream(fos);
?????? oos.writeObject(md);
?????? oos.close();? fos.close();
?????? //after 1 day,
?????? FileInputStream fis = new FileInputStream("mydata.ser");
?????? ObjectInputStream ois = new ObjectInputStream(fis);
?????? md = (MyData) ois.readObject();
?????? System.out.println(md.s);??????
?????? System.out.println(md.f);??????
?????? System.out.println(md.i);
?????? System.out.println(md.v.get(0));
?????? ois.close(); fis.close();
??? }
}
?
class MyData implements Serializable {
??? String s = "abc";
??? float? f = 3.14f;
??? transient int i = 5;? //transient variable can't be serialized.
??? Vector v = null;
}//end
?
//
從鍵盤逐行讀入數(shù)據(jù)輸出到文件
import java.io.*;
public class Test9_2 {
??? public static void main (String[] args) {
???
????? File file = new File("tt.txt");
???
????? try {
???
?
??
??? InputStreamReader? is = new InputStreamReader(System.in);
??????
??? BufferedReader in=new BufferedReader(is);
??????
??? PrintWriter out? = new PrintWriter(new FileWriter(file));
??????
??? String s = in.readLine();
??????
??? while (!s.equals("")) {//
從鍵盤逐行讀入數(shù)據(jù)輸出到文件
?????????? out.println(s);
?????????? s = in.readLine();
??????
???? }
??????
???? in.close();? //
關(guān)閉
BufferedReader
輸入流
.????? ????
??????
???? out.close();? //
關(guān)閉連接文件的
PrintWriter
輸出流
.
???
?????? }catch (IOException e) {System.out.println(e);? }
???
?}
}//end
?
// ReadData
import java.io.*;
public class ReadData {
??? public static void main(String[] args) {
?????? try{
?????????? //stream chaining.
?????????? File f = new File("p1.txt"); //use a File object instead String.
?????????? FileInputStream fis = new FileInputStream(f);
?????????? BufferedInputStream bis = new BufferedInputStream(fis);
?????????? DataInputStream dis = new DataInputStream(bis);
??????????? //int r = dis.readInt();
?????????? int r1 = dis.readInt();
?????????? String r = dis.readUTF();
?????????? //String r1 = dis.readUTF();
?????????? System.out.println(r1 + r );
?????????? dis.close(); bis.close(); fis.close();
?????? }
?????? catch (Exception e)
?????? {
?????????? e.printStackTrace();
?????? }
??? }
}//end
RandomAccessFile
類用于文件的輸入輸出,處理方式是利用文件指針進(jìn)行隨機(jī)定位讀寫。
構(gòu)造函數(shù)為:
RandomAccessFile(File?file,?String?mode);
RandomAccessFile(String?name,?String?mode);
其中
mode
為操作狀態(tài),有兩種狀態(tài):
r,
用于讀;
rw
,用于讀寫
主要成員方法:
void?close();//
long?getFilePointer();//
獲取文件指針位置
long?length();//
獲取文件長度,單位為字節(jié)
int?read();//
從文件輸入流中讀取一個字節(jié)的數(shù)據(jù),遇文件結(jié)束返回
-1
int?read(byte[]?b);
byte?readByte()
void?seek(long?pos);//
指針定位于
pos
處
void?writeBytes(String?s)
...
String?readLine()
//example of RandomAccessFile
public void setFile(String dir,String filename){
?????? if((filename == null)||(filename.length() == 0)) return;
?????????? RandomAccessFile file = new ?RandomAccessFile(dir+filename,"r");
?????????? byte[] buffer=new byte[4096];
?????????? int len;
?????????? textArea.setText("");
?????????? while((len=file.read(buffer))!=-1){
????????????? String s=new String(buffer,0,len);
????????????? textArea.append(s);
?????????? }
?????????? file.close();
??????? } catch(IOException e){
?????????? textArea.setText(e.getMessage());
??????? }
?}
十八
異常處理機(jī)制
(
略
)
十九
socket
編程
?
//TestServer.java
import java.net.*;
import java.io.*;
public class TestServer {
???
? public static void main(String args[]) {
?????? ServerSocket s = null;
?????? try {
??????
?????? s = new ServerSocket(8888);
?????? } catch (IOException e) {}
?????? while (true) {
??????
?????? try {
????????????? Socket s1 = s.accept();
????????????? new MyThread(s1).start();
??????????
??????
????? } catch (IOException e) {}
?????? }
???
? }
}
class MyThread extends Thread
{
??? Socket s;
??? MyThread(Socket s)
??? {this.s = s;}
??? public void run()
??? {
?????? try{
?????? DataInputStream? dis = new DataInputStream(s.getInputStream());
?????? DataOutputStream dos = new DataOutputStream(System.out);
?????? String str = dis.readUTF();
?????? dos.writeUTF("echo "+str);
?????? dos.flush();
?????? dis.close();
?????? dos.close();
?????? s.close();
?????? }catch(Exception e)
?????? {
??????????
?????? }
??? }
}
?
//TestClient.java
import java.net.*;
import java.io.*;
?
public class TestClient {
???
? public static void main(String args[]) {
?????? try {
?????????? Socket s1 = new Socket("127.0.0.1", 8888);
?????????? OutputStream os = s1.getOutputStream();
?????????? DataOutputStream dos = new DataOutputStream(os);
?????????? BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
?????????? String str = br.readLine();
?????????? dos.writeUTF(str);
?????????? dos.flush();
?????????? s1.close();
?????????? dos.close();
?????? } catch (ConnectException connExc) {
?????????? System.err.println("
服務(wù)器連接失敗!
");
?????? } catch (IOException e) {
?????? }
???
? }
}
二十
JDBC
import java.sql.*;
public class JDBCDemo
{
??? public static void main(String[] args)
??? {
?????? try
?????? {
?????????? Statement stmt;
?????????? PreparedStatement pstmt;
?????????? ResultSet rs;
?
?????????? //load the jdbc-odbc driver
?????????? Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
?
?????????? //define the JDBC url
?????????? String url = "jdbc:odbc:JDBCDemo";
?
?????????? //get the connection of database
?????????? Connection con = DriverManager.getConnection(url);
?
?????????? System.out.println("URL " + url);
?????????? System.out.println("Connection: " + con);
?
?????????? //get the statement object
?????????? stmt = con.createStatement();
?
?????????? //if exit the DemoTable, delete it, or throw exception
?????????? System.out.println("DROP TABLE DemoTable, if it exits");
?????????? try
?????????? {
????????????? stmt.executeUpdate("DROP TABLE DemoTable");
?????????? }
?????????? catch (Exception e)
?????????? {
????????????? System.out.print(e);
????????????? System.out.println("No existing table to delete");
?????????? }
?
?????????? //Create a Demotable
?????????? stmt.executeUpdate("CREATE TABLE DemoTable(test_id int, test_val char(15) not null");
?
?????????? //insert the entries in the table
?????????? stmt.executeUpdate("INSERT INTO DemoTable(test_id, test_val) VALUES(1,'one')");
?????????? stmt.executeUpdate("INSERT INTO DemoTable(test_id, test_val) VALUES(2,'two')");
?????????? stmt.executeUpdate("INSERT INTO DemoTable(test_id, test_val) VALUES(3,'three')");
?
?????????? stmt = con.createStatement();
?????????? //get the records of DemoTable
?????????? rs = stmt.executeQuery("SELECT * FROM DemoTable ORDER BY test_id");
?
?????????? //show them
?????????? while(rs.next())
?????????? {
????????????? int theInt = rs.getInt("test_id");
????????????? String theString = rs.getString("test_val");
????????????? System.out.println("\t test_id = "+theInt+"\t test_val = "+theString);
?????????? }
?
?????????? //use of preparedStatement
?????????? pstmt = con.prepareStatement("update DemoTable set test_val = ? where test_id = ?");
?
?????????? pstmt.setString(1,"hello");
?????????? pstmt.setInt(2,2);
?????????? pstmt.executeUpdate();
?????????? System.out.println("Update row number 2: OK");
?
?????????? con.close();
?????? }
?????? catch (Exception e)
?????? {
?????????? e.printStackTrace();
?????? }
??? }
}