天天看點

Java FAQ(slhynju 0.3版)

****** 版權聲明 ********

* 在完整保留此版權聲明并接受下列條款的前提下,你可以自由的擷取、存儲、使用、修

改、分發本文。

* 由于你可能自第三方獲得本文,作者不保證本文的正确性和一緻性。

* 作者也不對任何因使用本文而造成的直接或間接的經濟損失或其他損失負責,即使事先

你已告知這一風險。

* 如果你修改并分發本文,并且未附加任何版權聲明,則該版權聲明自動适用于你修改和

添加的内容。

* 如果你修改并分發本文,并且附加了你的版權聲明,你應當明确标明你修改和添加的内

容,并聲明你的版權聲明隻适用于你修改和添加的内容,其餘内容仍然使用本版權聲明。

* 如果你在分發本文的過程中直接或間接地、有意或無意地獲利,你應當公開分發一份完

全一緻和免費的本文複制品,該複制品不必包括你修改或添加的内容。

* 作者:slhynju

* 版本:0.3

* 更新日期:2003/11/28

* &copyright 2003-4-9

*************************/

目錄:

Q1.1 什麼是Java、Java2、JDK?JDK後面的1.3、1.4版本号又是怎麼回事?

Q1.2 什麼是JRE/J2RE?

Q1.3 學習Java用什麼工具比較好?

Q1.4 學習Java有哪些好的參考書?

Q1.5 Java和C++哪個更好?

Q1.6 什麼是J2SE/J2EE/J2ME?

Q2.1 我寫了第一個Java程式,應該如何編譯/運作?

Q2.2 我照你說的做了,但是出現什麼“'javac' 不是内部或外部指令,也不是可運作的

程式或批處理檔案。”。

Q2.3 環境變量怎麼設定?

Q2.4 我在javac xxx.java的時候顯示什麼“unreported exception java.io.IOExcepti

on;”。

Q2.5 javac xxx.java順利通過了,但是java xxx的時候顯示什麼“NoClassDefFoundErr

or”。

Q2.6 我在java xxx的時候顯示“Exception in thread "main" java.lang.NoSuchMetho

dError: main”。

Q2.7 在java xxx的時候顯示“Exception in thread "main" java.lang.NullPointerEx

ception”。

Q2.8 package是什麼意思?怎麼用?

Q2.9 我沒有聲明任何package會怎麼樣?

Q2.10 在一個類中怎麼使用其他類?

Q2.11 我用了package的時候顯示"NoClassDefFoundError",但是我把所有package去掉的

時候能正常運作。

Q2.12 我想把java編譯成exe檔案,該怎麼做?

Q2.13 我在編譯的時候遇到什麼"deprecated API",是什麼意思?

Q3.1 我怎麼給java程式加啟動參數,就像dir /p/w那樣?

Q3.2 我怎麼從鍵盤輸入一個int/double/字元串?

Q3.3 我怎麼輸出一個int/double/字元串?

Q3.4 我發現有些書上直接用System.in輸入,比你要簡單得多。

Q3.5 我怎麼從檔案輸入一個int/double/字元串?

Q3.6 我想讀寫檔案的指定位置,該怎麼辦?

Q3.7 怎麼判斷要讀的檔案已經到了盡頭?

Q4.1 java裡面怎麼定義宏?

Q4.2 java裡面沒法用const。

Q4.3 java裡面也不能用goto。

Q4.4 java裡面能不能重載操作符?

Q4.5 我new了一個對象,但是沒法delete掉它。

Q4.6 我想知道為什麼main方法必須被聲明為public static?為什麼在main方法中不能調

用非static成員?

Q4.7 throw和throws有什麼不同?

Q4.8 什麼是異常?

Q4.9 final和finally有什麼不同?

Q5.1 extends和implements有什麼不同?

Q5.2 java怎麼實作多繼承?

Q5.3 abstract是什麼?

Q5.4 public,protected,private有什麼不同?

Q5.5 Override和Overload有什麼不同?

Q5.6 我繼承了一個方法,但現在我想調用在父類中定義的方法。

Q5.7 我想在子類的構造方法中調用父類的構造方法,該怎麼辦?

Q5.8 我在同一個類中定義了好幾個構造方法并且想在一個構造方法中調用另一個。

Q5.9 我沒有定義構造方法會怎麼樣?

Q5.10 我調用無參數的構造方法失敗了。

Q5.11 我該怎麼定義類似于C++中的析構方法(destructor)?

Q5.12 我想将一個父類對象轉換成一個子類對象該怎麼做?

Q5.13 其實我不确定a是不是B的執行個體,能不能分情況處理?

Q5.14 我在方法裡修改了一個對象的值,但是退出方法後我發現這個對象的值沒變!

Q6.1 java能動态配置設定數組嗎?

Q6.2 我怎麼知道數組的長度?

Q6.3 我還想讓數組的長度能自動改變,能夠增加/删除元素。

Q6.4 什麼是連結清單?為什麼要有ArrayList和LinkedList兩種List?

Q6.5 我想用隊列/棧。

Q6.6 我希望不要有重複的元素。

Q6.7 我想周遊集合/Map。

Q6.8 我還要能夠排序。

Q6.9 但是我想給數組排序。

Q6.10 我想按不同方式排序。

Q6.11 Map有什麼用?

Q6.12 set方法沒問題,但是get方法傳回的是Object。

Q6.13 ArrayList和Vector有什麼不同?HashMap和Hashtable有什麼不同?

Q6.14 我要獲得一個随機數。

Q6.15 我比較兩個String總是false,但是它們明明都是"abc" !

Q6.16 我想修改一個String但是在String類中沒找到編輯方法。

Q6.17 我想處理日期/時間。

一、準備篇

答:Java是一種通用的,并發的,強類型的,面向對象的程式設計語言(摘自Java規範第二版

)。

JDK是Sun公司分發的免費Java開發工具包,正式名稱為J2SDK(Java2 Software Develop K

it)。

包括基本的java工具包和标準類庫。

到目前(2003年7月)為止,Java有3個主要版本,即1.0,1.1,2.0;

JDK有1.0,1.1,1.2,1.3,1.4五個版本。

從JDK1.2起,Sun公司覺得Java改變足夠大而将java語言版本号提升為2.0。

不同的JDK主要在于提供的類庫不同。作為學習你可以下載下傳最新的JDK1.4.2。

真正開發時則應考慮向前相容,比如1.3。下載下傳請去[url]http://java.sun.com[/url]。

JDK1.5預計将在2004年推出,屆時其中将包含若幹嶄新的特性。

答:J2RE是Java2 Runtime Environment,即Java運作環境,有時簡稱JRE。

如果你隻需要運作Java程式或Applet,下載下傳并安裝它即可。

如果你要自行開發Java軟體,請下載下傳JDK。在JDK中附帶有JRE。

注意由于Microsoft對Java的支援不完全,請不要使用IE自帶的虛拟機來運作Applet,務必

安裝一個JRE或JDK。

答:作者建議首先使用JDK+文本編輯器,這有助你了解下列幾個基礎概念:path,classp

ath,package

并熟悉基本指令:javac和java。并且下載下傳和你的JDK版本一緻的API幫助。

如果你不确定類或函數的用法,請先查閱API而不是發貼求助。

當你熟悉Java之後,你可以考慮開始使用一個IDE。

作者推薦eclipse,下載下傳網址[url]http://www.eclipse.org[/url]。因為eclispe是免費的,插件化的

eclispe的主要缺點是缺乏一個可視化的桌面程式開發工具,

幸運的是IBM在2003年11月已經将部分代碼捐給eclipse組織,可以預計這個缺點很快就會

得到彌補。

無論如何,請不要使用Microsoft的VJ++!衆所周知Microsoft從來就沒有認真支援過Java

最後但并非最不重要,要有一本好的參考書,并且英文要過關。

答:作者首先推薦Thinking in Java,中文名《Java程式設計思想》,有中文版。

目前的最新版本是第三版。

在[url]http://64.78.49.204[/url]可以免費下載下傳英文版。

該書第一章介紹了很多面向對象的程式設計思想,作為新手應當認真閱讀。

除此以外,O'relly出版社和Wrox出版社的書也不錯。作者本人不喜歡大陸作者的書。

也許你覺得英文太難,但是網上大多數資料都是英文的。另外,你需要經常查閱API,而那

也是英文的。

答:這個問題是一個很不恰當的問題。你應該問:Java和C++哪個更适用于我的項目?

Java的優點和缺點一樣明顯。

跨平台是Java的主要優點,但代價是運作速度的下降。

VC和Windows平台有良好的內建和足夠快的速度,但是也隻能局限在Windows平台上。

和C++相比,Java學起來更快,開發人員不會碰到很多容易出錯的特性。

但是VB程式員甚至隻需要拼裝子產品就可以了。

答:J2SE就是一般的Java。

J2ME是針對嵌入式裝置的,比如支援Java的手機,它有自己的JRE和SDK。

J2EE是一組用于企業級程式開發的規範和類庫。

二、指令篇

答:首先請将程式儲存為xxx.java檔案,注意你可能需要修改檔案字尾名。

然後在dos視窗下使用javac xxx.java指令,你會發現該目錄下多了一個xxx.class檔案,

再使用java xxx指令,你的java程式就開始運作了。

答:你遇到了path問題。作業系統在一定的範圍(path)内搜尋javac.exe,但是沒能找到。

請編輯你的作業系統環境變量,新增一個JAVA_HOME變量,設為你JDK的安裝目錄,

再編輯Path變量,加上一項 %JAVA_HOME%\bin。

然後儲存并新開一個dos視窗,你就可以使用javac和java指令了。

答:請向身邊會設的人咨詢。

答:參見Q4.8以了解java中的異常機制。

答:1. 你遇到了classpath問題。java指令在一定的範圍(classpath)内搜尋你直接或間接

使用的class檔案,但是未能找到。

首先請确認你沒有錯敲成java xxx.class,

其次,檢查你的CLASSPATH環境變量,其實你并不需要設定該變量,

但如果你設定了該變量又沒有包含.(代表目前目錄)的項,

你就會遇到這個問題。請在你的CLASSPATH環境變量中加入一項. 或幹脆删掉這個變量。

2. 如果你使用了并非JDK自帶的标準包,比如javax.servlet.*包,也會遇到這個問題,請

将相應的jar檔案加入classpath。

3. 如果你在java源檔案中定義了package,請參見Q2.11。

答:首先,在你的程式中每個java檔案有且隻能有一個public類,

這個類的類名必須和檔案名的大小寫完全一樣。

其次,在你要運作的類中有且隻能有一個public static void main(String[] args)方法

這個方法就是你的主程式。

答:在程式中你試圖對值為null的對象調用方法,請檢查你的程式。

參見Q4.8以了解java中的異常機制。

答:為了唯一辨別每個類并分組,java使用了package的概念。

每個類都有一個全名,例如String的全名是java.lang.String,其中java.lang是包名,S

tring是短名。

這樣,如果你也定義了另外一個類String,你可以把它放在mypackage中,

通過使用全名mypackage.String和java.lang.String來區分這兩個類。

同時,将邏輯上相關的類放在同一個包中,可以使程式結構更為清楚。

為了定義包,你要做的就是在java檔案開頭加一行“package mypackage;”。

注意包沒有嵌套或包含關系,A包和A.B包對java指令來說是并列的兩個包(雖然開發者可

能暗示包含關系)。

答:你的類被認為放在預設包中。這時全名和短名是一緻的。

答:如果你使用java.lang包或者預設包中的類,不用做任何事。

如果你使用其他包中的類,在package聲明之後,類聲明之前使用import package1.class

1; 或 import package2.*;

這裡.*表示引入這個包中的所有類。然後在程式中你可以使用其他類的短名。

如果短名間有重名沖突,必須使用全名來區分。

答:将你的java檔案按包名存放。

比如你的工作目錄是/work,你的類是package1.class1,那麼将它存放為/work/package1

/class1.java。

如果沒有聲明包,那麼直接放在/work下。

在/work下執行javac package1/class1.java,再執行java package1.class1,你會發現一

切正常。

另外,你可以考慮開始使用IDE。

答:JDK隻能将java源檔案編譯為class檔案。

class檔案是一種跨平台的位元組碼,必須依賴平台相關的JRE來運作。Java以此來實作跨平

台性。

有些開發工具可以将java檔案編譯為exe檔案。作者反對這種做法,因為這樣就取消了跨平

如果你确信你的軟體隻在Windows平台上運作,你可以考慮使用C++/C#來程式設計。

答:所謂deprecated是指已經過時,但是為了向前相容起見仍然保留的方法。

這些方法可能會在以後取消支援。你應當改用較新的方法。

在API裡面會說明你應當用什麼方法來代替之。

三、I/O篇

答:還記得public static void main(String[] args)嗎?這裡的args就是你的啟動參數

在運作時你輸入java package1.class1 arg1 arg2,args中就會有兩個String,第一個是

arg1,第二個是arg2。

答:java的I/O操作比C++要複雜一點。如果要從鍵盤輸入,樣例代碼如下:

BufferedReader cin = new BufferedReader( new InputStreamReader( System.in ) );

String s = cin.readLine();

這樣你就獲得了一個字元串,如果你需要數字的話再使用:

int n = Integer.parseInt( s ); 或者 double d = Double.parseDouble( s );

答:使用System.out.println(n)或者System.out.println("Hello")等等。

答:java使用unicode,是雙位元組。而System.in是單位元組的stream。

如果你要輸入雙位元組文字比如中文,請使用作者的做法。

Q3.5 我怎麼從檔案輸入/輸出一個int/double/字元串?

答:類似于從鍵盤輸入,隻不過換成

BufferedReader fin = new BufferedReader( new FileReader(" myFileName " ) );

PrintWriter fout = new PrintWriter( new FileWriter(" myFileName " ) );

另外如果你還沒下載下傳API,請開始下載下傳并閱讀java.io包中的内容。

答:java.io.RandomAccessFile可以滿足你的需要。

答:在Reaer的read方法中明确說明傳回-1表示流的結尾。

四、 關鍵字篇

答:java不支援宏,因為宏代換不能保證類型安全。

如果你需要定義常量,可以将它定義為某個類的static final成員。參見Q4.2和Q4.6。

答:你可以用final關鍵字。例如 final int m = 9。被聲明為final的變量不能被再次賦

值。

final也可以用于聲明方法或類,被聲明為final的方法或類不能被繼承。

注意const是java的保留字以備擴充。

答:甚至在面向過程的語言中你也可以完全不用goto。請檢查你的程式流程是否合理。

如果你需要從多層循環中迅速跳出,java增強了(和C++相比)break和continue的功能,

支援label。

例如:

outer :

while( ... )

{

inner :

for( ... )

... break inner; ...

... continue outer; ...

}

和const一樣,goto也是java的保留字以備擴充。

答:不能。String的+号是唯一一個内置的重載操作符。你可以通過定義接口和方法來實作

類似功能。

答:java有自動記憶體回收機制,即所謂Garbarge Collection。你不需要删除對象。你再也

不用擔心指針錯誤,記憶體溢出了。

答:聲明為public是為了這個方法可以被外部調用,詳情見Q5.4。

static是為了将某個成員變量/方法關聯到類(class)而非執行個體(instance)。

你不需要建立一個對象就可以直接使用這個類的static成員,因而在static成員中不能調

用非static成員,因為後者是關聯到對象執行個體(instance)的。

在A類中調用B類的static成員可以使用B.staticMember的寫法。

注意一個類的static成員變量是唯一的,被所有該類對象所共享的。

你可以使用如下方法來使用非static成員:

public class A

private void someMethod() //非static成員

{}

public static void main(String args)

A a = new A(); //建立一個對象執行個體

a.someMethod(); //現在你可以使用非static方法了

答:throws用于聲明一個方法會抛出哪些異常。而throw是在方法體中實際執行抛出異常的

動作。

如果你在方法中throw一個異常,卻沒有在方法聲明中聲明之,編譯器會報錯。

注意Error和RuntimeException的子類是例外,無需特别聲明。

答:異常最早在Ada語言中引入,用于在程式中動态處理錯誤并恢複。

你可以在方法中攔截底層異常并處理之,也可以抛給更高層的子產品去處理。

你也可以抛出自己的異常訓示發生了某些不正常情況。常見的攔截處理代碼如下:

try

......//以下是可能發生異常的代碼

...... //異常被抛出,執行流程中斷并轉向攔截代碼。

......

catch(Exception1 e) //如果Exception1是Exception2的子類并要做特别處理,應排在前

//發生Exception1時被該段攔截

catch(Exception2 e)

//發生Exception2時被該段攔截

finally //這是可選的

//無論異常是否發生,均執行此段代碼

//即使在catch段中又向外抛出了新的exception,finally段也會得到執行。

答:final請見Q4.2。finally用于異常機制,參見Q4.8。

五、 面向對象篇

答:extends用于(單)繼承一個類(class),而implements用于實作一個接口(interf

ace)。

interface的引入是為了部分地提供多繼承的功能。

在interface中隻需聲明方法頭,而将方法體留給實作的class來做。

這些實作的class的執行個體完全可以當作interface的執行個體來對待。

在interface之間也可以聲明為extends(單繼承)的關系。

答:java不支援顯式的多繼承。

因為在顯式多繼承的語言例如c++中,會出現子類被迫聲明祖先虛基類構造函數的問題,

而這是違反面向對象的封裝性原則的。

java提供了interface和implements關鍵字來部分地實作多繼承。參見Q5.1。

答:被聲明為abstract的方法無需給出方法體,留給子類來實作。

而如果一個類中有abstract方法,那麼這個類也必須聲明為abstract。

被聲明為abstract的類無法執行個體化,盡管它可以定義構造方法供子類使用。

答:這些關鍵字用于聲明類和成員的可見性。

public成員可以被任何類通路,

protected成員限于自己和子類通路,

private成員限于自己通路。

Java還提供了第四種的預設可見性,當沒有任何public,protected,private修飾時,成員

是同一包内可見。

類可以用public或預設來修飾。

答:Override是指父類和子類之間方法的繼承關系,這些方法有着相同的名稱和參數類型

Overload是指同一個類中不同方法(可以在子類也可以在父類中定義)間的關系,

這些方法有着相同的名稱和不同的參數類型。

答:用super.xxx()可以在子類中調用父類方法。

答:在子類構造方法的第一行調用super(...)即可。

答:在構造方法第一行調用this(...)。

答:自動獲得一個無參數的構造方法。

答:如果你至少定義了一個構造方法,就不再有自動提供的無參數的構造方法了。

你需要另外顯式定義一個無參數的構造方法。

另外一種可能是你的構造方法或者類不是public的,參見Q5.4了解java中的可見性。

答:提供一個void finalize()方法。在Garbarge Collector回收該對象時會調用該方法。

注意實際上你很難判斷一個對象會在什麼時候被回收。作者從未感到需要用到該方法。

答:強制類型轉換。如

public void meth(A a)

B b = (B)a;

如果a實際上并不是B的執行個體,會抛出ClassCastException。是以請確定a确實是B的執行個體。

答:可以使用instanceof操作符。例如

if( a instanceof B )

else

...

答:很可能你把傳入參數重賦了一個新對象,例如下列代碼就會造成這種錯誤:

public void fun1(A a) //a是局部參數,指向了一個外在對象。

a = new A(); //a指向了一個新對象,和外在對象脫鈎了。如果你要讓a作為傳出變量,

不要寫這一句。

a.setAttr(attr);//修改了新對象的值,外在對象沒有被修改。

基本類型也會出現這種情況。例如:

public void fun2(int a)

a = 10;//隻作用于本方法,外面的變量不會變化。

六、java.util篇

答:可以。例如int n = 3; Language[] myLanguages = new Language[n];

答:用length屬性。如上例中的 myLanguages.length 就為 3。

答:用順序表--java.util.List接口。

你可以選擇用ArrayList或是LinkedList,前者是數組實作,後者是連結清單實作。

例如: List list = new ArrayList(); 或是 List list = new LinkedList(); 。

答:請補習資料結構。

答:用java.util.LinkedList。

答:用集合--java.util.Set接口。例如:Set set = new HashSet()。

答:用java.util.Iterator。參見API。

答:用java.util.TreeSet。例如:Set set = new TreeSet()。放進去的元素會自動排序

你需要為元素實作Comparable接口,還可能需要提供equals()方法,compareTo()方法,h

ashCode()方法。

答:java.util.Arrays類包含了sort等實用方法。

答:為每種方式定義一個實作了接口Comparator的排序類并和Arrays或TreeSet綜合運用。

答:存儲key-value的關鍵字-值對,你可以通過關鍵字來快速存取相應的值。

答:強制類型轉換成你需要的類型。參見Q5.12。

答:ArrayList和HashMap是多線程不安全的,在多個線程中通路同一個ArrayList對象可能

會引起沖突并導緻錯誤。

而Vector和Hashtable是多線程安全的,即使在多個線程中同時通路同一個Vector對象也不

會引起差錯。

看起來我們更應該使用Vector和Hashtable,但是實際上Vector和Hashtable的性能太差,

是以如果你不在多線程中使用的話,還是應該用ArrayList和HashMap。

答:使用java.util.Random類。

答:比較String一定要使用equals或equalsIgnoreCase方法,不要使用 == !

==比較的是兩個引用(變量)是否指向了同一個對象,而不是比較其内容。

答:使用StringBuffer類。

String str = "......."; //待處理的字元串

StringBuffer buffer = new StringBuffer(str); //使用該字元串初始化一個StringBuf

fer

buffer.append("..."); //調用StringBuffer的相關API來編輯字元串

String str2 = buffer.toString(); //獲得編輯後的字元串。

另外,如果你需要将多個字元串連接配接起來,請盡量避免使用+号直接連接配接,而是使用Strin

gBuffer.append()方法。

答:使用java.util.Date類。你可以使用java.text.SimpleDateFormat類來在String和Da

te間互相轉換。

SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //規

定日期格式

Date date = formatter.parse("2003-07-26 18:30:35"); //将符合格式的String轉換為

Date

String s = formatter.format(date); //将Date轉換為符合格式的String

關于定義日期格式的詳細資訊請參見API。

上一篇: Python IP切換