java面試題(二)

一、概念題

1、爲什麼需要main方法?

Main 方法爲 java 程序的入口方法,jvm 在運行程序時,會首先查找 main 方法。

2、一個 java 文件中是否可以定義多個類?

可以,但是只能有一個公共類,並且這個公共類的類名必須與文件名相同

3、什麼是構造方法?

構造方法是一種特殊的方法,用來在對象實例化時初始化對象的成員變量。

4

1java語言的優點?

答:java1995SUN公司推出的一門高級編程語言,是面向互聯網的語言,是一個WEB應用程序首選的語言,簡單易學、安全可靠。主要特點:完全面向對象、與平臺無關(跨平臺)。

2什麼叫跨平臺?以及跨平臺的原理?

答:一、同樣的一段Java代碼可以忽略不同操作系統的差異性去運行。

二、java跨平臺的前提是基於JVMjava虛擬機,Java Virtual Machine),所有的java代碼並不是直接在計算機中運行而是先交給JVMjvm屏蔽了不同操作系統的差異性,將同一段java代碼翻譯針對不同的操作系統能夠理解的語言,對不同的系統開發了不同的Java虛擬機。Java語言本身是跨平臺的,但是jvm不是跨平臺的。

3、請描述JVM\JRE\JDK

答:jvm---java Virtual Machine---JAVA虛擬機,java能夠跨平臺的一個前提

JRE---java runtime environment---java運行時的環境,包含了JVM+核心類庫

JDK---java development kit---java開發工具包,包含了開發工具+JRE

4爲什麼JDK中包含一個JRE?

答:其一,開發完的程序總需要運行一下看看效果。其二,也是最重要的,jdk中的開發工具其實都是java語言編寫的應用程序,爲了方便使用纔打包成exe文件,如果沒有jre,那麼這些工具試運行不了的。簡而言之,jdk開發的Java程序交給jre去運行。

5、什麼叫編譯?以及編譯中的問題?編譯命令?

答:一、將給人看的代碼翻譯成給機器看的代碼,會將一個java文件翻譯成一個字節碼文件,這就是編譯。

二、class文件的文件名和類名對應---每一個類編譯完成之後都會產生一個class文件;當用public來修飾一個類的時候,這時候要求類名和java文件名必須一致---這個類也稱爲公共類;一個java文件中可以定義多個類,並且每個類對應一個class文件。

 

6、標識符的命名規則?駝峯命名法?

答:一、命名規則:(1)可以有字母、數字、_$組成,但是不建議使用$符號。(2java 支持中文名---不建議使用(3)不能使用純數字,數字不能作爲開頭。(4)不能使用關鍵字java/sum/org

二、駝峯命名法:1)類名/接口名:如果由多個單詞組成,每個單詞的首字母大寫  HelloWorld。(2)變量名/方法名:如果由多個單詞組成,第一個單詞的首字母小寫,其餘單詞的首字母大寫  playGame3)包名:如果由多個單詞組成,所有字母全部小寫,每個單詞之間用 . 隔開(4)常量名:如果由多個單詞組成,所有字母全部大寫,每個單詞之間用 _ 隔開

7、類於對象的關係?

答:(1)對一類事物的公有特徵和行爲進行了提取,將特徵抽取成了屬性,將行爲抽取成了方法,就形成了對應的類——類是對象的概括。

2)根據類通過new 關鍵字創建了一個對象/實例,並且可以在後續操作中給對象中的屬性賦值或者去調用對象身上的方法——對象是類的具體化。

8、成員變量與局部變量的區別?

答:(1)定義位置不同:成員變量定義在類內方法外,局部變量定義在方法/代碼塊/語句內部。

2)內存位置不同:成員變量存儲在堆內存中,並且在堆內存中自動的賦予了初始值;局部變量存儲在棧內存中,在棧內存中需要手動賦予初始值。

3)做用域不同:成員變量作用在整個類中,局部變量只能作用在定義它的方法/代碼塊/語句內。

4)生命週期不同:成員變量在創建的時候隨之存儲到了堆內存中,在對象被回收的時候隨之銷燬。局部變量在方法/代碼塊/語句執行完成立即銷燬。

9、什麼是面向過程,什麼是面向對象?面向對象一定優於面向過程嗎?

答:一、面向過程注重的是執行的動作/完成的過程,強調的是執行的過程。面向對象注重的是對象,只要找到了對應的對象,那麼就自然擁有了對象所具有的一切功能。面向對象是基於面向過程。

二、不一定,當場景比較複雜的時候,面向對象更簡便,建議使用面向對象;當事物比較簡單的時候,面向過程效率比較高,建議面向過程。

10、面向對象的四個特性?

答:面向對象的四個特性:封裝、繼承、多態、抽象

1)封裝是將一段邏輯或功能提取出來,進行封裝,這種封裝的體現形式就是函數。

封裝的優點:(1)方便重複使用某段功能,提高了代碼的複用性。(2)使代碼更加規範化、結構化。(3)便於模塊化開發。

2)繼承是對一些類共有的屬性和方法進行提取,提取到一個新的類中,通過extends關鍵字使原來的類和新類之間產生了聯繫,這個聯繫稱之爲繼承。原來的類稱之爲子類(派生類),新的類稱之爲父類(超類、基類)。

作用:提高複用性,增強安全性,統一代碼結構,在一定程度上降低了代碼的冗餘度。

注意:在java中是單繼承,即一個子類只有一個父類,而一個父類可以有多個子類。

如果支持多繼承,而這多個父類中存在了方法簽名一致,就會導致調用的混亂,單繼承有效的避免方法調用的混亂,從而提高代碼的安全性。

3)多態是面嚮對象語言中,接口的多種不同的實現方式即爲多態。多態又分爲編譯時多態和運行時多態,編譯時多態可以進行重載,運行時多態可以進行向上造型和重寫。

4)抽象。在抽象中應注意(1)抽象類不能創建對象,但是有構造函數。(2)抽象方法之間可以重載。(3)抽象方法可以和實體方法重載。(4)靜態方法不可以是抽象的,因爲靜態超脫對象,跟着類而來。(5)抽象方法不可以用final修飾。(6)抽象方法不可以是私有的,因爲繼承不過去,無法被重寫。(7)如果抽象方法的權限修飾符是默認的時候,要求子類必須是同包類。(8)抽象類不能與finalprivatestatic關鍵字共存。

11、異常是什麼?常見的異常?

答:代碼中出現問題,用來反饋處理問題的。2、異常的分類  Throwable是頂級父類

  1Error——表示的是嚴重的邏輯或者底層錯誤,一旦出現無法處理。如StackOverFlowError.——棧溢出錯誤

   2Exception——是指程序中出現的能處理的一些意外或者問題。

3Exception的分類

  1)編譯時異常/已檢查異常——在編譯的時候要求處理,要麼拋出,要麼捕獲。如:CloneNotSupportedException   ParseException

   2)運行時異常/未檢查異常——在編譯的時候無錯,但是運行的時候報錯,也就是語法無錯。一旦出現,可以處理也可以不處理。——RuntimeException

    如:ArithmeticException——算術異常

        NullPointException——空指針異常

        ArrayIndexOutOfBoundsException——下標越界異常

        ClassCasteException——類加載異常

        NumberFormatException——數字格式異常

4、如何自定義異常?

1)寫一個類繼承Exception或者是其中的任何一個字類

public class ExceptionDemo2 {

public static void main(String[] args) {

A a = new B();

try {

a.m(5);

} catch (IOException | CloneNotSupportedException e) {

e.printStackTrace();

}

}

}

class A {

public void m(int i) throws IOException, CloneNotSupportedException {

if (i == 1)

throw new IOException();

if (i == 2) {

throw new CloneNotSupportedException();

}

}

// 異常不影響方法的重載

public void m(double d) {

}

}

class B extends A {

// 子類重寫方法的時候,拋出的異常不能超過父類異常的範圍---編譯時異常

// 子類不能拋出比父類更多的異常

public void m(int i) throws EOFException,FileNotFoundException,NullPointerException{

}

}

5、異常處理?

 1)直接拋出:可以在一個方法中通過throw new 異常來在方法中拋出異常、

                可以通過throws關鍵字在方法名上聲明拋出的異常。

 2)捕獲處理

  A、多個catch分別捕獲分別處理

  B、捕獲一個Exception,統一處理。

  C、分批處理異常的時候,同一批的這些異常之間可以用|隔開——從JDK1.7開始出現。

 

12throwthrows有什麼區別?

答:(1throw是語句拋出一個異常,語法:throw(異常對象);throw e;(2throws是方法可能拋出異常的聲明。(用在聲明方法時,表示該方法可能要拋出異常)。語法:[(修飾符)](返回值類型)(方法名)([參數列表])[throws(異常類)]{..}

public void doA(int a ) throws Exception1,Exception3{..}

舉例:如:void doA(int a )throws IOException{try{

}catch(Exception1 e){throw e;}

catch(Exception2 e){System.out.println("出錯了");}

if(!a=b){throw new Exception("自定義異常");}

代碼塊中可能產生3個異常,如果產生Exception1異常,則捕獲之後在拋出,又該方法的調用者去處理。如果產生Exception2,則該方法自己處理了。所以該方法就不會再向外拋出Exception2異常了,void doA()throws Exception1,Exception3裏面的Exception2也就不用寫了。而Exception3異常時該方法的某段邏輯出錯,程序員自己做了處理,在該段邏輯錯誤的情況下拋出異常Exception3,則該方法的調用者也要處理此異常。

1throw語句用在方法體內,表示拋出異常,由方法體內的語句處理。throws語句用在方法聲明後面,表示再拋出異常,由該方法的調用者處理。

2throws主要是聲明這個方法會拋出這種類型的異常,使他的調用者知道要捕獲這個異常。throw是具體向外拋出異常的動作,所以它是拋出一個異常的實例。

3throws說明你有那個可能,傾向。throw的話,那就是你把那個傾向變成真實的了。

同時:1throws出現在方法函數頭,而throw出現在函數體。2throws表示出現異常的一種可能,並不一定會發生這些異常;而throw則是拋出了異常,執行throw則一定拋出了某種異常。3、兩者都是消極處理異常的方式,只是拋出或者可能拋出異常,但是不會由函數去處理異常,真正的處理異常由函數的上層調用處理。

13Set\ HashSet\List\ArrayList/Vector/LinkedList有什麼區別?

(1)Set不包含重複元素,元素之間可能有序,內存是一定不連續。

HashSet---是一個線程不安全的集合,默認容量是16,加載因子/裝載因子是0.75f,每次擴容一倍

(1) list元素有序,可以重複,但是內存不一定連續。由於List中元素是有序的,所以存在了下標,因此可以通過遍歷下標的方式來遍歷一個List

(2)ArrayListList的一個實現類,本質上是基於數組的,內存空間是連續的,不便於增刪元素,便於查詢;是線程不安全的;初始容量爲10,每次在當前的基礎上擴容一半-> 10 -> 15 -> 22 -> 33 -> 49

(3)Vector向量---最早期的集合---基於數組;是一個線程安全的列表;默認容量是10,每次擴容一倍;10 -> 20 -> 40

Vector是從JDK1.0開始出現的,早於集合Collection接口。

(4) LinkedListList的一個實現類,是基於鏈表(指針)實現的。能保證元素之間的順序,但是內存是不連續的。便於增刪元素,不便於查詢。是一個線程不安全的列表

14ArrayList和數組有什麼區別?長度、元素類型

答:(1)長度:ArrayList長度可變,數組不可變。(2)元素類型:ArraryList存儲的對象是引用類型,數組基本類型和引用類型都可以。

15List和數組有什麼區別?長度、元素類型、內存連續

1)長度:list長度可變,數組不可變。

2)元素類型:List中的元素是引用類型,數組基本類型和引用類型都可以。

3)內存:List內存不一定連續,數組內存連續。

16、線性集合---ListQueue

17、重載和重寫有什麼區別?

答:重載是發生在一個類中,方法名一致,參數列表不同,和修飾符、異常等無關,是一種編譯時多態。

重寫是發生在了父子類中,父子類中存在了方法簽名一致的方法,遵循兩小兩等一大原則,是一種運行時多態。其中兩小兩等一大爲(1)方法簽名一致。(2)如果父類中方法的返回值類型是基本數據類型/void/最終類,那麼子類在重寫方法的時候,返回值類型要一致。(3)子類方法的權限修飾符的範圍要大於等於父類方法的權限修飾符的範圍。(4)如果父類中方法的返回值類型是一個引用數據類型,那麼子類在重寫方法的時候,返回值類型是父類方法返回值類型的子類或者一致。(5)子類拋出的異常必須小於等於父類,子類不能比父類拋出更多的異常,針對編譯時異常而言,對運行時異常沒有影響。

 

18爲什麼內部接口默認是靜態的?

因爲:在java中接口的作用是用來實現,若接口不是靜態的,使用接口的時候,需要外部類的對象來調用。再來implents接口的時候,不能再後面創建對象new。在定義類的時候不允許創建對象。靜態的東西不需要對象,所以默認是靜態。

接口定義接口,靜態?如果不是靜態的得通過對象調用;接口不能創鍵對象。

19、垃圾回收機制?

當對象剛創建的時候,存儲到新生代的伊甸園區,經過一次回收之後,如果這個對象在棧內存中沒有了引用,會被解析回收;如果這個對象在棧內存中依然存在引用,那麼會被移到新聲代的倖存區;倖存區的掃描頻率略低於伊甸園區;在倖存區中經過多次掃描依然存在的對象,會被挪到老生代中。老生代的掃描頻率遠遠低於新生代。老生代中的對象一旦產生了回收,可能會導致程序的卡頓甚至崩潰。

發生在新生代的回收---minor GC---初代回收

發生在老生代的回收---full GC---完全回收

20String/StringBuilder/StringBuffer區別?

StringStringBuilder StringBuffer 都是操作字符串的類。

String 是不可變類,也就是說 String 對象一但被創建,其值將不能改變。

StringBuilder StringBuffer 是可變類,當對象被創建後仍然可以對其值進行修改。而StringBuilder StringBuffer 只能通過構造方法的方式創建對象。

StringBuilder是一個操作字符串的類,本身是線程不安全的,效率較高,String中的+拼接運算默認使用的是StringBuilder中的append方法

StringBuffer是線程安全的,效率較低。

21、正則表達式?

Pattern---代表正則表達式的類

用來作爲模式或者規則進行匹配的

[abc] 表示a/b/c中的任何一個

[^abc] 表示除了a/b/c

\d 表示數字

\D 表示非數字

\w 表示單詞字符

\W 表示非單詞字符

\s 表示空白字符

\S 表示非空白字符

^a 表示以a作爲開頭

a$ 表示以a作爲結尾

. 表示任意字符

* 表示出現零次或者多次

+ 表示至少出現一次

? 表示至多出現一次

{n} 表示恰好出現n

{n,} 表示至少出現n

{n,m} 表示至少出現n次,但是不超過m

22、幾種類型的包裝類?

byte-Byte short-Short int-Integer long-Long

float-Float double-Double char-Character boolean-Boolean

23、區別?

Math.ceil(1.2)->2想上取整,floor(1.2->1);向下取整 , Math.round(1.6)->2,四捨五入。

24StackQueue

1Stack---

先進後出。將元素放入棧中---入棧/壓棧;將元素從棧中取出---出棧/彈棧;最先放入棧中的元素---棧底元素;最後放入棧中的元素--棧頂元素

2Queue---隊列

先進先出。排在隊列最前面的元素---隊頭元素,排在隊列最後面的元素---隊尾元素。

 

25、對集合的理解?

Collection---頂級接口---存儲一組數據的容器,爲了標識集合中的元素類型,使用泛型進行限定

 

26、泛型如何繼承?

extends /接口---允許傳入類/接口本身及其子類/子接口對象---限定了上限

super /接口---允許傳入類/接口本身及其父類/父接口對象---限定了下限

// 只操作數值型

// ? extends /接口 泛型的繼承

// ? extends Number ---> 做了一個限定,限定泛型類型只能是Number及其子類對象

// 此時限定了泛型的上限---Number

public static void add(List<? extends Number> list) {

 

// 除了null以外,其他任何類型都不行

// 爲什麼null可以?---引用類型

// 爲什麼不能傳入具體類型?---Integer

// list.add(new Integer(5));

list.add(null);

 

// 求和

 

}

 

// 限定泛型的下限

// ? super Integer ---> 做了一個限定,限定泛型的類型只能是Integer及其父類或者父接口

public static void m(List<? super Integer> list) {

// 允許添加這個類本身的對象/null

list.add(new Integer(5));

// Number n = new Integer(6);

// list.add(n);

}

27、如何理解映射?

映射。鍵值對---由一個鍵和一個值組成---> 鍵唯一,值可以重複。一個映射是由多個鍵值對組成 。Map不是集合

28如何遍歷一個映射?

1. 先來獲取所有的鍵,遍歷鍵獲取值

2. 直接遍歷這些鍵值對

29HashMapHashtable的區別?

HashMap---默認初始容量是16,加載因子是0.75f,每次擴容一倍;允許一個鍵爲null,允許多個值爲null;是一個異步式線程不安全的映射

Hashtable---默認初始容量是11,加載因子是0.75f,每次擴容兩倍;不允許鍵值爲null;是一個同步式線程安全的映射

ConcurrentHashMap---是一個異步式線程安全的映射

30、絕對路徑和相對路徑?

絕對路徑:以盤符或者/ 開頭的路徑是絕對路徑。和當前路徑沒有關係

相對路徑:不以盤符或者/ 開頭的路徑是絕對路徑。是以當前路徑作爲基準進行計算。 .. 表示的是上一層路徑;   . 表示的是當前目錄

31finalfinallyfinalize有什麼區別?

Final 用於聲明屬性、方法和類,分別表示屬性不可變、方法不可重寫和類不可被繼承。

Finally 作爲異常處理的一部分,它只能用在 try/catch 語句中,並且附帶一個語句塊,表示這段語句最終一定會被執行,經常被用在需要釋放資源的情況下。

Finalize Object 類的一個方法,在垃圾回收器執行時會調用被回收對象的 finalize()方法。-通知GC回收垃圾對象,gc不一定會啓動回收

32、接口與抽象類的區別?

1.不同點:接口只能有抽象函數,抽象類可以沒有抽象函數;抽象類本身是類是單繼承的,接口可以多繼承;一個類可以實現多個接口但只能實現一個抽象類;接口沒有構造函數,抽象類有構造函數;接口中定義的變量默認爲:public final static修飾,抽象方法默認修飾符爲public2.相同點:都不能創建對象,都需要子類或者實類來實現其中的抽象方法

33Breakreturncontinue  有什麼區別?

Break 用於直接強行跳出當前循環,不在執行剩餘代碼。

Continue 用於停止當前循環,回到循環起始處,進入下一次循環操作。

Return 語句是一個跳轉語句,用來表示從一個方法返回,可以使程序控制返回到調用該方法的地方。

34Instanceof 有什麼作用?

Instanceof 的作用是判斷一個引用類型的變量所指向的對象是否是一個類的實例。

35、值傳遞與引用傳遞的區別?

值傳遞:在方法調用中,實參會把它的值傳遞給形參,形參只是用實參的值初始化一個臨時的存儲單元(方法內的局部變量),因此性參與實參雖然有着相同的值,但是卻有着不用的存儲單元,因此對形參的改變不會影響實參的值。

引用傳遞:在方法的調用中,傳遞的是對象(也可以看做是對象的地址),這時形參與實參指向同一塊存儲單元(對象),因此對形參的修改就會影響實參的值。

36、字符串存儲的機制是什麼?

字符串會存儲在常量池中。在給字符串賦值的時候,JVM 會檢查常量池中是否已經存在該字符串,如果存在則直接引用該地址,否則會在常量池中創建該字符串然後引用該地址。

37、什麼是迭代器?

迭代器是一個對象,它的工作是遍歷並選擇集合中的對象,它提供了一種訪問一個容器對象中的各個元素,而又不必暴露該對象內部細節的方法。

38、自動封箱拆箱

封箱:將基本數據類轉換成對應包裝類的過程。自動封箱的過程實際上就是調用了對應的包裝類的 valueOf()方法。

拆箱:把包裝類變成基本數據類型的過程。 實際上是調用了對象的***value().

39Collection Collections 的區別

Collection 是集合類的頂級接口,它提供了對集合類操作的統一接口方法。實現 Collection 接口的子接口有 List Set

Collections 是針對集合類的一個包裝類(工具類),它提供一系列靜態方法以實現對各種集合的操作。

 

 

 

.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

其他資料get過來的!!!!!!!

 

1、一個".java"源文件中是否可以包括多個類(不是內部類)?有什麼限制?

答:可以有多個類,但只能有一個public的類,並且public的類名必須與文件名相一致。

2java有沒有goto?

答:gotoJava中的保留字,現在並沒有在java使用。其中保留字還有const(常量)。

3、說說&&&的區別。

答:(1&&&都可以用作邏輯與的運算符,表示邏輯與(and),當運算符兩邊的表達式的結果都爲true時,整個運算結果才爲true,否則,只要有一方爲false,則結果爲false

2&&還具有短路的功能,即如果第一個表達式爲false,則不再計算第二個表達式,例如,對於if(str != null && !str.equals(“”))表達式,當strnull時,後面的表達式不會執行,所以不會出現NullPointerException如果將&&改爲&,則會拋出NullPointerException異常。If(x==33 & ++y>0) y會增長,If(x==33 && ++y>0)不會增長

3&還可以用作位運算符,當&操作符兩邊的表達式不是boolean類型時,&表示按位與操作,我們通常使用0x0f來與一個整數進行&運算,來獲取該整數的最低4bit位,例如,0x31 & 0x0f的結果爲0x01

 

備註:這道題先說兩者的共同點,再說出&&&的特殊之處,並列舉一些經典的例子來表明自己理解透徹深入、實際經驗豐富。

4、在JAVA中如何跳出當前的多重嵌套循環?

答:在Java中,要想跳出多重循環,可以在外面的循環語句前定義一個標號,然後在裏層循環體的代碼中使用帶有標號的break 語句,即可跳出外層循環。例如,

ok:

for(int i=0;i<10;i++)

{

for(int j=0;j<10;j++)

{

System.out.println(“i=” + i + “,j=” + j);

if(j == 5) break ok;

}

}

另外,我個人通常並不使用標號這種方式,而是讓外層的循環條件表達式的結果可以受到裏層循環體代碼的控制,例如,要在二維數組中查找到某個數字。

int arr[][] = {{1,2,3},{4,5,6,7},{9}};

boolean found = false;

for(int i=0;i<arr.length && !found;i++)

{

for(int j=0;j<arr[i].length;j++)

{

System.out.println(“i=” + i + “,j=” + j);

if(arr[i][j]  == 5)

{

found = true;

break;

}

}

}

5switch語句能否作用在byte上,能否作用在long上,能否作用在String?

答:在switchexpr1)中,expr1只能是一個整數表達式或者枚舉常量(更大字體),整數表達式可以是int基本類型或Integer包裝類型,由於,byte,short,char都可以隱含轉換爲int,所以,這些類型以及這些類型的包裝類型也是可以的。顯然,longString類型都不符合switch的語法規定,並且不能被隱式轉換成int類型,所以,它們不能作用於swtich語句中。

6short s1 = 1; s1 = s1 + 1;有什麼錯? short s1 = 1; s1 += 1;有什麼錯?

答:對於short s1 = 1; s1 = s1 + 1; 由於s1+1運算時會自動提升表達式的類型,所以結果是int型,再賦值給short類型s1時,編譯器將報告需要強制轉換類型的錯誤。

對於short s1 = 1; s1 += 1;由於 += java語言規定的運算符,java編譯器會對它進行特殊處理,因此可以正確編譯。

7char型變量中能不能存貯一箇中文漢字?爲什麼?

答:char型變量是用來存儲Unicode編碼的字符的,unicode編碼字符集中包含了漢字,所以,char型變量中當然可以存儲漢字啦。不過,如果某個特殊的漢字沒有被包含在unicode編碼字符集中,那麼,這個char型變量中就不能存儲這個特殊漢字。補充說明:unicode編碼佔用兩個字節,所以,char類型的變量也是佔用兩個字節。

備註:後面一部分回答雖然不是在正面回答題目,但是,爲了展現自己的學識和表現自己對問題理解的透徹深入,可以回答一些相關的知識,做到知無不言,言無不盡。

8、用最有效率的方法算出2乘以8等於幾?

答:2 << 3。因爲將一個數左移n位,就相當於乘以了2n次方,那麼,一個數乘以8只要將其左移3位即可,而位運算cpu直接支持的,效率最高,所以,2乘以8等於幾的最效率的方法是2 << 3。

9、使用final關鍵字修飾一個變量時,是引用不能變,還是引用的對象不能變 

答:使用final關鍵字修飾一個變量時,是指引用變量不能變,引用變量所指向的對象中的內容還是可以改變的。例如,對於如下語句:

 final StringBuffer a=new StringBuffer("immutable");
執行如下語句將報告編譯期錯誤

a=new StringBuffer("");
但是,執行如下語句則可以通過編譯:

a.append(" broken!"); 

 

有人在定義方法的參數時,可能想採用如下形式來阻止方法內部修改傳進來的參數對象:

public void method(final  StringBuffer  param)

{

}

實際上,這是辦不到的,在該方法內部仍然可以增加如下代碼來修改參數對象:

param.append("a");

10"=="equals方法究竟有什麼區別?

(單獨把一個東西說清楚,然後再說清楚另一個,這樣,它們的區別自然就出來了,混在一起說,則很難說清楚)

答:(1)“==”比較的是值,是變量(棧)內存中存放的對象(堆)內存的地址。

equals用於比較兩個對象的值是否相同,不是比較地址。

2)對於基本數據類型而言,“==”是判斷兩個變量得值是否相等。比如:

int a = 3;

int b = 3;

System.out.println(a == b);返回的是true。而equals不能用於基本數據類型,只能用於類變量,對於基本數據類型要用其包裝類,如:

Integer i1 = new Integer(1);

Integer i2 = new Integer(1);

System.out.println(i1.equals(i2));返回的結果是true

3)對於對象變量,因爲對象變量的存儲的是對象在內存中的路徑,即內存地址,所以用“==”比較時,即使對象的值相等,但是他們的內存地址不同,所以結果爲false。比如:

Integer i1 = new Integer(1);

Integer i2 = new Integer(1);

System.out.println(i1 == i2);結果爲false。故“==”適用於比較兩個變量的值是否相等,而不是變量引用的對象是否相等。而equals用於比較兩個對象是否相同,如:

String s = new String("foor");

String ss = new String("foor");

System.out.println(s.equals(ss));結果是true

特別注意Object類中的equals方法和“==”是一樣的,沒有區別,而String類和Integer類等等一些類,是重寫了equals方法,才使得equals和“==”不同,所以,當自己創建類時,自動繼承了Objectequals的方法,要想實現不同的等於比較,必須重寫equals

==”比equals運行的速度快,因爲“==”只是比較引用。

11、靜態變量和實例變量的區別?

答:(1)在語法定義上的區別:靜態變量前要加static關鍵字,而實例變量前則不加。

2)在程序運行時的區別:實例變量屬於某個對象的屬性,必須創建了實例對象,其中的實例變量纔會被分配空間,才能使用這個實例變量。靜態變量不屬於某個實例對象,而是屬於類,所以也稱爲類變量,只要程序加載了類的字節碼,不用創建任何實例對象,靜態變量就會被分配空間,靜態變量就可以被使用了。總之,實例變量必須創建對象後纔可以通過這個對象來使用,靜態變量則可以直接使用類名來引用。

例如,對於下面的程序,無論創建多少個實例對象,永遠都只分配了一個staticVar變量,並且每創建一個實例對象,這個staticVar就會加1;但是,每創建一個實例對象,就會分配一個instanceVar,即可能分配多個instanceVar,並且每個instanceVar的值都只自加了1次。

public class VariantTest

{

public static int staticVar = 0;

public int instanceVar = 0;

public VariantTest()

{

staticVar++;

instanceVar++;

System.out.println(“staticVar=” + staticVar + ”,instanceVar=” + instanceVar);

}

}

備註:這個解答除了說清楚兩者的區別外,最後還用一個具體的應用例子來說明兩者的差異,體現了自己有很好的解說問題和設計案例的能力,思維敏捷,超過一般程序員,有寫作能力!

12、是否可以從一個static方法內部發出對非static方法的調用?

答:不可以。因爲非static方法是要與對象關聯在一起的,必須創建一個對象後,纔可以在該對象上進行方法調用,靜態方法在類加載的時候加載到方法區中的靜態區,存儲在了靜態區並沒有執行;在方法被調用的時候纔去棧內存中執行。靜態方法也是先於對象存在,所以靜態方法可以通過類來調用,也可以通過對象來調用。也就是說,靜態方法是先於對象而存在的;在Java中所有的非靜態方法和非靜態屬性都是通過對象來調用的

當一個static方法被調用時,可能還沒有創建任何實例對象,如果從一個static方法中發出對非static方法的調用,那個非static方法是關聯到哪個對象上的呢?這個邏輯無法成立,所以,一個static方法不可以從內部發出對非static方法的調用。

13Integerint的區別

答:(1intjava提供的8種原始數據類型之一。Java爲每個原始類型提供了封裝類,Integerjavaint提供的封裝類。(2int的默認值爲0,而Integer的默認值爲null,即Integer可以區分出未賦值和值爲0的區別,int則無法表達出未賦值的情況,例如,要想表達出沒有參加考試和考試成績爲0的區別,則只能使用Integer。在JSP開發中,Integer的默認爲null,所以用el表達式在文本框中顯示時,值爲空白字符串,而int默認的默認值爲0,所以用el表達式在文本框中顯示時,結果爲0,所以,int不適合作爲web層的表單數據的類型。

3)在Hibernate中,如果將OID定義爲Integer類型,那麼Hibernate就可以根據其值是否爲null而判斷一個對象是否是臨時的,如果將OID定義爲了int類型,還需要在hbm映射文件中設置其unsaved-value屬性爲0

4)另外,Integer提供了多個與整數相關的操作方法,例如,將一個字符串轉換成整數,Integer中還定義了表示整數的最大值和最小值的常量。

14Math.round(11.5)等於多少? Math.round(-11.5)等於多少?

答:Math類中提供了三個與取整有關的方法:ceilfloorround,這些方法的作用與它們的英文名稱的含義相對應,例如,ceil的英文意義是天花板,該方法就表示向上取整,所以,Math.ceil(11.3)的結果爲12,Math.ceil(-11.3)的結果是-11floor的英文意義是地板,該方法就表示向下取整,所以,Math.floor(11.6)的結果爲11,Math.floor(-11.6)的結果是-12;最難掌握的是round方法,它表示“四捨五入”,算法爲Math.floor(x+0.5),即將原來的數字加上0.5後再向下取整,所以,Math.round(11.5)的結果爲12Math.round(-11.5)的結果爲-11

15、下面的代碼有什麼不妥之處?

1. if(username.equals(“zxx”){}

2. int  x = 1;

return x==1?true:false;

答:void方法不能返回一個數值。

16、請說出作用域publicprivateprotected,以及不寫時的區別

答:這四個作用域的可見範圍如下表所示。

說明:如果在修飾的元素上面沒有寫任何訪問修飾符,則表示friendly

 

作用域    當前類 同一package 子孫類 其他package

public    √     √          √       √

protected  √     √          √      ×

friendly   √     √          ×      ×

private    √     ×          ×      ×

備註:只要記住了有4種訪問權限,4個訪問範圍,然後將全選和範圍在水平和垂直方向上分別按排從小到大或從大到小的順序排列,就很容易畫出上面的圖了。

17**OverloadOverride的區別。Overloaded的方法是否可以改變返回值的類型?

重寫與重載的區別:

1)重載發生在一個類中,方法名一致,參數列表不同,和修飾符、異常等無關,是一種編譯時多態。(2)重寫是發生在了父子類中,父子類中存在了方法簽名一致的方法,遵循兩小兩等一大原則,是一種運行時多態。

1)重寫必須繼承,重載不用。(2)重寫的方法名,參數數目相同,參數類型兼容;重載的方法名相同,參數列表不同。(3)重寫的方法修飾符大於等於父類,重載和修飾符無關

重寫要注意 兩等兩小一大原則   1)方法簽名一致。(2)如果父類中方法的返回值類型是基本數據類型/void/最終類,那麼子類在重寫方法的時候,返回值類型要一致。(3)子類方法的權限修飾符的範圍要大於等於父類方法的權限修飾符的範圍。(4)如果父類中方法的返回值類型是一個引用數據類型,那麼子類在重寫方法的時候,返回值類型是父類方法返回值類型的子類或者一致。(5)子類拋出的異常必須小於等於父類,子類不能比父類拋出更多的異常,針對編譯時異常而言,對運行時異常沒有影響。

 

答:Overload是重載的意思,Override是覆蓋的意思,也就是重寫。

1)重載Overload表示同一個類中可以有多個名稱相同的方法,但這些方法的參數列表各不相同(即參數個數或類型不同)。重寫Override表示子類中的方法可以與父類中的某個方法的名稱和參數完全相同,通過子類創建的實例對象調用這個方法時,將調用子類中的定義方法,這相當於把父類中定義的那個完全相同的方法給覆蓋了,這也是面向對象編程的多態性的一種表現。子類覆蓋父類的方法時,只能比父類拋出更少的異常,或者是拋出父類拋出的異常的子異常,因爲子類可以解決父類的一些問題,不能比父類有更多的問題。子類方法的訪問權限只能比父類的更大,不能更小。如果父類的方法是private類型,那麼,子類則不存在覆蓋的限制,相當於子類中增加了一個全新的方法。

2)至於Overloaded的方法是否可以改變返回值的類型這個問題,要看你倒底想問什麼呢?這個題目很模糊。如果幾個Overloaded的方法的參數列表不一樣,它們的返回者類型當然也可以不一樣。但我估計你想問的問題是:如果兩個方法的參數列表完全一樣,是否可以讓它們的返回值不同來實現重載Overload。這是不行的,我們可以用反證法來說明這個問題,因爲我們有時候調用一個方法時也可以不定義返回結果變量,即不要關心其返回結果,例如,我們調用map.remove(key)方法時,雖然remove方法有返回值,但是我們通常都不會定義接收返回結果的變量,這時候假設該類中有兩個名稱和參數列表完全相同的方法,僅僅是返回類型不同,java就無法確定編程者倒底是想調用哪個方法了,因爲它無法通過返回結果類型來判斷。

 

override可以翻譯爲覆蓋,從字面就可以知道,它是覆蓋了一個方法並且對其重寫,以求達到不同的作用。對我們來說最熟悉的覆蓋就是對接口方法的實現,在接口中一般只是對方法進行了聲明,而我們在實現時,就需要實現接口聲明的所有方法。除了這個典型的用法以外,我們在繼承中也可能會在子類覆蓋父類中的方法。在覆蓋要注意以下的幾點:

1、覆蓋的方法的標誌必須要和被覆蓋的方法的標誌完全匹配,才能達到覆蓋的效果;

2、覆蓋的方法的返回值必須和被覆蓋的方法的返回一致;

3、覆蓋的方法所拋出的異常必須和被覆蓋方法的所拋出的異常一致,或者是其子類;

4、被覆蓋的方法不能爲private,否則在其子類中只是新定義了一個方法,並沒有對其進行覆蓋。

overload對我們來說可能比較熟悉,可以翻譯爲重載,它是指我們可以定義一些名稱相同的方法,通過定義不同的輸入參數來區分這些方法,然後再調用時,VM就會根據不同的參數樣式,來選擇合適的方法執行。在使用重載要注意以下的幾點:

1、在使用重載時只能通過不同的參數樣式。例如,不同的參數類型,不同的參數個數,不同的參數順序(當然,同一方法內的幾個參數類型必須不一樣,例如可以是fun(int,float),但是不能爲fun(int,int));

2、不能通過訪問權限、返回類型、拋出的異常進行重載;

3、方法的異常類型和數目不會對重載造成影響;

4、對於繼承來說,如果某一方法在父類中是訪問權限是priavte,那麼就不能在子類對其進行重載,如果定義的話,也只是定義了一個新方法,而不會達到重載的效果。

19ClassLoader如何加載class

答:jvm裏有多個類加載,每個類加載可以負責加載特定位置的類,例如,bootstrap類加載負責加載jre/lib/rt.jar中的類, 我們平時用的jdk中的類都位於rt.jar中。extclassloader負責加載jar/lib/ext/*.jar中的類,appclassloader負責classpath指定的目錄或jar中的類。除了bootstrap之外,其他的類加載器本身也都是java類,它們的父類是ClassLoader

20、抽象類的作用

答:(1)可以通過它實現多態,後期綁定,爲將來想要實現的東西做好接口,實現複用性。(2)寫成抽象類,這樣別人看到你的代碼或者你看到別人的代碼,你就會注意抽象方法,而直到這個抽象方法是在子類中實現的,所以有個提示作用。如:

21、構造器Constructor是否可被override?

答:構造器Constructor不能被繼承,因此不能重寫Override,但可以被重載Overload

22、接口是否可繼承接口? 抽象類是否可實現(implements)接口? 抽象類是否可繼承具體類(concrete class)? 抽象類中是否可以有靜態的main方法?

答:接口可以繼承接口。抽象類可以實現(implements)接口,抽象類是否可繼承具體類。抽象類中可以有靜態的main方法。

備註:只要明白了接口和抽象類的本質和作用,這些問題都很好回答,你想想,如果你是java語言的設計者,你是否會提供這樣的支持,如果不提供的話,有什麼理由嗎?如果你沒有道理不提供,那答案就是肯定的了。

 只有記住抽象類與普通類的唯一區別就是不能創建實例對象和允許有abstract方法。

 

23、寫clone()方法時,通常都有一行代碼,是什麼?

答:clone 有缺省行爲,super.clone();因爲首先要把父類中的成員複製到位,然後纔是複製自己的成員。

24、面向對象的特徵有哪些方面

計算機軟件系統是現實生活中的業務在計算機中的映射,而現實生活中的業務其實就是一個個對象協作的過程。面向對象編程就是按現實業務一樣的方式將程序代碼按一個個對象進行組織和編寫,讓計算機系統能夠識別和理解用對象方式組織和編寫的程序代碼,這樣就可以把現實生活中的業務對象映射到計算機系統中。

面向對象的編程語言有封裝、繼承 、抽象、多態等4個主要的特徵。

1封裝:

封裝保證軟件部件具有優良的模塊性的基礎封裝的目標就是要實現軟件部件的“高內聚、低耦合”,防止程序相互依賴性而帶來的變動影響。在面向對象的編程語言中,對象是封裝的最基本單位面向對象的封裝比傳統語言的封裝更爲清晰、更爲有力面向對象的封裝就是把描述一個對象的屬性和行爲的代碼封裝在一個“模塊”中,也就是一個類中,屬性用變量定義,行爲用方法進行定義,方法可以直接訪問同一個對象中的屬性。通常情況下,只要記住讓變量和訪問這個變量的方法放在一起,將一個類中的成員變量全部定義成私有的,只有這個類自己的方法纔可以訪問到這些成員變量,這就基本上實現對象的封裝,就很容易找出要分配到這個類上的方法了,就基本上算是會面向對象的編程了。把握一個原則:把對同一事物進行操作的方法和相關的方法放在同一個類中,把方法和它操作的數據放在同一個類中。

例如,人要在黑板上畫圓,這一共涉及三個對象:人、黑板、圓,畫圓的方法要分配給哪個對象呢?由於畫圓需要使用到圓心和半徑,圓心和半徑顯然是圓的屬性,如果將它們在類中定義成了私有的成員變量,那麼,畫圓的方法必須分配給圓,它才能訪問到圓心和半徑這兩個屬性,人以後只是調用圓的畫圓方法、表示給圓發給消息而已,畫圓這個方法不應該分配在人這個對象上,這就是面向對象的封裝性,即將對象封裝成一個高度自治和相對封閉的個體,對象狀態(屬性)由這個對象自己的行爲(方法)來讀取和改變。一個更便於理解的例子就是,司機將火車剎住了,剎車的動作是分配給司機,還是分配給火車,顯然,應該分配給火車,因爲司機自身是不可能有那麼大的力氣將一個火車給停下來的,只有火車自己才能完成這一動作,火車需要調用內部的離合器和剎車片等多個器件協作才能完成剎車這個動作,司機剎車的過程只是給火車發了一個消息,通知火車要執行剎車動作而已。

 

抽象:

抽象就是找出一些事物的相似和共性之處,然後將這些事物歸爲一個類,這個類只考慮這些事物的相似和共性之處,並且會忽略與當前主題和目標無關的那些方面,將注意力集中在與當前目標有關的方面。例如,看到一隻螞蟻和大象,你能夠想象出它們的相同之處,那就是抽象。抽象包括行爲抽象和狀態抽象兩個方面。例如,定義一個Person類,如下:

class Person

{

String name;

int age;

}

人本來是很複雜的事物,有很多方面,但因爲當前系統只需要瞭解人的姓名和年齡,所以上面定義的類中只包含姓名和年齡這兩個屬性,這就是一種抽像,使用抽象可以避免考慮一些與目標無關的細節。我對抽象的理解就是不要用顯微鏡去看一個事物的所有方面,這樣涉及的內容就太多了,而是要善於劃分問題的邊界,當前系統需要什麼,就只考慮什麼。

 

繼承:

在定義和實現一個類的時候,可以在一個已經存在的類的基礎之上來進行,把這個已經存在的類所定義的內容作爲自己的內容,並可以加入若干新的內容,或修改原來的方法使之更適合特殊的需要,這就是繼承。繼承是子類自動共享父類數據和方法的機制,這是類之間的一種關係,提高了軟件的可重用性和可擴展性

 

多態:

多態是指程序中定義的引用變量所指向的具體類型和通過該引用變量發出的方法調用在編程時並不確定,而是在程序運行期間才確定,即一個引用變量倒底會指向哪個類的實例對象,該引用變量發出的方法調用到底是哪個類中實現的方法,必須在由程序運行期間才能決定。因爲在程序運行時才確定具體的類,這樣,不用修改源程序代碼,就可以讓引用變量綁定到各種不同的類實現上,從而導致該引用調用的具體方法隨之改變,即不修改程序代碼就可以改變程序運行時所綁定的具體代碼,讓程序可以選擇多個運行狀態,這就是多態性。多態性增強了軟件的靈活性和擴展性。例如,下面代碼中的UserDao是一個接口,它定義引用變量userDao指向的實例對象由daofactory.getDao()在執行的時候返回,有時候指向的是UserJdbcDao這個實現,有時候指向的是UserHibernateDao這個實現,這樣,不用修改源代碼,就可以改變userDao指向的具體類實現,從而導致userDao.insertUser()方法調用的具體代碼也隨之改變,即有時候調用的是UserJdbcDaoinsertUser方法,有時候調用的是UserHibernateDaoinsertUser方法:

UserDao userDao = daofactory.getDao();  

userDao.insertUser(user);

 

比喻:人吃飯,你看到的是左手,還是右手?

25java中實現多態的機制是什麼?

答:靠的是父類或接口定義的引用變量可以指向子類或具體實現類的實例對象,而程序調用的方法在運行期才動態綁定,就是引用變量所指向的具體實例對象的方法,也就是內存里正在運行的那個對象的方法,而不是引用變量的類型中定義的方法。

26abstract classinterface有什麼區別?

答:含有abstract修飾符的class即爲抽象類,abstract 類不能創建的實例對象。含有abstract方法的類必須定義爲abstract classabstract class類中的方法不必是抽象的。abstract class類中定義抽象方法必須在具體(Concrete)子類中實現,所以,不能有抽象構造方法或抽象靜態方法。如果的子類沒有實現抽象父類中的所有抽象方法,那麼子類也必須定義爲abstract類型。

接口(interface)可以說成是抽象類的一種特例,接口中的所有方法都必須是抽象的。接口中的方法定義默認爲public abstract類型,接口中的成員變量類型默認爲public static final

下面比較一下兩者的語法區別:

1.抽象類可以有構造方法,接口中不能有構造方法。

2.抽象類中可以有普通成員變量,接口中沒有普通成員變量

3.抽象類中可以包含非抽象的普通方法,接口中的所有方法必須都是抽象的,不能有非抽象的普通方法。

4. 抽象類中的抽象方法的訪問類型可以是publicprotected和(默認類型,雖然

eclipse下不報錯,但應該也不行),但接口中的抽象方法只能是public類型的,並且默認即爲public abstract類型。

5. 抽象類中可以包含靜態方法,接口中不能包含靜態方法

6. 抽象類和接口中都可以包含靜態成員變量,抽象類中的靜態成員變量的訪問類型可以任意,但接口中定義的變量只能是public static final類型,並且默認即爲public static final類型。

7. 一個類可以實現多個接口,但只能繼承一個抽象類。

下面接着再說說兩者在應用上的區別:

接口更多的是在系統架構設計方法發揮作用,主要用於定義模塊之間的通信契約。而抽象類在代碼實現方面發揮作用,可以實現代碼的重用,例如,模板方法設計模式是抽象類的一個典型應用,假設某個項目的所有Servlet類都要用相同的方式進行權限判斷、記錄訪問日誌和處理異常,那麼就可以定義一個抽象的基類,讓所有的Servlet都繼承這個抽象基類,在抽象基類的service方法中完成權限判斷、記錄訪問日誌和處理異常的代碼,在各個子類中只是完成各自的業務邏輯代碼,僞代碼如下:

public abstract class BaseServlet extends HttpServlet

{

public final void service(HttpServletRequest request, HttpServletResponse response) throws IOExcetion,ServletException

{

記錄訪問日誌

進行權限判斷

if(具有權限)

{

try

{

doService(request,response);

}

catch(Excetpion e)

{

記錄異常信息

}

}

}

protected abstract void doService(HttpServletRequest request, HttpServletResponse response) throws IOExcetion,ServletException;  

//注意訪問權限定義成protected,顯得既專業,又嚴謹,因爲它是專門給子類用的

}

 

public class MyServlet1 extends BaseServlet

{

protected void doService(HttpServletRequest request, HttpServletResponse response) throws IOExcetion,ServletException

{

Servlet只處理的具體業務邏輯代碼

}

 

}

父類方法中間的某段代碼不確定,留給子類幹,就用模板方法設計模式。

備註:這道題的思路是先從總體解釋抽象類和接口的基本概念,然後再比較兩者的語法細節,最後再說兩者的應用區別。比較兩者語法細節區別的條理是:先從一個類中的構造方法、普通成員變量和方法(包括抽象方法),靜態變量和方法,繼承性等6個方面逐一去比較回答,接着從第三者繼承的角度的回答,特別是最後用了一個典型的例子來展現自己深厚的技術功底。

27abstractmethod是否可同時是static,是否可同時是native,是否可同時是synchronized?

答:abstractmethod 不可以是static的,因爲抽象的方法是要被子類實現的,而static與子類扯不上關係!

native方法表示該方法要用另外一種依賴平臺的編程語言實現的,不存在着被子類實現的問題,所以,它也不能是抽象的,不能與abstract混用。例如,FileOutputSteam類要硬件打交道,底層的實現用的是操作系統相關的api實現,例如,在windowsc語言實現的,所以,查看jdk 的源代碼,可以發現FileOutputStreamopen方法的定義如下:

private native void open(String name) throws FileNotFoundException;

如果我們要用java調用別人寫的c語言函數,我們是無法直接調用的,我們需要按照java的要求寫一個c語言的函數,又我們的這個c語言函數去調用別人的c語言函數。由於我們的c語言函數是按java的要求來寫的,我們這個c語言函數就可以與java對接上,java那邊的對接方式就是定義出與我們這個c函數相對應的方法,java中對應的方法不需要寫具體的代碼,但需要在前面聲明native

關於synchronizedabstract合用的問題,我覺得也不行,因爲在我幾年的學習和開發中,從來沒見到過這種情況,並且我覺得synchronized應該是作用在一個具體的方法上纔有意義。而且,方法上的synchronized同步所使用的同步鎖對象是this,而抽象方法上無法確定this是什麼。

28、什麼是內部類?Static Nested Class Inner Class的不同

答:內部類就是在一個類的內部定義的類,內部類中不能定義靜態成員(靜態成員不是對象的特性,只是爲了找一個容身之處,所以需要放到一個類中而已,這麼一點小事,你還要把它放到類內部的一個類中,過分了啊!提供內部類,不是爲讓你幹這種事情,無聊,不讓你幹。我想可能是既然靜態成員類似c語言的全局變量,而內部類通常是用於創建內部對象用的,所以,把“全局變量”放在內部類中就是毫無意義的事情,既然是毫無意義的事情,就應該被禁止),內部類可以直接訪問外部類中的成員變量,內部類可以定義在外部類的方法外面,也可以定義在外部類的方法體中,如下所示:

public class Outer

{

int out_x  = 0;

public void method()
{

Inner1 inner1 = new Inner1();

public class Inner2   //在方法體內部定義的內部類

{

public method()

{

out_x = 3;

}

}

Inner2 inner2 = new Inner2();

}

 

public class Inner1   //在方法體外面定義的內部類

{

}

}

在方法體外面定義的內部類的訪問類型可以是public,protecte,默認的,private4種類型,這就好像類中定義的成員變量有4種訪問類型一樣,它們決定這個內部類的定義對其他類是否可見;對於這種情況,我們也可以在外面創建內部類的實例對象,創建內部類的實例對象時,一定要先創建外部類的實例對象,然後用這個外部類的實例對象去創建內部類的實例對象,代碼如下:

Outer outer = new Outer();

Outer.Inner1 inner1 = outer.new Innner1();

 

在方法內部定義的內部類前面不能有訪問類型修飾符,就好像方法中定義的局部變量一樣,但這種內部類的前面可以使用finalabstract修飾符。這種內部類對其他類是不可見的其他類無法引用這種內部類,但是這種內部類創建的實例對象可以傳遞給其他類訪問。這種內部類必須是先定義,後使用,即內部類的定義代碼必須出現在使用該類之前,這與方法中的局部變量必須先定義後使用的道理也是一樣的。這種內部類可以訪問方法體中的局部變量,但是,該局部變量前必須加final修飾符。

對於這些細節,只要在eclipse寫代碼試試,根據開發工具提示的各類錯誤信息就可以馬上瞭解到。

 

在方法體內部還可以採用如下語法來創建一種匿名內部類,即定義某一接口或類的子類的同時,還創建了該子類的實例對象,無需爲該子類定義名稱:

public class Outer

{

public void start()

{

new Thread(

new Runable(){

public void run(){};

}

).start();

}

}

 

最後,在方法外部定義的內部類前面可以加上static關鍵字,從而成爲Static Nested Class,它不再具有內部類的特性,所有,從狹義上講,它不是內部類。Static Nested Class與普通類在運行時的行爲和功能上沒有什麼區別,只是在編程引用時的語法上有一些差別,它可以定義成publicprotected、默認的、private等多種類型,而普通類只能定義成public和默認的這兩種類型。在外面引用Static Nested Class類的名稱爲“外部類名.內部類名”。在外面不需要創建外部類的實例對象,就可以直接創建Static Nested Class,例如,假設Inner是定義在Outer類中的Static Nested Class,那麼可以使用如下語句創建Inner類:

Outer.Inner inner = new Outer.Inner();

由於static Nested Class不依賴於外部類的實例對象,所以,static Nested Class能訪問外部類的非static成員變量。當在外部類中訪問Static Nested Class時,可以直接使用Static Nested Class的名字,而不需要加上外部類的名字了,在Static Nested Class中也可以直接引用外部類的static的成員變量,不需要加上外部類的名字。

在靜態方法中定義的內部類也是Static Nested Class,這時候不能在類前面加static關鍵字,靜態方法中的Static Nested Class與普通方法中的內部類的應用方式很相似,它除了可以直接訪問外部類中的static的成員變量,還可以訪問靜態方法中的局部變量,但是,該局部變量前必須加final修飾符。

 

備註:首先根據你的印象說出你對內部類的總體方面的特點:例如,在兩個地方可以定義,可以訪問外部類的成員變量,不能定義靜態成員,這是大的特點。然後再說一些細節方面的知識,例如,幾種定義方式的語法區別,靜態內部類,以及匿名內部類。

29、內部類可以引用它的包含類的成員嗎?有沒有什麼限制?

答:完全可以。如果不是靜態內部類,那沒有什麼限制!

如果你把靜態嵌套類當作內部類的一種特例,那在這種情況下不可以訪問外部類的普通成員變量,而只能訪問外部類中的靜態成員,例如,下面的代碼:

class Outer

{

static int x;

static class Inner

{

void test()

{

syso(x);

}

}

}

 

答題時,也要能察言觀色,揣摩提問者的心思,顯然人家希望你說的是靜態內部類不能訪問外部類的成員,但你一上來就頂牛,這不好,要先順着人家,讓人家滿意,然後再說特殊情況,讓人家吃驚。

 

29Anonymous Inner Class (匿名內部類) 是否可以extends(繼承)其它類,是否可以implements(實現)interface(接口)?

答:可以繼承其他類或實現其他接口。不僅是可以,而是必須!

30super.getClass()方法調用

下面程序的輸出結果是多少?

import java.util.Date;

public  class Test extends Date{

public static void main(String[] args) {

new Test().test();

}

public void test(){

System.out.println(super.getClass().getName());

}

}

 

很奇怪,結果是Test

這屬於腦筋急轉彎的題目,在一個qq羣有個網友正好問過這個問題,我覺得挺有趣,就研究了一下,沒想到今天還被你面到了,哈哈。

test方法中,直接調用getClass().getName()方法,返回的是Test類名

由於getClass()Object類中定義成了final,子類不能覆蓋該方法,所以,在

test方法中調用getClass().getName()方法,其實就是在調用從父類繼承的getClass()方法,等效於調用super.getClass().getName()方法,所以,super.getClass().getName()方法返回的也應該是Test

如果想得到父類的名稱,應該用如下代碼:

getClass().getSuperClass().getName();

 

31jdk中哪些類是不能繼承的?

答:不能繼承的是類是那些用final關鍵字修飾的類。一般比較基本的類型防止擴展類無意間破壞原來方法的實現的類型都應該是final,在jdkSystem,String,StringBuffer等都是基本類型。

32String是最基本的數據類型嗎?

答:基本數據類型包括byteintcharlongfloatdoublebooleanshort

java.lang.String類是final類型的,因此不可以繼承這個類、不能修改這個類。爲了提高效率節省空間,我們應該用StringBuffer

 

33String s = "Hello";s = s + " world!";這兩行代碼執行後,原始的String對象中的內容到底變了沒有?
答:沒有。因爲String被設計成不可變(immutable)類,所以它的所有對象都是不可變對象。在這段代碼中,s原先指向一個String對象,內容是 "Hello",然後我們對s進行了+操作,那麼s所指向的那個對象是否發生了改變呢?答案是沒有。這時,s不指向原來那個對象了,而指向了另一個 String對象,內容爲"Hello world!",原來那個對象還存在於內存之中,只是s這個引用變量不再指向它了。
通過上面的說明,我們很容易導出另一個結論,如果經常對字符串進行各種各樣的修改,或者說,不可預見的修改,那麼使用String來代表字符串的話會引起很大的內存開銷。因爲 String對象建立之後不能再改變,所以對於每一個不同的字符串,都需要一個String對象來表示。這時,應該考慮使用StringBuffer類,它允許修改,而不是每個不同的字符串都要生成一個新的對象。並且,這兩種類的對象轉換十分容易。
同時,我們還可以知道,如果要使用內容相同的字符串,不必每次都new一個String。例如我們要在構造器中對一個名叫sString引用變量進行初始化,把它設置爲初始值,應當這樣做:
public class Demo {
private String s;
...
public Demo {
s = "Initial Value";
}
...
}
而非
s = new String("Initial Value");
後者每次都會調用構造器,生成新對象,性能低下且內存開銷大,並且沒有意義,因爲String對象不可改變,所以對於內容相同的字符串,只要一個String對象來表示就可以了。也就說,多次調用上面的構造器創建多個對象,他們的String類型屬性s都指向同一個對象。
上面的結論還基於這樣一個事實:對於字符串常量,如果內容相同,Java認爲它們代表同一個String對象。而用關鍵字new調用構造器,總是會創建一個新的對象,無論內容是否相同。
至於爲什麼要把String類設計成不可變類,是它的用途決定的。其實不只String,很多Java標準類庫中的類都是不可變的。在開發一個系統的時候,我們有時候也需要設計不可變類,來傳遞一組相關的值,這也是面向對象思想的體現。不可變類有一些優點,比如因爲它的對象是隻讀的,所以多線程併發訪問也不會有任何問題。當然也有一些缺點,比如每個不同的狀態都要一個對象來代表,可能會造成性能上的問題。所以Java標準類庫還提供了一個可變版本,即 StringBuffer

34、是否可以繼承String? 

答:String類是final類故不可以繼承。

 

35String s = new String("xyz");創建了幾個String Object? 二者之間有什麼區別?

答:兩個或一個,”xyz”對應一個對象,這個對象放在字符串常量緩衝區,常量”xyz”不管出現多少遍,都是緩衝區中的那一個。New String每寫一遍,就創建一個新的對象,它一句那個常量”xyz”對象的內容來創建出一個新String對象。如果以前就用過’xyz’,這句代表就不會創建”xyz”自己了,直接從緩衝區拿。

36String StringBuffer的區別?

答:JAVA平臺提供了兩個類:StringStringBuffer,它們可以儲存和操作字符串,即包含多個字符的字符數據。String類表示內容不可改變的字符串。而StringBuffer類表示內容可以被修改的字符串。當你知道字符數據要改變的時候你就可以使用StringBuffer。典型地,你可以使用StringBuffers來動態構造字符數據。另外,String實現了equals方法,new String(“abc”).equals(new String(“abc”)的結果爲true,StringBuffer沒有實現equals方法,所以,new StringBuffer(“abc”).equals(new StringBuffer(“abc”)的結果爲false

 

接着要舉一個具體的例子來說明,我們要把1100的所有數字拼起來,組成一個串。

StringBuffer sbf = new StringBuffer();  

for(int i=0;i<100;i++)

{

sbf.append(i);

}

上面的代碼效率很高,因爲只創建了一個StringBuffer對象,而下面的代碼效率很低,因爲創建了101個對象。

String str = new String();  

for(int i=0;i<100;i++)

{

str = str + i;

}

在講兩者區別時,應把循環的次數搞成10000,然後用endTime-beginTime來比較兩者執行的時間差異,最後還要講講StringBuilderStringBuffer的區別。

 

String覆蓋了equals方法和hashCode方法,而StringBuffer沒有覆蓋equals方法和hashCode方法,所以,將StringBuffer對象存儲進Java集合類中時會出現問題。

 

37.StringBufferStringBuilder的區別

  StringBufferStringBuilder類都表示內容可以被修改的字符串,StringBuilder是線程不安全的,運行效率高,如果一個字符串變量是在方法裏面定義,這種情況只可能有一個線程訪問它,不存在不安全的因素了,則用StringBuilder。如果要在類裏面定義成員變量,並且這個類的實例對象會在多線程環境下使用,那麼最好用StringBuffer

 

38如何把一段逗號分割的字符串轉換成一個數組?

如果不查jdk api,我很難寫出來!我可以說說我的思路:

用正則表達式,代碼大概爲:String [] result = orgStr.split(“,”);

StingTokenizer ,代碼爲:StringTokenizer  tokener = StringTokenizer(orgStr,”,”);

String [] result = new String[tokener .countTokens()];

Int i=0;

while(tokener.hasNext(){result[i++]=toker.nextToken();}

 

39、數組有沒有length()這個方法? String有沒有length()這個方法?

數組沒有length()這個方法,有length的屬性。String有有length()這個方法

40、下面這條語句一共創建了多少個對象:String s="a"+"b"+"c"+"d";

答:對於如下代碼:

String s1 = "a";

String s2 = s1 + "b";

String s3 = "a" + "b";

System.out.println(s2 == "ab");

System.out.println(s3 == "ab");

第一條語句打印的結果爲false,第二條語句打印的結果爲true,這說明javac編譯可以對字符串常量直接相加的表達式進行優化,不必要等到運行期去進行加法運算處理,而是在編譯時去掉其中的加號,直接將其編譯成一個這些常量相連的結果。

題目中的第一行代碼被編譯器在編譯時優化後,相當於直接定義了一個”abcd”的字符串,所以,上面的代碼應該只創建了一個String對象。寫如下兩行代碼,

String s = "a" + "b" + "c" + "d";

System.out.println(s == "abcd");

最終打印的結果應該爲true

 

 

41try {}裏有一個return語句,那麼緊跟在這個try後的finally {}裏的code會不會被執行,什麼時候被執行,在return前還是後?

也許你的答案是在return之前,但往更細地說,我的答案是在return中間執行,請看下面程序代碼的運行結果:

public  class Test {

 

/**

 * @param args add by zxx ,Dec 9, 2008

 */

public static void main(String[] args) {

// TODO Auto-generated method stub

System.out.println(new Test().test());;

}

 

static int test()

{

int x = 1;

try

{

return x;

}

finally

{

++x;

}

}

}

 

---------執行結果 ---------

1

 

運行結果是1,爲什麼呢?主函數調用子函數並得到結果的過程,好比主函數準備一個空罐子,當子函數要返回結果時,先把結果放在罐子裏,然後再將程序邏輯返回到主函數。所謂返回,就是子函數說,我不運行了,你主函數繼續運行吧,這沒什麼結果可言,結果是在說這話之前放進罐子裏的。

42、下面的程序代碼輸出的結果是多少?

public class  smallT

{

public static void  main(String args[])

{

smallT t  = new  smallT();

int  b  =  t.get();

System.out.println(b);

}

public int  get()

{

try

{

return 1 ;

}

finally

{

return 2 ;

}

}

}

 

返回的結果是2

我可以通過下面一個例子程序來幫助我解釋這個答案,從下面例子的運行結果中可以發現,try中的return語句調用的函數先於finally中調用的函數執行,也就是說return語句先執行,finally語句後執行,所以,返回的結果是2Return並不是讓函數馬上返回,而是return語句執行後,將把返回結果放置進函數棧中,此時函數並不是馬上返回,它要執行finally語句後才真正開始返回。

在講解答案時可以用下面的程序來幫助分析:

public  class Test {

 

/**

 * @param args add by zxx ,Dec 9, 2008

 */

public static void main(String[] args) {

// TODO Auto-generated method stub

System.out.println(new Test().test());;

}

 

int test()

{

try

{

return func1();

}

finally

{

return func2();

}

}

int func1()

{

System.out.println("func1");

return 1;

}

int func2()

{

System.out.println("func2");

return 2;

}

}

-----------執行結果-----------------

 

func1

func2

2

 

結論:finally中的代碼比return break語句後執行

 

43final, finally, finalize的區別。

 final 用於聲明屬性,方法和類,分別表示屬性不可變,方法不可覆蓋,類不可繼承。

內部類要訪問局部變量,局部變量必須定義成final類型,例如,一段代碼……

 

finally是異常處理語句結構的一部分,表示總是執行。

 

 

finalizeObject類的一個方法,在垃圾收集器執行的時候會調用被回收對象的此方法,可以覆蓋此方法提供垃圾收集時的其他資源回收,例如關閉文件等。JVM不保證此方法總被調用

 

45、運行時異常與一般異常有何異同?

異常表示程序運行過程中可能出現的非正常狀態,運行時異常表示虛擬機的通常操作中可能遇到的異常,是一種常見運行錯誤。java編譯器要求方法必須聲明拋出可能發生的非運行時異常,但是並不要求必須聲明拋出未被捕獲的運行時異常。

46errorexception有什麼區別?

error 表示恢復不是不可能但很困難的情況下的一種嚴重問題。比如說內存溢出。不可能指望程序能處理這樣的情況。 exception 表示一種設計或實現問題。也就是說,它表示如果程序運行正常,從不會發生的情況。

 

47Java中的異常處理機制的簡單原理和應用

異常是指java程序運行時(非編譯)所發生的非正常情況或錯誤,與現實生活中的事件很相似,現實生活中的事件可以包含事件發生的時間、地點、人物、情節等信息,可以用一個對象來表示,Java使用面向對象的方式來處理異常,它把程序中發生的每個異常也都分別封裝到一個對象來表示的,該對象中包含有異常的信息。

Java對異常進行了分類,不同類型的異常分別用不同的Java類表示,所有異常的根類爲java.lang.ThrowableThrowable下面又派生了兩個子類:ErrorExceptionError 表示應用程序本身無法克服和恢復的一種嚴重問題,程序只有死的份了,例如,說內存溢出和線程死鎖等系統問題。Exception表示程序還能夠克服和恢復的問題,其中又分爲系統異常和普通異常,系統異常是軟件本身缺陷所導致的問題,也就是軟件開發人員考慮不周所導致的問題,軟件使用者無法克服和恢復這種問題,但在這種問題下還可以讓軟件系統繼續運行或者讓軟件死掉,例如,數組腳本越界(ArrayIndexOutOfBoundsException),空指針異常(NullPointerException)、類轉換異常(ClassCastException);普通異常是運行環境的變化或異常所導致的問題,是用戶能夠克服的問題,例如,網絡斷線,硬盤空間不夠,發生這樣的異常後,程序不應該死掉。

java爲系統異常和普通異常提供了不同的解決方案,編譯器強制普通異常必須try..catch處理或用throws聲明繼續拋給上層調用方法處理,所以普通異常也稱爲checked異常,而系統異常可以處理也可以不處理,所以,編譯器不強制用try..catch處理或用throws聲明,所以系統異常也稱爲unchecked異常。

 

提示答題者:就按照三個級別去思考:虛擬機必須宕機的錯誤,程序可以死掉也可以不死掉的錯誤,程序不應該死掉的錯誤;

 

 

48、請寫出你最常見到的5runtime exception

這道題主要考你的代碼量到底多大,如果你長期寫代碼的,應該經常都看到過一些系統方面的異常,你不一定真要回答出5個具體的系統異常,但你要能夠說出什麼是系統異常,以及幾個系統異常就可以了,當然,這些異常完全用其英文名稱來寫是最好的,如果實在寫不出,那就用中文吧,有總比沒有強!

所謂系統異常,就是…..,它們都是RuntimeException的子類,在jdk doc中查RuntimeException類,就可以看到其所有的子類列表,也就是看到了所有的系統異常。我比較有印象的系統異常有:NullPointerExceptionArrayIndexOutOfBoundsExceptionClassCastException。

49JAVA語言如何進行異常處理,關鍵字:throws,throw,try,catch,finally分別代表什麼意義?在try塊中可以拋出異常嗎?

50ArrayListVector的區別

答:這兩個類都實現了List接口(List接口繼承了Collection接口),他們都是有序集合,即存儲在這兩個集合中的元素的位置都是有順序的,相當於一種動態的數組,我們以後可以按位置索引號取出某個元素,,並且其中的數據是允許重複的,這是HashSet之類的集合的最大不同處,HashSet之類的集合不可以按索引號去檢索其中的元素,也不允許有重複的元素(本來題目問的與hashset沒有任何關係,但爲了說清楚ArrayListVector的功能,我們使用對比方式,更有利於說明問題)。

 

接着才說ArrayListVector的區別,這主要包括兩個方面:.
1同步性

Vector是線程安全的,也就是說是它的方法之間是線程同步的,而ArrayList是線程序不安全的,它的方法之間線程不同步的。如果只有一個線程會訪問到集合,那最好是使用ArrayList,因爲它不考慮線程安全,效率會高些;如果有多個線程會訪問到集合,那最好是使用Vector,因爲不需要我們自己再去考慮和編寫線程安全的代碼。

 

備註:對於Vector&ArrayListHashtable&HashMap,要記住線程安全的問題,記住VectorHashtable是舊的,是java一誕生就提供了的,它們是線程安全的,ArrayListHashMapjava2時才提供的,它們是線程不安全的。所以,我們講課時先講老的。
2數據增長

ArrayListVector都有一個初始的容量大小,存儲進它們裏面的元素的個數超過了容量時,就需要增加ArrayListVector的存儲空間,每次要增加存儲空間時,不是隻增加一個存儲單元,而是增加多個存儲單元,每次增加的存儲單元的個數在內存空間利用與程序效率之間要取得一定的平衡。Vector默認增長爲原來兩倍,而ArrayList增長策略在文檔中沒有明確規定(從源代碼看到的是增長爲原來1.5倍)。ArrayListVector都可以設置初始的空間大小,Vector還可以設置增長的空間大小,而ArrayList沒有提供設置增長空間的方法。

    總結:即Vector增長原來的一倍,ArrayList增加原來的0.5

51、說出ArrayList,Vector, LinkedList的存儲性能和特性

ArrayListVector都是使用數組方式存儲數據,此數組元素數大於實際存儲的數據以便增加和插入元素,它們都允許直接按序號索引元素,但是插入元素要涉及數組元素移動等內存操作,所以索引數據快而插入數據慢,Vector由於使用了synchronized方法(線程安全),通常性能上較ArrayList差,而LinkedList使用雙向鏈表實現存儲,按序號索引數據需要進行前向或後向遍歷,但是插入數據時只需要記錄本項的前後項即可,所以插入速度較快。

 

LinkedList也是線程不安全的,LinkedList提供了一些方法,使得LinkedList可以被當作堆棧和隊列來使用。

52、去掉一個Vector集合中重複的元素

Vector newVector = new Vector();

For (int i=0;i<vector.size();i++)

{

Object obj = vector.get(i);

if(!newVector.contains(obj);

newVector.add(obj);

}

還有一種簡單的方式,HashSet set = new HashSet(vector);

53Collection Collections的區別。

  Collection是集合類的上級接口,繼承與他的接口主要有Set List.

Collections是針對集合類的一個幫助類,他提供一系列靜態方法實現對各種集合的搜索、排序、線程安全化等操作。

39Set裏的元素是不能重複的,那麼用什麼方法來區分重複與否呢? 是用==還是equals()? 它們有何區別?

Set裏的元素是不能重複的,元素重複與否是使用equals()方法進行判斷的。

   equals()==方法決定引用值是否指向同一對象equals()在類中被覆蓋,爲的是當兩個分離的對象的內容和類型相配的話,返回真值。

 

54、你所知道的集合類都有哪些?主要方法?

最常用的集合類是 List MapList 的具體實現包括 ArrayList Vector,它們是可變大小的列表,比較適合構建、存儲和操作任何類型對象的元素列表。 List 適用於按數值索引訪問元素的情形。

Map 提供了一個更通用的元素存儲方法。 Map 集合類用於存儲元素對(稱作""""),其中每個鍵映射到一個值。

 

ArrayList/VectoràList

                    àCollection

HashSet/TreeSetàSet

 

PropetiesàHashTable

àMap

Treemap/HashMap

 

我記的不是方法名,而是思想,我知道它們都有增刪改查的方法,但這些方法的具體名稱,我記得不是很清楚,對於set,大概的方法是add,remove, contains;對於map,大概的方法就是put,removecontains等,因爲,我只要在eclispe下按點操作符,很自然的這些方法就出來了。我記住的一些思想就是List類會有get(int index)這樣的方法,因爲它可以按順序取元素,而set類中沒有get(int index)這樣的方法。Listset都可以迭代出所有元素,迭代時先要得到一個iterator對象,所以,setlist類都有一個iterator方法,用於返回那個iterator對象。map可以返回三個集合,一個是返回所有的key的集合,另外一個返回的是所有value的集合,再一個返回的keyvalue組合成的EntrySet對象的集合,map也有get方法,參數是key,返回值是key對應的value

 

55、兩個對象值相同(x.equals(y) == true),但卻可有不同的hash code,這句話對不對?

對。

如果對象要保存在HashSetHashMap中,它們的equals相等,那麼,它們的hashcode值就必須相等。

如果不是要保存在HashSetHashMap,則與hashcode沒有什麼關係了,這時候hashcode不等是可以的,例如arrayList存儲的對象就不用實現hashcode,當然,我們沒有理由不實現,通常都會去實現的。

56TreeSet裏面放對象,如果同時放入了父類和子類的實例對象,那比較時使用的是父類的compareTo方法,還是使用的子類的compareTo方法,還是拋異常!

(應該是沒有針對問題的確切的答案,當前的add方法放入的是哪個對象,就調用哪個對象的compareTo方法,至於這個compareTo方法怎麼做,就看當前這個對象的類中是如何編寫這個方法的)

實驗代碼:

public class Parent implements Comparable {

private int age = 0;

public Parent(int age){

this.age = age;

}

public int compareTo(Object o) {

// TODO Auto-generated method stub

System.out.println("method of parent");

Parent o1 = (Parent)o;

return age>o1.age?1:age<o1.age?-1:0;

}

 

}

 

public class Child extends Parent {

 

public Child(){

super(3);

}

public int compareTo(Object o) {

 

// TODO Auto-generated method stub

System.out.println("method of child");

// Child o1 = (Child)o;

return 1;

 

}

}

 

public class TreeSetTest {

 

/**

 * @param args

 */

public static void main(String[] args) {

// TODO Auto-generated method stub

TreeSet set = new TreeSet();

set.add(new Parent(3));

set.add(new Child());

set.add(new Parent(4));

System.out.println(set.size());

}

 

}

 

 

57、說出一些常用的類,包,接口,請各舉5

要讓人家感覺你對java ee開發很熟,所以,不能僅僅只列core java中的那些東西,要多列你在做ssh項目中涉及的那些東西。就寫你最近寫的那些程序中涉及的那些類。

 

常用的類:BufferedReader  BufferedWriter  FileReader  FileWirter  String  Integer

java.util.DateSystemClassList,HashMap

 

常用的包:java.lang   java.io  java.util  java.sql ,javax.servlet,org.apache.strtuts.action,org.hibernate

常用的接口:Remote  List  Map  Document  NodeList ,Servlet,HttpServletRequest,HttpServletResponse,Transaction(Hibernate)Session(Hibernate),HttpSession

58、描述一下JVM加載class文件的原理機制?

JVM中類的裝載是由ClassLoader和它的子類來實現的,Java ClassLoader 是一個重要的Java運行時系統組件。它負責在運行時查找和裝入類文件的類。

59heapstack有什麼區別。

java的內存分爲兩類,一類是棧內存,一類是堆內存。棧內存是指程序進入一個方法時,會爲這個方法單獨分配一塊私屬存儲空間,用於存儲這個方法內部的局部變量,當這個方法結束時,分配給這個方法的棧會釋放,這個棧中的變量也將隨之釋放。

堆是與棧作用不同的內存,一般用於存放不放在當前方法棧中的那些數據,例如,使用new創建的對象都放在堆裏,所以,它不會隨方法的結束而消失。方法中的局部變量使用final修飾後,放在堆中,而不是棧中。

60GC是什麼? 爲什麼要有GC?

GC是垃圾收集的意思(Gabage Collection,內存處理是編程人員容易出現問題的地方,忘記或者錯誤的內存回收會導致程序或系統的不穩定甚至崩潰,Java提供的GC功能可以自動監測對象是否超過作用域從而達到自動回收內存的目的,Java語言沒有提供釋放已分配內存的顯示操作方法。

 

61、垃圾回收的優點和原理。並考慮2種回收機制。

Java語言中一個顯著的特點就是引入了垃圾回收機制,使c++程序員最頭疼的內存管理的問題迎刃而解,它使得Java程序員在編寫程序的時候不再需要考慮內存管理。由於有個垃圾回收機制,Java中的對象不再有"作用域"的概念,只有對象的引用纔有"作用域"。垃圾回收可以有效的防止內存泄露,有效的使用可以使用的內存。垃圾回收器通常是作爲一個單獨的低級別的線程運行,不可預知的情況下對內存堆中已經死亡的或者長時間沒有使用的對象進行清楚和回收,程序員不能實時的調用垃圾回收器對某個對象或所有對象進行垃圾回收。回收機制有分代複製垃圾回收和標記垃圾回收,增量垃圾回收。

 

62、垃圾回收器的基本原理是什麼?垃圾回收器可以馬上回收內存嗎?有什麼辦法主動通知虛擬機進行垃圾回收?

對於GC來說,當程序員創建對象時,GC就開始監控這個對象的地址、大小以及使用情況。通常,GC採用有向圖的方式記錄和管理堆(heap)中的所有對象。通過這種方式確定哪些對象是"可達的",哪些對象是"不可達的"。當GC確定一些對象爲"不可達"時,GC就有責任回收這些內存空間。可以。程序員可以手動執行System.gc(),通知GC運行,但是Java語言規範並不保證GC一定會執行。

 

63、能不能自己寫個類,也叫java.lang.String

 

可以,但在應用的時候,需要用自己的類加載器去加載,否則,系統的類加載器永遠只是去加載jre.jar包中的那個java.lang.String。由於在tomcatweb應用程序中,都是由webapp自己的類加載器先自己加載WEB-INF/classess目錄中的類,然後才委託上級的類加載器加載,如果我們在tomcatweb應用程序中寫一個java.lang.String,這時候Servlet程序加載的就是我們自己寫的java.lang.String,但是這麼幹就會出很多潛在的問題,原來所有用了java.lang.String類的都將出現問題。

 

雖然java提供了endorsed技術,可以覆蓋jdk中的某些類,具體做法是….。但是,能夠被覆蓋的類是有限制範圍,反正不包括java.lang這樣的包中的類。

 

(下面的例如主要是便於大家學習理解只用,不要作爲答案的一部分,否則,人家懷疑是題目泄露了)例如,運行下面的程序:

package java.lang;

 

public class String {

 

/**

 * @param args

 */

public static void main(String[] args) {

// TODO Auto-generated method stub

System.out.println("string");

}

 

}

報告的錯誤如下:

java.lang.NoSuchMethodError: main

Exception in thread "main"

這是因爲加載了jre自帶的java.lang.String,而該類中沒有main方法。

 

程序題

21ArrayList如何實現插入的數據按自定義的方式有序存放

class MyBean implements Comparable{

public int compareTo(Object obj){

if(! obj instanceof MyBean)

throw new ClassCastException() //具體異常的名稱,我要查jdk文檔。

MyBean other = (MyBean) obj;

return age > other.age?1:age== other.age?0:-1;

}

}

 

 

class MyTreeSet {

 

private ArrayList  datas = new ArrayList();

public void add(Object obj){

for(int i=0;i<datas.size();i++){

if(obj.compareTo(datas.get(i) != 1){

datas.add(i,obj);

}

}

}

}

22.設計出計算任意正整數的階層

import java.util.Scanner;

public class Exer3{

public static void main(String[] args){

Scanner s = new Scanner(System.in);

int number = s.nextInt();

System.out.println(factorial(number));

}

public static long factorial(int number){

if(number == 0){

return 1;

}

return number *factorial(--number);

}

}

23新題目:編程:1.編寫一個函數將一個十六進制數的字符串參數轉換成整數返回。

String str = “13abf”;

int len = str.length;

int sum = 0;

for(int i=0;i<len;i++){

char c = str.charAt(len-1-i);

int n = Character.digit(c,16);

sum += n * (1<<(4*i));

}

      

     其實,也可以用Integer.parseInt(str,16),但面試官很可能是想考我們的編碼基本功。

 

編程2

   :銀行貸款的還款方式中最常用的是一種叫“等額本息”,還款法,即借款人在約定還款期限內的每一期(月)歸還的金額(產生的利息+部分本金)都是相等的,現有一筆總額爲T元的N年期住房貸款,年利率爲R,要求算出每一期的還款的本金和利息總額,請寫出解決思路和任意一種編程語言實現的主要代碼。

思路:既然是按月還款,那我就要將N年按月來計算,即要還N*12個月,這樣就可以求出每月要還的本金。由於每月要還的那部分本金所欠的時間不同,所以,它們所產生的利息是不同的,該部分本金的利息爲:部分本金額*所欠月數*月利率。應該是這麼個算法,如果利息還計利息,如果月還款不按年利率來算,老百姓算不明白的。

int monthMoney = T/N/12;

float monthRate = R/12;

int totalMonth = N * 12;

float totalRate = 0;

for(int i=1;i<=totalMonth;i++){

totalRate += monthMoney * monthRate * i;

}

int result = monthMoney + totalRate/N/12;

2. *任意數字序列“123456”之類,輸出它們所有的排列組合

String str = “xafdvs”;

char[] arr1 = str.toCharArray();

char[] arr2 = Arrays.copyOf(arr1,arr1.length);

for(int i=0;i<arr1.length-1;i++)

{

for(int j = i+1;j<arr2.length;j++){

syso: arr1[i] + “,” + arr2[j];

}

}

Java代碼查錯

1.
abstract class Name {
   private String name;
   public abstract boolean isStupidName(String name) {}
}
大俠們,這有何錯誤?
答案: 錯。abstract method必須以分號結尾,且不帶花括號。
2.
public class Something {
   void doSomething () {
       private String s = "";
       int l = s.length();
   }
}
有錯嗎?
答案: 錯。局部變量前不能放置任何訪問修飾符 (privatepublic,和protected)final可以用來修飾局部變量
(final如同abstractstrictfp,都是非訪問修飾符,strictfp只能修飾classmethod而非variable)
3.
abstract class Something {
   private abstract String doSomething ();
}
這好像沒什麼錯吧?
答案: 錯。abstractmethods不能以private修飾。abstractmethods就是讓子類implement(實現)具體細節的,怎麼可以用privateabstract
method封鎖起來呢? (同理,abstract method前不能加final)
4.
public class Something {
   public int addOne(final int x) {
       return ++x;
   }
}
這個比較明顯。
答案: 錯。int x被修飾成final,意味着x不能在addOne method中被修改。
5.
public class Something {
   public static void main(String[] args) {
       Other o = new Other();
       new Something().addOne(o);
   }
   public void addOne(final Other o) {
       o.i++;
   }
}
class Other {
   public int i;
}
和上面的很相似,都是關於final的問題,這有錯嗎?
答案: 正確。在addOne method中,參數o被修飾成final。如果在addOne method裏我們修改了oreference
(比如: o = new Other();),那麼如同上例這題也是錯的。但這裏修改的是omember vairable
(成員變量),而oreference並沒有改變。
6.
class Something {
    int i;
    public void doSomething() {
        System.out.println("i = " + i);
    }
}
有什麼錯呢? 看不出來啊。
答案: 正確。輸出的是"i = 0"int i屬於instant variable (實例變量,或叫成員變量)instant variabledefault valueintdefault value0
7.
class Something {
    final int i;
    public void doSomething() {
        System.out.println("i = " + i);
    }
}
和上面一題只有一個地方不同,就是多了一個final。這難道就錯了嗎?
答案: 錯。final int i是個finalinstant variable (實例變量,或叫成員變量)finalinstant variable沒有default value,必須在constructor (構造器)結束之前被賦予一個明確的值。可以修改爲"final int i = 0;"
8.
public class Something {
     public static void main(String[] args) {
        Something s = new Something();
        System.out.println("s.doSomething() returns " + doSomething());
    }
    public String doSomething() {
        return "Do something ...";
    }
}
 看上去很完美。
答案: 錯。看上去在maincall doSomething沒有什麼問題,畢竟兩個methods都在同一個class裏。但仔細看,mainstatic的。static method不能直接call non-static methods。可改成"System.out.println("s.doSomething() returns " + s.doSomething());"。同理,static method不能訪問non-static instant variable
9.
此處,Something類的文件名叫OtherThing.java
class Something {
    private static void main(String[] something_to_do) {       
        System.out.println("Do something ...");
    }
}
 這個好像很明顯。
答案: 正確。從來沒有人說過JavaClass名字必須和其文件名相同。但public class的名字必須和文件名相同。
10
interface  A{
   int x = 0;
}
class B{
   int x =1;
}
class C extends B implements A {
   public void pX(){
      System.out.println(x);
   }
   public static void main(String[] args) {
      new C().pX();
   }
}
答案:錯誤。在編譯時會發生錯誤(錯誤描述不同的JVM有不同的信息,意思就是未明確的x調用,兩個x都匹配(就象在同時import java.utiljava.sql兩個包時直接聲明Date一樣)。對於父類的變量,可以用super.x來明確,而接口的屬性默認隱含爲 public static final.所以可以通過A.x來明確。
11.
interface Playable {
    void play();
}
interface Bounceable {
    void play();
}
interface Rollable extends Playable, Bounceable {
    Ball ball = new Ball("PingPang");
}
class Ball implements Rollable {
    private String name;
    public String getName() {
        return name;
    }
    public Ball(String name) {
        this.name = name;       
    }
   public void play() {
        ball = new Ball("Football");
        System.out.println(ball.getName());
    }
}
這個錯誤不容易發現。
答案: 錯。"interface Rollable extends Playable, Bounceable"沒有問題。interface可繼承多個interfaces,所以這裏沒錯。問題出在interface Rollable裏的"Ball ball = new Ball("PingPang");"。任何在interface裏聲明的interface variable (接口變量,也可稱成員變量),默認爲public static final。也就是說"Ball ball = new Ball("PingPang");"實際上是"public static final Ball ball = new Ball("PingPang");"。在Ball類的Play()方法中,"ball = new Ball("Football");"改變了ballreference,而這裏的ball來自Rollable interfaceRollable interface裏的ballpublic static final的,finalobject是不能被改變reference的。因此編譯器將在"ball = new Ball("Football");"這裏顯示有錯。

1.判斷身份證:要麼是15位,要麼是18位,最後一位可以爲字母,並寫程序提出其中的年月日。

答:我們可以用正則表達式來定義複雜的字符串格式,(\d{17}[0-9a-zA-Z]|\d{14}[0-9a-zA-Z])可以用來判斷是否爲合法的15位或18位身份證號碼。

因爲15位和18位的身份證號碼都是從7位到第12位爲身份證爲日期類型。這樣我們可以設計出更精確的正則模式,使身份證號的日期合法,這樣我們的正則模式可以進一步將日期部分的正則修改爲[12][0-9]{3}[01][0-9][123][0-9],當然可以更精確的設置日期。

jdkjava.util.Regex包中有實現正則的類,PatternMatcher。以下是實現代碼:

 

import java.util.regex.Matcher;

import java.util.regex.Pattern;

 

public class RegexTest {

 

/**

 * @param args

 */

public static void main(String[] args) {

// 測試是否爲合法的身份證號碼

String[] strs = { "130681198712092019", "13068119871209201x",

"13068119871209201", "123456789012345", "12345678901234x",

"1234567890123" };

Pattern p1 = Pattern.compile("(\\d{17}[0-9a-zA-Z]|\\d{14}[0-9a-zA-Z])");

for (int i = 0; i < strs.length; i++) {

Matcher matcher = p1.matcher(strs[i]);

System.out.println(strs[i] + ":" + matcher.matches());

}

 

Pattern p2 = Pattern.compile("\\d{6}(\\d{8}).*"); // 用於提取出生日字符串

Pattern p3 = Pattern.compile("(\\d{4})(\\d{2})(\\d{2})");// 用於將生日字符串進行分解爲年月日

for (int i = 0; i < strs.length; i++) {

Matcher matcher = p2.matcher(strs[i]);

boolean b = matcher.find();

if (b) {

String s = matcher.group(1);

Matcher matcher2 = p3.matcher(s);

if (matcher2.find()) {

System.out

.println("生日爲" + matcher2.group(1) + ""

+ matcher2.group(2) + ""

+ matcher2.group(3) + "");

}

}

 

}

 

}

 

}

 

1、編寫一個程序,將a.txt文件中的單詞與b.txt文件中的單詞交替合併到c.txt文件中,a.txt文件中的單詞用回車符分隔,b.txt文件中用回車或空格進行分隔。

答:

package cn.itcast;

 

import java.io.File;

import java.io.FileReader;

import java.io.FileWriter;

 

public class MainClass{

public static void main(String[] args) throws Exception{

FileManager a = new FileManager("a.txt",new char[]{'\n'});

FileManager b = new FileManager("b.txt",new char[]{'\n',' '});

FileWriter c = new FileWriter("c.txt");

String aWord = null;

String bWord = null;

while((aWord = a.nextWord()) !=null ){

c.write(aWord + "\n");

bWord = b.nextWord();

if(bWord != null)

c.write(bWord + "\n");

}

while((bWord = b.nextWord()) != null){

c.write(bWord + "\n");

}

c.close();

}

}

 

 

class FileManager{

 

String[] words = null;

int pos = 0;

public FileManager(String filename,char[] seperators) throws Exception{

File f = new File(filename);

FileReader reader = new FileReader(f);

char[] buf = new char[(int)f.length()];

int len = reader.read(buf);

String results = new String(buf,0,len);

String regex = null;

if(seperators.length >1 ){

regex = "" + seperators[0] + "|" + seperators[1];

}else{

regex = "" + seperators[0];

}

words = results.split(regex);

}

public String nextWord(){

if(pos == words.length)

return null;

return words[pos++];

}

 

}

 

1、編寫一個程序,將d:\java目錄下的所有.java文件複製到d:\jad目錄下,並將原來文件的擴展名從.java改爲.jad

(大家正在做上面這道題,網上遲到的朋友也請做做這道題,找工作必須能編寫這些簡單問題的代碼!)

答:listFiles方法接受一個FileFilter對象,這個FileFilter對象就是過慮的策略對象,不同的人提供不同的FileFilter實現,即提供了不同的過濾策略。

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.FilenameFilter;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

 

public class Jad2Java {

 

public static void main(String[] args) throws Exception {

File srcDir = new File("java");

if(!(srcDir.exists() && srcDir.isDirectory()))

throw new Exception("目錄不存在");

File[] files = srcDir.listFiles(

new FilenameFilter(){

 

public boolean accept(File dir, String name) {

return name.endsWith(".java");

}

}

);

System.out.println(files.length);

File destDir = new File("jad");

if(!destDir.exists()) destDir.mkdir();

for(File f :files){

FileInputStream  fis = new FileInputStream(f);

String destFileName = f.getName().replaceAll("\\.java$", ".jad");

FileOutputStream fos = new FileOutputStream(new File(destDir,destFileName));

copy(fis,fos);

fis.close();

fos.close();

}

}

private static void copy(InputStream ips,OutputStream ops) throws Exception{

int len = 0;

byte[] buf = new byte[1024];

while((len = ips.read(buf)) != -1){

ops.write(buf,0,len);

}

 

}

}

 

由本題總結的思想及策略模式的解析:

1.

class jad2java{

1. 得到某個目錄下的所有的java文件集合

1.1 得到目錄 File srcDir = new File("d:\\java");

1.2 得到目錄下的所有java文件:File[] files = srcDir.listFiles(new MyFileFilter());

1.3 只想得到.java的文件: class MyFileFilter implememyts FileFilter{

public boolean accept(File pathname){

return pathname.getName().endsWith(".java")

}

}

2.將每個文件複製到另外一個目錄,並改擴展名

2.1 得到目標目錄,如果目標目錄不存在,則創建之

2.2 根據源文件名得到目標文件名,注意要用正則表達式,注意.的轉義。

2.3 根據表示目錄的File和目標文件名的字符串,得到表示目標文件的File

//要在硬盤中準確地創建出一個文件,需要知道文件名和文件的目錄。

2.4 將源文件的流拷貝成目標文件流,拷貝方法獨立成爲一個方法,方法的參數採用抽象流的形式。

//方法接受的參數類型儘量面向父類,越抽象越好,這樣適應面更寬廣。

}

 

分析listFiles方法內部的策略模式實現原理

File[] listFiles(FileFilter filter){

File[] files = listFiles();

//Arraylist acceptedFilesList = new ArrayList();

File[] acceptedFiles = new File[files.length];

int pos = 0;

for(File file: files){

boolean accepted = filter.accept(file);

if(accepted){

//acceptedFilesList.add(file);

acceptedFiles[pos++] = file;

}

}

Arrays.copyOf(acceptedFiles,pos);

//return (File[])accpetedFilesList.toArray();

}

1、編寫一個截取字符串的函數,輸入爲一個字符串和字節數,輸出爲按字節截取的字符串,但要保證漢字不被截取半個,如“我ABC”,4,應該截取“我AB”,輸入“我ABCDEF”,6,應該輸出“我ABC”,而不是“我ABC+漢的半個”。

答:

首先要了解中文字符有多種編碼及各種編碼的特徵。

    假設n爲要截取的字節數。

public static void main(String[] args) throws Exception{

String str = "a愛中華abc我愛傳智def';

String str = "ABC";

int num = trimGBK(str.getBytes("GBK"),5);

System.out.println(str.substring(0,num) );

}

public static int  trimGBK(byte[] buf,int n){

int num = 0;

boolean bChineseFirstHalf = false;

for(int i=0;i<n;i++)

{

if(buf[i]<0 && !bChineseFirstHalf){

bChineseFirstHalf = true;

}else{

num++;

bChineseFirstHalf = false;

}

}

return num;

}

1、有一個字符串,其中包含中文字符、英文字符和數字字符,請統計和打印出各個字符的個數。

答:哈哈,其實包含中文字符、英文字符、數字字符原來是出題者放的煙霧彈。

String content = “中國aadf111bbb菲的zz薩菲”;

HashMap map = new HashMap();

for(int i=0;i<content.length;i++)

{

char c = content.charAt(i);

Integer num = map.get(c);

if(num == null)

num = 1;

else

num = num + 1;

map.put(c,num);

}

for(Map.EntrySet entry : map)

{

system.out.println(entry.getkey() + “:” + entry.getValue());

}

估計是當初面試的那個學員表述不清楚,問題很可能是:

如果一串字符如"aaaabbc中國1512"要分別統計英文字符的數量,中文字符的數量,和數字字符的數量,假設字符中沒有中文字符、英文字符、數字字符之外的其他特殊字符。

int engishCount;

int chineseCount;

int digitCount;

for(int i=0;i<str.length;i++)

{

char ch = str.charAt(i);

if(ch>=’0’ && ch<=’9’)

{

digitCount++

}

else if((ch>=’a’ && ch<=’z’) || (ch>=’A’ && ch<=’Z’))

{

engishCount++;

}

else

{

chineseCount++;

}

}

System.out.println(……………);

 

1、從類似如下的文本文件中讀取出所有的姓名,並打印出重複的姓名和重複的次數,並按重複次數排序:

1,張三,28

2,李四,35

3,張三,28

4,王五,35

5,張三,28

6,李四,35

7,趙六,28

8,田七,35

 

程序代碼如下(答題要博得用人單位的喜歡,包名用該公司,面試前就提前查好該公司的網址,如果查不到,現場問也是可以的。還要加上實現思路的註釋):

package com.huawei.interview;

 

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.util.Comparator;

import java.util.HashMap;

import java.util.Iterator;

import java.util.Map;

import java.util.TreeSet;

 

 

public class GetNameTest {

 

/**

 * @param args

 */

public static void main(String[] args) {

// TODO Auto-generated method stub

//InputStream ips = GetNameTest.class.getResourceAsStream("/com/huawei/interview/info.txt");

//用上一行註釋的代碼和下一行的代碼都可以,因爲info.txtGetNameTest類在同一包下面,所以,可以用下面的相對路徑形式

Map results = new HashMap();

InputStream ips = GetNameTest.class.getResourceAsStream("info.txt");

BufferedReader in = new BufferedReader(new InputStreamReader(ips));

String line = null;

try {

while((line=in.readLine())!=null)

{

dealLine(line,results);

}

sortResults(results);

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

static class User

{

public  String name;

public Integer value;

public User(String name,Integer value)

{

this.name = name;

this.value = value;

}

 

@Override

public boolean equals(Object obj) {

// TODO Auto-generated method stub

//下面的代碼沒有執行,說明往treeset中增加數據時,不會使用到equals方法。

boolean result = super.equals(obj);

System.out.println(result);

return result;

}

}

private static void sortResults(Map results) {

// TODO Auto-generated method stub

TreeSet sortedResults = new TreeSet(

new Comparator(){

public int compare(Object o1, Object o2) {

// TODO Auto-generated method stub

User user1 = (User)o1;

User user2 = (User)o2;

/*如果compareTo返回結果0,則認爲兩個對象相等,新的對象不會增加到集合中去

 * 所以,不能直接用下面的代碼,否則,那些個數相同的其他姓名就打印不出來。

 * */

//return user1.value-user2.value;

//return user1.value<user2.value?-1:user1.value==user2.value?0:1;

if(user1.value<user2.value)

{

return -1;

}else if(user1.value>user2.value)

{

return 1;

}else

{

return user1.name.compareTo(user2.name);

}

}

}

);

Iterator iterator = results.keySet().iterator();

while(iterator.hasNext())

{

String name = (String)iterator.next();

Integer value = (Integer)results.get(name);

if(value > 1)

{

sortedResults.add(new User(name,value));

}

}

printResults(sortedResults);

}

private static void printResults(TreeSet sortedResults)

{

Iterator iterator  = sortedResults.iterator();

while(iterator.hasNext())

{

User user = (User)iterator.next();

System.out.println(user.name + ":" + user.value);

}

}

public static void dealLine(String line,Map map)

{

if(!"".equals(line.trim()))

{

String [] results = line.split(",");

if(results.length == 3)

{

String name = results[1];

Integer value = (Integer)map.get(name);

if(value == null) value = 0;

map.put(name,value + 1);

}

}

}

 

}

7、遞歸算法題1

一個整數,大於0,不用循環和本地變量,按照n,2n,4n,8n的順序遞增,當值大於5000時,把值按照指定順序輸出來。
例:n=1237
則輸出爲:
1237,
2474,
4948,
9896,
9896,
4948,
2474,
1237,

提示:寫程序時,先致謝按遞增方式的代碼,寫好遞增的以後,再增加考慮遞減部分。

public static void doubleNum(int n)

{

System.out.println(n);

if(n<=5000)

doubleNum(n*2);

System.out.println(n);

}

 

 

7、遞歸算法題2

1個人10,第2個比第1個人大2歲,依次遞推,請用遞歸方式計算出第8個人多大?

package cn.itcast;

 

import java.util.Date;

 

public class A1 {

 

public static void main(String [] args)

{

System.out.println(computeAge(8));

}

public static int computeAge(int n)

{

if(n==1) return 10;

return computeAge(n-1) + 2;

}

}

 

public static void toBinary(int n,StringBuffer result)

{

 

if(n/2 != 0)

toBinary(n/2,result);

result.append(n%2);

}

94、排序都有哪幾種方法?請列舉。用JAVA實現一個快速排序。

 本人只研究過冒泡排序、選擇排序和快速排序,下面是快速排序的代碼:

public class QuickSort {
/**
* 快速排序
* @param strDate
* @param left
* @param right
*/
public void quickSort(String[] strDate,int left,int right){
String middle,tempDate;
int i,j;
i=left;
j=right;
middle=strDate[(i+j)/2];
do{
while(strDate[i].compareTo(middle)<0&& i<right)
i++; //找出左邊比中間值大的數
while(strDate[j].compareTo(middle)>0&& j>left)
j--; //找出右邊比中間值小的數
if(i<=j){ //將左邊大的數和右邊小的數進行替換
tempDate=strDate[i];
strDate[i]=strDate[j];
strDate[j]=tempDate;
i++;
j--;
}
}while(i<=j); //當兩者交錯時停止

if(i<right){
quickSort(strDate,i,right);//
}
if(j>left){
quickSort(strDate,left,j);
}
}
/**
  * @param args
  */
public static void main(String[] args){
String[] strVoid=new String[]{"11","66","22","0","55","22","0","32"};
QuickSort sort=new QuickSort();
sort.quickSort(strVoid,0,strVoid.length-1);
for(int i=0;i<strVoid.length;i++){
System.out.println(strVoid[i]+" ");
}
}


}

7、有數組a[n],用java代碼將數組元素順序顛倒

//用下面的也可以

//for(int i=0,int j=a.length-1;i<j;i++,j--) 是否等效於 for(int i=0;i<a.length/2;i++)呢?

 

import java.util.Arrays;

 

public class SwapDemo{

 

public static void main(String[] args){

int [] a = new int[]{

(int)(Math.random() * 1000),

(int)(Math.random() * 1000),

(int)(Math.random() * 1000),

(int)(Math.random() * 1000),

(int)(Math.random() * 1000)

};

System.out.println(a);

System.out.println(Arrays.toString(a));

swap(a);

System.out.println(Arrays.toString(a));

}

public static void swap(int a[]){

int len = a.length;

for(int i=0;i<len/2;i++){

int tmp = a[i];

a[i] = a[len-1-i];

a[len-1-i] = tmp;

}

}

}

2.金額轉換,阿拉伯數字的金額轉換成中國傳統的形式如:(¥1011)->(一千零一拾一元整)輸出。

去零的代碼:

return sb.reverse().toString().replaceAll("零[拾佰仟]","零").replaceAll("零+萬","萬").replaceAll("零+元","元").replaceAll("零+","零");

 

public class RenMingBi {

 

/**

 * @param args add by zxx ,Nov 29, 2008

 */

private static final char[] data = new char[]{

'','','','','','','','','',''

};

private static final char[] units = new char[]{

'','','','','','','','',''

};

public static void main(String[] args) {

// TODO Auto-generated method stub

System.out.println(

convert(135689123));

}

 

public static String convert(int money)

{

StringBuffer sbf = new StringBuffer();

int unit = 0;

while(money!=0)

{

sbf.insert(0,units[unit++]);

int number = money%10;

sbf.insert(0, data[number]);

money /= 10;

}

 

return sbf.toString();

}

}

 

 

 

發佈了1 篇原創文章 · 獲贊 12 · 訪問量 6803
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章