Java程序員面試分類模擬10_第1頁
Java程序員面試分類模擬10_第2頁
Java程序員面試分類模擬10_第3頁
Java程序員面試分類模擬10_第4頁
Java程序員面試分類模擬10_第5頁
已閱讀5頁,還剩43頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

Java程序員面試分類模擬10論述題1.

break、continue以及return有什么區(qū)別正確答案:break、continue以及return的區(qū)別如下:

1)break用于直接強(qiáng)行(江南博哥)跳出當(dāng)前循環(huán),不再執(zhí)行剩余代碼。當(dāng)循環(huán)中遇到break語句時,忽略循環(huán)體中任何其他語句和循環(huán)條件測試,程序控制在循環(huán)體后面的語句重新開始。所以,當(dāng)多層循環(huán)嵌套,并且break語句出現(xiàn)在嵌套循環(huán)中的內(nèi)層循環(huán)時,它將僅僅只是終止了內(nèi)層循環(huán)的執(zhí)行,而不影響外層循環(huán)的執(zhí)行。

2)continue用于停止當(dāng)次循環(huán),回到循環(huán)起始處,進(jìn)入下一次循環(huán)操作。continue語句之后的語句將不再執(zhí)行,用于跳過循環(huán)體中的一部分語句,也就是不執(zhí)行這部分語句,而不是跳出整個循環(huán)執(zhí)行下一條語句,這就是continue與break的主要區(qū)別。簡單來說,continue只是中斷一次循環(huán)的執(zhí)行而已。

3)return語句是一個跳轉(zhuǎn)語句,用來表示從一個方法返回(返回一個值或其他復(fù)雜類型),可以使程序控制返回到調(diào)用該方法的地方。當(dāng)執(zhí)行main方法時,return語句可以使程序執(zhí)行返回到Java運(yùn)行系統(tǒng)。

break只能跳出當(dāng)前的循環(huán),那么如何才能跳出多重循環(huán)呢?可以在多重循環(huán)的外面定義一個標(biāo)識,然后在循環(huán)體里使用帶有標(biāo)識的break語句,這樣即可跳出多重循環(huán),示例如下:

publicclassBreak{

publicstaticvoidmain(String[]args){

out:

for(inti=0;i<5;i++){

for(intj=0;j<5;j++){

if(j>=2)

breakout:

System.out.println(j);

}

}

System.out.println("break");

}

程序運(yùn)行結(jié)果為:

0

1

break

上例中,當(dāng)內(nèi)部循環(huán)執(zhí)行到j(luò)等于2時,程序跳出雙重循環(huán),執(zhí)行System.out.println("break")語句。

引申:Java語言中是否存在goto關(guān)鍵字?

雖然關(guān)鍵字goto作為Java的保留字,但目前并沒有在Java中使用。在C/C++中,goto常被用于跳出多重循環(huán),而在。Java語言中,可以使用break和continue來達(dá)到同樣的效果。那么,既然goto沒有在Java語言中使用,為什么還要把它作為保留字呢?其中一個原因就是這個關(guān)鍵字有可能會在將來被使用。如果現(xiàn)在不把goto作為保留字,開發(fā)人員就有可能用goto作為變量名來使用。一旦有一天Java支持goto關(guān)鍵字了,這會導(dǎo)致以前的程序無法正常運(yùn)行,因此把goto作為保留字是非常有必要的。

這里需要注意的是,在Java語言中,雖然沒有g(shù)oto語句,但是卻能使用標(biāo)識符加冒號(:)的形式定義標(biāo)簽,如“mylabel:”,這主要是為了在多重循環(huán)中方便使用break和coutinue而設(shè)計(jì)的。

2.

final、finally和finalize有什么區(qū)別正確答案:final、finally和finalize的區(qū)別如下:

1)final用于聲明屬性、方法和類,分別表示屬性不可變、方法不可覆蓋和類不可被繼承(不能再派生出新的子類)。

final屬性:被final修飾的變量不可變。由于不可變有兩重含義:一是引用不可變;二是對象不可變。那么,final到底指的是哪種含義呢?下面通過一個例子來進(jìn)行說明。publicclassTest{publicstaticvoidmain(String[]arg){finalStringBuffers=newStringBuffer("Hello"。s.append("word");System.out.println(s);}}publicclassTest{publicstaticvoidmain(String[]arg){finalStringBuffers=newStringBuffer("Hello");s=newStringBuffer("Helloworld");}}運(yùn)行結(jié)果為:Helloworld運(yùn)行結(jié)果為:編譯期間錯誤

從以上的例子中可以看出,final指的是引用的不可變性,即它只能指向初始時指向的那個對象,而不關(guān)心指向?qū)ο髢?nèi)容的變化。所以,被final修飾的變量必須被初始化。一般可以通過以下幾種方式對其進(jìn)行初始化:①在定義的時候初始化。②final成員變量可以在初始化塊中初始化,但不可在靜態(tài)初始化塊中初始化。③靜態(tài)final成員變量可以在靜態(tài)初始化塊中初始化,但不可在初始化塊中初始化。④在類的構(gòu)造器中初始化,但靜態(tài)final成員變量不可以在構(gòu)造函數(shù)中初始化。

final方法:當(dāng)一個方法聲明為final時,該方法不允許任何子類重寫這個方法,但子類仍然可以使用這個方法。另外,還有一種被稱為inline(內(nèi)聯(lián))的機(jī)制,當(dāng)調(diào)用一個被聲明為final的方法時,直接將方法主體插入到調(diào)用處,而不是進(jìn)行方法調(diào)用(類似于C++中的inline),這樣做能提高程序的效率。

final參數(shù):用來表示這個參數(shù)在這個函數(shù)內(nèi)部不允許被修改。

final類:當(dāng)一個類被聲明為final時,此類不能被繼承,所有方法都不能被重寫。但這并不表示final類的成員變量也是不可改變的,要想做到final類的成員變量不可改變,必須給成員變量增加final修飾。值得注意的是,一個類不能既被聲明為abstract,又被聲明為final。

2)finally作為異常處理的一部分,它只能用在try/catch語句中,并且附帶一個語句塊,表示這段語句最終一定被執(zhí)行,經(jīng)常被用在需要釋放資源的情況下。

示例1:不使用finally的代碼如下所示:

Connectionconn;

Statementstmt;

try{

conn=DriverManager.getConnection(url1,userName,password);

stmt=conn.createStatement();

stmt.executeUpdate(update);//執(zhí)行一條update語句,此時出現(xiàn)異常

stmt.close();

conn.close();

}catch(Exceptione){

}

在上面的程序片段中,如果程序在運(yùn)行過程中沒有發(fā)生異常,那么數(shù)據(jù)庫的連接能夠得到釋放,程序運(yùn)行沒有問題。如果在執(zhí)行update語句時出現(xiàn)異常,后面的close()方法將不會被調(diào)用,數(shù)據(jù)庫的連接將得不到釋放。如果這樣的程序長期運(yùn)行,將會耗光數(shù)據(jù)庫的連接資源。通過使用finally可以保證任何情況下數(shù)據(jù)庫的連接資源都能夠被釋放。

示例2:使用finally的代碼如下所示。

Connectionconn=null;

Statementstmt=null;

try{

conn=DriverManager.getConnection(url1,userName,password);

stmt=conn.createStatement();

stmt.executeUpdate(update);//執(zhí)行一條update語句,此時出現(xiàn)異常

stmt.close();

conn.close();

}catch(Exceptione)finally{

if(stmt!=NULL)

stmt.close();

if(conn!=NULL)

conn.close();

}

在示例2中,不管程序運(yùn)行是否會出現(xiàn)異常,finally中的代碼一定會執(zhí)行,這樣能夠保證在任何情況下數(shù)據(jù)庫的連接資源都能被釋放。

3)finalize是Object類的一個方法,在垃圾回收器執(zhí)行時會調(diào)用被回收對象的finalize()方法,可以覆蓋此方法來實(shí)現(xiàn)對其他資源的回收,例如關(guān)閉文件等。需要注意的是,一旦垃圾回收器準(zhǔn)備好釋放對象占用的空間,將首先調(diào)用其finalize()方法,并且在下一次垃圾回收動作發(fā)生時,才會真正回收對象占用的內(nèi)存。

常見筆試題:

JDK中哪些類是不能繼承的?

答案:從上面的介紹可以知道,不能繼承的類是那些用final關(guān)鍵字修飾的類。一般比較基本的類型為防止擴(kuò)展類無意間破壞原來方法的實(shí)現(xiàn)的類型都應(yīng)該是final的,在JDK中,String、StringBuffer等都是基本類型,所以,String、StringBuffer等類是不能繼承的。

3.

assert有什么作用正確答案:斷言(assert)作為一種軟件調(diào)試的方法,提供了一種在代碼中進(jìn)行正確性檢查的機(jī)制,目前很多開發(fā)語言都支持這種機(jī)制。它的主要作用是對一個boolean表達(dá)式進(jìn)行檢查,一個正確運(yùn)行的程序必須保證這個boolean表達(dá)式的值為true,若boolean表達(dá)式的值為false,則說明程序已經(jīng)處于一種不正確的狀態(tài)下,系統(tǒng)需要提供告警信息并且退出程序。在實(shí)際的開發(fā)中,assert主要用來保證程序的正確性,通常在程序開發(fā)和測試時使用。為了提高程序運(yùn)行的效率,在軟件發(fā)布后,assert檢查默認(rèn)是被關(guān)閉的。

assert包括兩種表達(dá)式,分別為assertexpression1與assertexpression1:expression2,其中,expression1表示一個boolean表達(dá)式,expression2表示一個基本類型或者是一個對象,基本類型包括boolean、char、double、float、int和long。以下是對這兩個表達(dá)式的應(yīng)用。

publicclassTest{

publicstaticvoidmain(String[]args){

assert1+1==2;

System.out.println("assert1ok");

assert1+1==3:"assertfaild,exit";

System.out.println("assert2ok");

}

}

對于上述代碼,當(dāng)執(zhí)行指令javacTest.Java與javaTest時,程序的輸出結(jié)果為:

assert1ok

assert2ok

對于上述代碼,當(dāng)執(zhí)行指令javacTest.Java和java-eaTest時(注意:Java-eaTest的意思是打開-ea開關(guān)),程序的輸出結(jié)果為:

assert1ok

Exceptioninthread"main"Java.lang.AssertionError:assertfaild,exit

atTest.main(Test.Java:5)

assert的應(yīng)用范圍很多,主要包括①檢查控制流;②檢查輸入?yún)?shù)是否有效;③檢查函數(shù)結(jié)果是否有效;④檢查程序不變量。雖然assert的功能與if判斷類似,但二者存在著本質(zhì)的區(qū)別:assert一般在調(diào)試程序時使用,但如果不小心用assert來控制了程序的業(yè)務(wù)流程,那在調(diào)試結(jié)束后去掉assert就意味著修改了程序的正常邏輯,這樣的做法是非常危險(xiǎn)的;而if判斷是邏輯判斷,本身就是用以控制程序流程的。

需要注意的是,在Java語言中,assert與C語言中的assert盡管功能類似,但也不完全一樣,具體表現(xiàn)為兩個方面的不同:①Java語言中是使用assert關(guān)鍵字去實(shí)現(xiàn)其功能,而C語言中使用的是庫函數(shù);②C語言中的assert是在編譯時開啟,而Java語言中則是在運(yùn)行時開啟。

4.

static關(guān)鍵字有哪作用正確答案:static關(guān)鍵字主要有兩種作用:第一,為某特定數(shù)據(jù)類型或?qū)ο蠓峙鋯我坏拇鎯臻g,而與創(chuàng)建對象的個數(shù)無關(guān)。第二,實(shí)現(xiàn)某個方法或?qū)傩耘c類而不是對象關(guān)聯(lián)在一起,也就是說,在不創(chuàng)建對象的情況下就可以通過類來直接調(diào)用方法或使用類的屬性。具體而言,在Java語言中,static主要有4種使用情況:成員變量、成員方法、代碼塊和內(nèi)部類。

(1)static成員變量

雖然Java語言中沒有全局的概念,但可以通過static關(guān)鍵字來達(dá)到全局的效果。Java類提供了兩種類型的變量:用static關(guān)鍵字修飾的靜態(tài)變量和不用static關(guān)鍵字修飾的實(shí)例變量。靜態(tài)變量屬于類,在內(nèi)存中只有一個復(fù)制(所有實(shí)例都指向同一個內(nèi)存地址),只要靜態(tài)變量所在的類被加載,這個靜態(tài)變量就會被分配空間,因此就可以被使用了。對靜態(tài)變量的引用有兩種方式,分別為“類.靜態(tài)變量”和“對象.靜態(tài)變量”。

實(shí)例變量屬于對象,只有對象被創(chuàng)建后,實(shí)例變量才會被分配空間,才能被使用,它在內(nèi)存中存在多個復(fù)制。只能用“對象.實(shí)例變量”的方式來引用。以下是靜態(tài)變量與實(shí)例變量的使用示例。

publicclassTestAttribute{

publicstaticintstaticInt=0;

publicintnonStaticInt=0;

publicstaticvoidmain(String[]args){

TestAttributet=newTestAttribute();

system.out.println("t.staticInt="+t.staticInt);

system.out.println("TestAttribute.staticInt="+TestAttribute.staticInt);

system.out.println("t.nonStaticIn!="+t.nonStaticInt);

System.out.println("對靜態(tài)變量和實(shí)例變量分別+1");

t.staticInt++;

t.nonStaticInt++;

TestAttributet1=newTestAttribute();

System.out.println("t1.staticInt="+t1.staticInt);

System.out.println("TestAttribute.staticInt="+TestAttribute.staticInt);

System.out.println("t1.nonStaticInt="+t1.nonStaticInt);

}

}

程序運(yùn)行結(jié)果為:

t.staticInt=0

TestAttribute.staticInt=0

t.nonStaticInt=0

對靜態(tài)變量和實(shí)例變量分別+1

t1.staticInt=1

TestAttribute.staticInt=1

t1.nonStaticInt=0

從上例可以看出,靜態(tài)變量只有一個,被類擁有,所有對象都共享這個靜態(tài)變量,而實(shí)例對象是與具體對象相關(guān)的。需要注意的是,與C++語言不同的是,在Java語言中,不能在方法體中定義static變量。

(2)static成員方法

與變量類似,Java類同時也提供了static方法與非static方法。static方法是類的方法,不需要創(chuàng)建對象就可以被調(diào)用,而非static方法是對象的方法,只有對象被創(chuàng)建出來后才可以被使用。

static方法中不能使用this和super關(guān)鍵字,不能調(diào)用非static方法,只能訪問所屬類的靜態(tài)成員變量和成員方法,因?yàn)楫?dāng)static方法被調(diào)用時,這個類的對象可能還沒被創(chuàng)建,即使已經(jīng)被創(chuàng)建了,也無法確定調(diào)用哪個對象的方法。同理,static方法也不能訪問非static類型的變量。

static一個很重要的用途是實(shí)現(xiàn)單例模式。單例模式的特點(diǎn)是該類只能有一個實(shí)例,為了實(shí)現(xiàn)這一功能,必須隱藏類的構(gòu)造函數(shù),即把構(gòu)造函數(shù)聲明為private,并提供一個創(chuàng)建對象的方法,由于構(gòu)造對象被聲明為private,外界無法直接創(chuàng)建這個類型的對象,只能通過該類提供的方法來獲取類的對象,要達(dá)到這樣的目的只能把創(chuàng)建對象的方法聲明為static,程序示例如下:

classSingleton{

privatestaticSingletoninstance=null;

privateSingleton(){}

publicstaticSingletongetInstance(){

if(instance==null){

instance=newSingleton();

}

returninstance;

}

}

用public修飾的static變量和方法本質(zhì)上都是全局的,若在static變量前用private修飾,則表示這個變量可以在類的靜態(tài)代碼塊或者類的其他靜態(tài)成員方法中使用,但是不能在其他類中通過類名來直接引用。

(3)static代碼塊

static代碼塊(靜態(tài)代碼塊)在類中是獨(dú)立于成員變量和成員函數(shù)的代碼塊的。它不在任何一個方法體內(nèi),JVM在加載類時會執(zhí)行static代碼塊,如果有多個static代碼塊,JVM將會按順序來執(zhí)行。static代碼塊經(jīng)常被用來初始化靜態(tài)變量。需要注意的是,這些static代碼塊只會被執(zhí)行一次,示例如下:

publicclassTest{

privatestaticinta;

static{

Test.a=4;

System.out.println(a);

System.out.println("staticblockiscalled");

publicstaticvoidmain(String[]args){

}

程序運(yùn)行結(jié)果為:

4

staticblockiscalled

(4)static內(nèi)部類

static內(nèi)部類是指被聲明為static的內(nèi)部類,它可以不依賴于外部類實(shí)例對象而被實(shí)例化,而通常的內(nèi)部類需要在外部類實(shí)例化后才能實(shí)例化。靜態(tài)內(nèi)部類不能與外部類有相同的名字,不能訪問外部類的普通成員變量,只能訪問外部類中的靜態(tài)成員和靜態(tài)方法(包括私有類型),示例如下:

publicClassOuter{

staticintn=5;

staticClassInner{

voidaccessAttrFromOuter(){

System.out.println("Inner:Outer.n="+n);

}

}

publicstaticvoidmain(String[]args){

Outer.Innernest=newOuter.Inner();

nest.accessAttrFromOuter();

}

}

程序運(yùn)行結(jié)果為:

Inner:Outer.n=5

需要注意的是,只有內(nèi)部類才能被定義為static。

引申:

1.什么是實(shí)例變量?什么是局部變量?什么是類變量?什么是final變量?

實(shí)例變量:變量歸對象所有(只有在實(shí)例化對象后才可以)。每當(dāng)實(shí)例化一個對象時,會創(chuàng)建一個副本并初始化,如果沒有顯示初始化,那么會初始化一個默認(rèn)值。各個對象中的實(shí)例變量互不影響。

局部變量:在方法中定義的變量,在使用前必須初始化。

類變量:用static可修飾的屬性、變量歸類所有,只要類被加載,這個變量就可以被使用(類名.變量名)。所有實(shí)例化的對象共享類變量。

final變量:表示這個變量為常量,不能被修改。

2.static與final結(jié)合使用表示什么意思?

在Java語言中,static關(guān)鍵字常與final關(guān)鍵字結(jié)合使用,用來修飾成員變量與成員方法,有點(diǎn)類似于C/C++語言中的“全局常量”。對于變量,若使用staticfinal修飾,則表示一旦賦值,就不可修改,并且通過類名可以訪問。對于方法,若使用staticfinal修飾,則表示該方法不可覆蓋,并且可以通過類名直接訪問。

常見筆試題:

publicclassTest{

publicstaticinttestStatic(){

staticfinalinti=0;

system.out.println(i++);

publicstaticvoidmain(Stringargs[]){

Testtest=newTest();

test.testStatic();

}

上述程序的運(yùn)行結(jié)果是什么?______

A.0

B.1

C.2

D.編譯失敗

答案:D。在Java語言中,不能在成員函數(shù)內(nèi)部定義static變量。

5.

使用switch時有哪注意事項(xiàng)正確答案:switch語句用于多分支選擇,在使用switch(expr)時,expr只能是一個枚舉常量(內(nèi)部也是由整型或字符類型實(shí)現(xiàn))或一個整數(shù)表達(dá)式,其中整數(shù)表達(dá)式可以是基本類型int或其對應(yīng)的包裝類Integer,當(dāng)然也包括不同的長度整型,例如short。由于byte、short和char類型的值都能夠被隱式地轉(zhuǎn)換為int類型,因此這些類型以及它們對應(yīng)的包裝類型都可以作為switch的表達(dá)式。但是,long、float、double、String類型不能夠隱式地轉(zhuǎn)換為int類型,因此它們不能被用作switch的表達(dá)式。如果一定要使用long、float,或double作為switch的參數(shù),必須將其強(qiáng)制轉(zhuǎn)換為int型才可以,例如,以下對switch中參數(shù)的使用就是非法的。

floata=0.123;

switch(a)//錯誤!a不是整型或字符類型變量。

{

...

}

另外,與switch對應(yīng)的是case語句,case語句之后可以是直接的常量數(shù)值,例如1、2,也可以是一個常量計(jì)算式,例如1+2等,還可以是final型的變量(final變量必須是編譯時的常量),例如finalinta=0,但不能是變量或帶有變量的表達(dá)式,例如i*2等。當(dāng)然更不能是浮點(diǎn)型數(shù),例如1.1或者1.2/2等。

switch(formWay)

{

case2-1://正確

...

casea-2://錯誤

...

case2.0://錯誤

...

}

隨著Java語言的發(fā)展,在Java7中,switch開始支持String類型了。以下是一段支持String類型的示例代碼:

publicclassTest{

publicvoidtest(Stringstr){

switch(str){

case"hehao":

System.out.println("hehao");

break;

case"xuepeng";

System.out.println("xuepeng");

break;

case"yexiangyang":

System.out.println("yexiangyang");

break;

default:

System.out.println("default");

}

}

}

從本質(zhì)上來講,switch對字符串的支持,其實(shí)是int類型值的匹配。它的實(shí)現(xiàn)原理如下:通過對case后面的String對象調(diào)用hashCode()方法,得到一個int類型的hash值,然后用這個hash值來唯一標(biāo)識這個case。那么當(dāng)匹配時,首先調(diào)用這個字符串hashCode()函數(shù),獲取一個hash值(int類型),用這個hash值來匹配所有case,如果沒有匹配成功,說明不存在;如果匹配成功了,接著會調(diào)用字符串的String.equals()方法進(jìn)行匹配(至于為什么需要調(diào)用equals()方法)。由此可以看出,String變量不能為null,同時,switch的case子句中使用的字符串也不能為null。

在使用switch時,需要注意另外一個問題:一般必須在case語句結(jié)尾添加break語句。因?yàn)橐坏┩ㄟ^switch語句確定了入口點(diǎn),就會順序執(zhí)行后面的代碼,直到遇到關(guān)鍵字break。否則,會執(zhí)行滿足這個case之后的其他case的語句而不管case是否匹配,直到switch結(jié)束或者遇到break為止。如果在switch中省略了break語句,那么匹配的case值后的所有情況(包括default情況)都會被執(zhí)行,示例如下:

publicclassTest{

publicstaticvoidmain(String[]args){

intx=4;

switch(x)

case1:System.out.println(x);

case2:System.out.println(x);

case3:System.out.println(x);

case4:System.out.println(x);

case5:System.out.println(x);

(default:System.out.println(x);

}

}

}

程序運(yùn)行結(jié)果為:

4

4

4

6.

volatile有什么作用正確答案:在用Java語言編寫的程序中,有時為了提高程序的運(yùn)行效率,編譯器會自動對其進(jìn)行優(yōu)化,把經(jīng)常被訪問的變量緩存起來,程序在讀取這個變量時有可能會直接從緩存(例如寄存器)中來讀取這個值,而不會去內(nèi)存中讀取。這樣做的一個好處是提高了程序的運(yùn)行效率,但當(dāng)遇到多線程編程時,變量的值可能因?yàn)閯e的線程而改變了,而該緩存的值不會相應(yīng)改變,從而造成應(yīng)用程序讀取的值和實(shí)際的變量值不一致,例如,在本次線程內(nèi),當(dāng)讀取一個變量時,為提高存取速度,會先把變量讀取到一個緩存中,當(dāng)以后再取變量值時,就直接從緩存中取值,當(dāng)變量值在本線程里改變時,會同時把變量的新值復(fù)制到該緩存中,以便保持一致。

volatile是一個類型修飾符(typespecifier),它是被設(shè)計(jì)用來修飾被不同線程訪問和修改的變量。被volatile類型定義的變量,系統(tǒng)每次用到它時都是直接從對應(yīng)的內(nèi)存當(dāng)中提取,而不會利用緩存。在使用了volatile修飾成員變量后,所有線程在任何時候所看到變量的值都是相同的。下面給出一個使用volatile的示例。

publicclassMyThreadimplementsRunnable{

privatevolatileBooleanflag;

publicvoidstop(){

flag=false;

}

publicvoidrun(){

while(flag)

;//dosomething

}

}

以上代碼示例是用來停止線程最常用的一種方法,如果boolean類型的變量flag沒有被聲明為volatile,那么,當(dāng)這個線程的run方法在判斷flag值時,使用的有可能是緩存中的值,此時就不能及時地獲取其他線程對flag所做的操作,因此會導(dǎo)致線程不能及時地停止。

需要注意的是,由于volatile不能保證操作的原子性,因此,一般情況下volatile不能代替sychronized。此外,使用volatile會阻止編譯器對代碼的優(yōu)化,因此會降低程序的執(zhí)行效率。所以,除非迫不得已,否則,能不使用volatile就盡量不要使用volatile。

7.

instanceof有什么作用正確答案:instanceof是Java語言中的一個二元運(yùn)算符,它的作用是判斷一個引用類型的變量所指向的對象是否是一個類(或接口、抽象類、父類)的實(shí)例,即它左邊的對象是否是它右邊的類的實(shí)例該運(yùn)算符返回boolean類型的數(shù)據(jù)。

常見的用法為:result=objectinstanceofclass。如果object是class的一個實(shí)例,那么instanceof運(yùn)算符返回true;如果object不是Class的一個實(shí)例,或者object是null,那么instanceof運(yùn)算符返回false。

以如下程序?yàn)槔?/p>

publicclassTest{

publicstaticvoidmain(Stringargs[]){

StringS="Hello";

int[]a={1,2};

if(sinstanceofString)

System.out.println("true");

if(sinstanceofObject)

System.out.println("true");

if(ainstanceofint[])

System.out.println("true");

}

}

程序運(yùn)行結(jié)果為:

true

true

true

8.

strictfp有什么作用正確答案:關(guān)鍵字strictfp是strictfloatpoint的縮寫,指的是精確浮點(diǎn),它用來確保浮點(diǎn)數(shù)運(yùn)算的準(zhǔn)確性。JVM在執(zhí)行浮點(diǎn)數(shù)運(yùn)算時,如果沒有指定strictfp關(guān)鍵字,此時計(jì)算結(jié)果可能會不精確,而且計(jì)算結(jié)果在不同平臺或廠商的虛擬機(jī)上會有不同的結(jié)果,導(dǎo)致意想不到的錯誤。而一旦使用了strictfp來聲明一個類、接口或者方法,那么在所聲明的范圍內(nèi),Java編譯器以及運(yùn)行環(huán)境會完全依照IEEE二進(jìn)制浮點(diǎn)數(shù)算術(shù)標(biāo)準(zhǔn)(IEEE754)來執(zhí)行,在這個關(guān)鍵字聲明的范圍內(nèi)所有浮點(diǎn)數(shù)的計(jì)算都是精確的。需要注意的是,當(dāng)一個類被strictfp修飾時,所有方法都會自動被strictfp修飾。因此,strictfp可以保證浮點(diǎn)數(shù)運(yùn)算的精確性,而且在不同的硬件平臺上會有一致的運(yùn)行結(jié)果。下例給出了strictfp修飾類的使用方法:

publicstrictfpclassTest{

publicstaticvoidtestStrictfp(){

floatf=0.12365f;

doubled=0.03496421d;

doublesum=f+d;

System.out.println(sum);

}

publicstaticvoidmain(String[]args)}

testStrictfp();

}

}

程序運(yùn)行結(jié)果為:

0.15861420949932098

9.

Java提了哪基本數(shù)據(jù)類型正確答案:Java語言一共提供了8種原始的數(shù)據(jù)類型(byte,short,int,long,float,double,char,boolean),這些數(shù)據(jù)類型不是對象,而是Java語言中不同于類的特殊類型,這些基本類型的數(shù)據(jù)變量在聲明之后就會立刻在棧上被分配內(nèi)存空間。除了這8種基本的數(shù)據(jù)類型外,其他類型都是引用類型(例如類、接口、數(shù)組等),引用類型類似于C++中的引用或指針的概念,它以特殊的方式指向?qū)ο髮?shí)體,這類變量在聲明時不會被分配內(nèi)存空間,只是存儲了一個內(nèi)存地址而已。

下表為Java中的基本數(shù)據(jù)類型及其描述。不同數(shù)據(jù)類型對比數(shù)據(jù)類型字節(jié)長度范圍默認(rèn)值包裝類int4[-2147483648,2147483647](-231~231-1)0Integershort2[-32768,32767]0Shortlong8[-9223372036854775808,9223372036854775807](-263~263-1)0L或0lLongbyte1[-128,127]0Bytefloat432位IEEE754單精度范圍0.0F或0.0fFloatdouble864位IEEE754雙精度范圍0.0Doublechar2Unicode[0,65535]u0000Characterboolean1true和falsefalseBoolean

以上這些基本類型可以分為如下4種類型:

1)int長度數(shù)據(jù)類型:byte(8bit)、short(16bit)、int(32bit)、long(64bit)。

2)float長度數(shù)據(jù)類型:單精度(32bitfloat)、雙精度(64bitdouble)。

3)boolean類型變量的取值:true、false。對于boolean占用空間的大小,從理論上講,只需要1bit就夠了,但在設(shè)計(jì)的時候?yàn)榱丝紤]字節(jié)對齊等因素,一般會考慮使其占用一個字節(jié)。由于Java規(guī)范沒有明確的規(guī)定,因此,不同的JVM可能會有不同的實(shí)現(xiàn)。

4)char數(shù)據(jù)類型:unicode字符(16bit)。

此外,Java語言還提供了對這些原始數(shù)據(jù)類型的封裝類(字符類型Character,布爾類型Boolean,數(shù)值類型Byte、Short、Integer、Long、Float、Double)。需要注意的是,Java中的數(shù)值類型都是有符號的,不存在無符號的數(shù),它們的取值范圍也是固定的,不會隨著硬件環(huán)境或者操作系統(tǒng)的改變而改變。除了以上提到的8種基本數(shù)據(jù)類型以外,在Java語言中,還存在另外一種基本類型void,它也有對應(yīng)的封裝類java.lang.void,只是無法直接對它進(jìn)行操作而已。封裝類型和原始類型有許多不同點(diǎn):首先,原始數(shù)據(jù)類型在傳遞參數(shù)時都是按值傳遞,而封裝類型是按引用傳遞的。其次,當(dāng)封裝類型和原始類型用作某個類的實(shí)例數(shù)據(jù)時,它們所指定的默認(rèn)值不同。對象引用實(shí)例變量的默認(rèn)值為null,而原始類型實(shí)例變量的默認(rèn)值與它們的類型有關(guān)(例如int默認(rèn)初始化為0),示例如下:

publicclassTest{

Strings;

inti;

floatf;

publicstaticvoidmain(Stringargs[]){

Testt=newTest();

System.out.println(t.s==null);

System.out.println(t.i);

System.out.println(t.f);

}

}

程序運(yùn)行結(jié)果為:

true

0

0.0

除了以上需要注意的內(nèi)容外,在Java語言中,默認(rèn)聲明的小數(shù)是double類型的,因此在對float類型的變量進(jìn)行初始化時需要進(jìn)行類型轉(zhuǎn)換。float類型的變量有兩種初始化方法:floatf=1.0f或floatf=(float)1.0。與此類似的是,在Java語言中,直接寫的整型數(shù)字是int類型的,如果在給數(shù)據(jù)類型為long的變量直接賦值時,int類型的值無法表示一個非常大的數(shù)字,因此,在賦值時可以通過如下的方法來賦值:longl=26012402244L。

引申:

1.在Java語言中null值是什么?在內(nèi)存中null是什么?

null不是一個合法的Object實(shí)例,所以編譯器并沒有為其分配內(nèi)存,它僅僅用于表明該引用目前沒有指向任何對象。其實(shí),與C語言類似,null是將引用變量的值全部置0。

2.如何理解賦值語句Stringx=null?

在Java語言中,變量被分為兩大類型:原始值(primitive)與引用值(reference)。聲明為原始類型的變量,其存儲的是實(shí)際的值。聲明為引用類型的變量,存儲的是實(shí)際對象的地址(指針,引用)。對于賦值語句Stringx=null,它定義了一個變量“x”,x中存放的是String引用,此處為null。

常見筆試題:

1.下列表達(dá)式中,正確的是______。

A.byteb=128;

B.booleanflag=null;

C.floatf=0.9239;

D.longa=2147483648L;

答案:D。A中byte能表示的取值范圍為[-128,127],因此不能表示128。B中boolean的取值只能是true或false,不能為null。C中0.9239為double類型,需要進(jìn)行數(shù)據(jù)類型轉(zhuǎn)換。

2.String是最基本的數(shù)據(jù)類型嗎?

答案:不是?;緮?shù)據(jù)類型包括byte、int、char、long、float、double:、boolean和short。

3.int和Integer有什么區(qū)別?

答案:Java語言提供兩種不同的類型,即引用類型和原始類型(或內(nèi)置類型)。int是Java語言的原始數(shù)據(jù)類型,Integer是Java語言為int提供的封裝類。Java為每個原始類型提供了封裝類。

引用類型與原始類型的行為完全不同,并且它們具有不同的語義。而且,引用類型與原始類型具有不同的特征和用法。

4.賦值語句floatf=3.4是否正確?

答案:不正確。數(shù)據(jù)3.4默認(rèn)情況下是double類型,即雙精度浮點(diǎn)數(shù),將double類型數(shù)值賦值給float類型的變量,會造成精度損失,因此需要對其進(jìn)行強(qiáng)制類型轉(zhuǎn)換,即將3.4轉(zhuǎn)換成float類型或者將3.4強(qiáng)制寫成float類型。所以,floatf=(float)3.4或者floatf=3.4F寫法都是可以的。

10.

什么是不可變類正確答案:不可變類(immutableclass)是指當(dāng)創(chuàng)建了這個類的實(shí)例后,就不允許修改它的值了,也就是說,一個對象一旦被創(chuàng)建出來,在其整個生命周期中,它的成員變量就不能被修改了。它有點(diǎn)類似于常量(const),即只允許別的程序讀,不允許別的程序進(jìn)行修改。

在Java類庫中,所有基本類型的包裝類都是不可變類,例如Integer、Float等。此外,String也是不可變類??赡苡腥藭幸蓡?,既然String是不可變類,為什么還可以寫出如下代碼來修改String類型的值呢?

publicclassTest{

publicstaticvoidmain(String[]args){

Strings="Hello";

s+="world";

system.out.println(s);

}

}

程序運(yùn)行結(jié)果為:

Helloworld

表面上看,好像是修改String類型對象s的值。其實(shí)不是,Strings=“Hello”語句聲明了一個可以指向String類型對象的引用,這個引用的名字為s,它指向了一個字符串常量“Hello”。s+="world"并沒有改變s所指向的對象(由于“Hello”是String類型的對象,而String又是不可變量),這句代碼運(yùn)行后,s指向了另外一個String類型的對象,該對象的內(nèi)容為“Helloworld”。原來的那個字符串常量“Hello”還存在于內(nèi)存中,并沒有被改變。

在介紹完不可變類的基本概念后,下面主要介紹如何創(chuàng)建一個不可變類。通常來講,要創(chuàng)建一個不可變類需要遵循下面4條基本原則:

1)類中所有成員變量被private所修飾。

2)類中沒有寫或者修改成員變量的方法,例如setxxx,只提供構(gòu)造函數(shù),一次生成,永不改變。

3)確保類中所有方法不會被子類覆蓋,可以通過把類定義為final或者把類中的方法定義為final來達(dá)到這個目的。

4)如果一個類成員不是不可變量,那么在成員初始化或者使用get方法獲取該成員變量時,需要通過clone方法來確保類的不可變性。

5)如果有必要,可使用覆蓋Object類的equals()方法和hashCode()方法。在equals()方法中,根據(jù)對象的屬性值來比較兩個對象是否相等,并且保證用equals()方法判斷為相等的兩個對象的hashCode()方法的返回值也相等,這可以保證這些對象能被正確地放到HashMap或HashSet集合中。

除此之外,還有一些小的注意事項(xiàng):由于類的不可變性,在創(chuàng)建對象時就需要初始化所有成員變量,因此最好提供一個帶參數(shù)的構(gòu)造函數(shù)來初始化這些成員變量。

下面通過給出一個錯誤的實(shí)現(xiàn)方法與一個正確的實(shí)現(xiàn)方法來說明在實(shí)現(xiàn)這種類時需要特別注意的問題。首先給出一個錯誤的實(shí)現(xiàn)方法:

importjava.util.Date;

classImmutableClass{

privateDated;

publicImmutableClass(Dated){

this.d=d;

}

publicvoidprintState(){

System.out.println(d);

}

}

publicclassTestImmutable{

publicstaticvoidmain(String[]args){

Dated=newDate();

ImmutableClassimmuC=newImmutableClass(d);

immuC.printState();

d.setMonth(5);

immuC.printState();

}

程序運(yùn)行結(jié)果為:

SunAug0417:41:47CST2013

TueJun0417:41:47CST2013

需要說明的是,由于Date對象的狀態(tài)是可以被改變的,而ImmutableClass保存了Date類型對象的引用,當(dāng)被引用的對象的狀態(tài)改變時會導(dǎo)致ImmutableClass對象狀態(tài)的改變。

其實(shí),正確的實(shí)現(xiàn)方法如下所示:

importjava.util.ArrayList;

import.java.util.Date;

classImmutableClass{

privateDated;

publicImmutableClass(Dated){

this.d=(Date)d.clone();//解除了引用關(guān)系

}

publicvoidprintState(){

System.out.println(d);

}

publicDategetDate(){

return(Date)d.clone();

}

}

publicclassTest{

publicstaticvoidmain(String[]args){

Dated=newDate();

ImmutableClassimmuC=newImmutableClass(d);

immuC.printState();

d.setMonth(5);

immuC.printState();

}

}

程序運(yùn)行結(jié)果為:

SunAug0417:47:03CST2013

SunAug0417:47:03CST2013

Java語言中之所以設(shè)計(jì)有很多不可變類,主要是不可變類具有使用簡單、線程安全、節(jié)省內(nèi)存等優(yōu)點(diǎn),但凡事有利就有弊,不可變類自然也有其缺點(diǎn),例如,不可變類的對象會因?yàn)橹档牟煌a(chǎn)生新的對象,從而導(dǎo)致無法預(yù)料的問題,所以,切不可濫用這種模式。

11.

值傳遞與引用傳遞有哪區(qū)別正確答案:方法調(diào)用是編程語言中非常重要的一個特性,在方法調(diào)用時,通常需要傳遞一些參數(shù)來完成特定的功能。Java語言提供了兩種參數(shù)傳遞的方式:值傳遞和引用傳遞。

(1)值傳遞

在方法調(diào)用中,實(shí)參會把它的值傳遞給形參,形參只是用實(shí)參的值初始化一個臨時的存儲單元,因此形參與實(shí)參雖然有著相同的值,但是卻有著不同的存儲單元,因此對形參的改變不會影響實(shí)參的值。

(2)引用傳遞

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

在Java語言中,原始數(shù)據(jù)類型在傳遞參數(shù)時都是按值傳遞,而包裝類型在傳遞參數(shù)時是按引用傳遞的。

下面通過一個例子來介紹按值傳遞和按引用傳遞的區(qū)別:

publicclassTest{

publicstaticvoidtestPassParameter(StringBuffterss1,intn){

ss1.append("World");//引用

n=8;//值

}

publicstaticvoidmain(String[]args){

inti=1;

StringBuffers1=newStringBuffer("Hello");

testPassParameter(s1,i);

System.out.println(s1);

System.out.println(i);

}

}

程序運(yùn)行結(jié)果為:

HelloWorld

1

按引用傳遞其實(shí)與傳遞指針類似,是把對象的地址作為參數(shù)的,如下圖所示。

為了便于理解,假設(shè)1和“Hello”存儲的地址分別為0X12345678和0XFFFFFF12。在調(diào)用方法testPassParameter時,由于i為基本類型,因此參數(shù)是按值傳遞的,此時會創(chuàng)建一個i的副本,該副本與i有相同的值,把這個副本作為參數(shù)賦值給n,作為傳遞的參數(shù)。而StringBuffer由于是一個類,因此按引用傳遞,傳遞的是它的引用(傳遞的是存儲“Hello的地址”),如圖所示,在testPassParameter內(nèi)部修改的是n的值,這個值與i是沒關(guān)系的。但是在修改ss1時,修改的是ss1這個地址指向的字符串,由于形參ss1與實(shí)參s1指向的是同一塊存儲空間,因此修改ss1后,s1指向的字符串也被修改了。

Java中處理8種基本的數(shù)據(jù)類型用的是值傳遞,其他所有類型都用的是引用傳遞,由于這8種基本數(shù)據(jù)類型的包裝類型都是不可變量,因此增加了對“按引用傳遞”的理解難度。下面給出一個示例來說明:

publicclassTest{

publicstaticvoidchangeStringBuffer(StringBufferss1,StringBufferss2){

ss1.append("World");

ss2=ss1;

}

publicstaticvoidmain(String[]args){

Integera=1;

Integerb=a;

b++;

System.out.println(a);

System.out.println(b);

StringBuffers1=newStringBuffer("Hello");

StringBuffers2=newStringBuffer("Hello");

changeStfingBuffer(s1,s2);

System.out.println(s1);

System.out.println(s2);

}

程序運(yùn)行結(jié)果為:

1

2

HelloWorld

Hello

對于上述程序的前兩個輸出“1”和“2”,不少讀者可能會認(rèn)為,Integer是按值傳遞的而不是按引用傳遞的,其實(shí)這是一個理解上的誤區(qū),上述代碼還是按引用傳遞的,只是由于Integer是不可變類,因此沒有提供改變它值的方法,在上例中,在執(zhí)行完語句b++后,由于Integer是不可變類,因此此時會創(chuàng)建一個新值為2的Integer賦值給b,此時b與a其實(shí)已經(jīng)沒有任何關(guān)系了。

下面通過程序的后兩個輸出來加深對“按引用傳遞”的理解。為了理解后兩個輸出結(jié)果,首先必須理解“引用也是按值傳遞的”這一要點(diǎn)。為了便于理解,假設(shè)s1和s2指向字符串的地址分別為0X12345678和0XFFFFFF12,那么在調(diào)用函數(shù)changeStringBuffer時,傳遞s1與s2的引用就可以理解為傳遞了兩個地址0X12345678和0XFFFFFF12,而且這兩個地址是按值傳遞的(即傳遞了兩個值,ss1為0X12345678,ss2為0XFFFFFF12),在調(diào)用方法ss1.append("World")時,會修改ss1所指向的字符串的值,因此會修改調(diào)用者的s1的值,得到的輸出結(jié)果為“HelloWorld”。但是在執(zhí)行ss2=ss1時,只會修改ss2的值而對s2毫無影響,因此s2的值在調(diào)用前后保持不變。為了便于理解,下圖給出了函數(shù)調(diào)用的處理過程。

從圖中可以看出,在傳遞參數(shù)時相當(dāng)于傳遞了兩個地址,在調(diào)用ss1.append("World")時,修改了這個地址所指向字符串的值,而在調(diào)用ss2=ss1時,相當(dāng)于修改了函數(shù)changeStringBuffer內(nèi)部的局部變量ss2,這個修改與ss1沒關(guān)系。

常見筆試題:

下列說法中,正確的是______。

A.callbyvalue不會改變實(shí)際參數(shù)的值

B.callbyreference能改變實(shí)際參數(shù)

C.callbyreference不能改變實(shí)際參數(shù)的地址

D.callbyreference能改變實(shí)際參數(shù)的內(nèi)容

答案:A、C、D。見上面講解。

12.

不同數(shù)據(jù)類型的轉(zhuǎn)換有哪規(guī)則正確答案:在Java語言中,當(dāng)參與運(yùn)算的兩個變量的數(shù)據(jù)類型不同時,就需要進(jìn)行隱式的數(shù)據(jù)類型轉(zhuǎn)換,轉(zhuǎn)換的規(guī)則為:從低精度向高精度轉(zhuǎn)換,即優(yōu)先級滿足byte<short<char<int<long<float<double,例如,不同數(shù)據(jù)類型的值在進(jìn)行運(yùn)算時,short類型數(shù)據(jù)能夠自動轉(zhuǎn)為int類型,int類型數(shù)據(jù)能夠自動轉(zhuǎn)換為float類型等。反之,則需要通過強(qiáng)制類型轉(zhuǎn)換來實(shí)現(xiàn)。

在Java語言中,類型轉(zhuǎn)換可以分為以下幾種類型:

(1)類型自動轉(zhuǎn)換

低級數(shù)據(jù)類型可以自動轉(zhuǎn)換為高級數(shù)據(jù)類型,下表給出了常見的自動類型轉(zhuǎn)換的規(guī)則。自動類型轉(zhuǎn)換的規(guī)則操作數(shù)1的類型操作數(shù)2的類型轉(zhuǎn)換后的類型longbyteshortcharintlongintbyteshortcharintfloatbyteshortintcharlongfloatdoublebyteshortintlongcharfloatdouble當(dāng)類型自動轉(zhuǎn)換時,需要注意以下幾點(diǎn):1)char類型的數(shù)據(jù)轉(zhuǎn)換為高級類型(如int,long等),會轉(zhuǎn)換為其對應(yīng)的ASCII碼。2)byte、char、short類型的數(shù)據(jù)在參與運(yùn)算時會自動轉(zhuǎn)換為int型,但當(dāng)使用“+=”運(yùn)算時,就不會產(chǎn)生類型的轉(zhuǎn)換(將在下一節(jié)中詳細(xì)介紹)。3)另外,在Java語言中,基本數(shù)據(jù)類型與boolean類型是不能相互轉(zhuǎn)換的??傊?dāng)有多種類型的數(shù)據(jù)混合運(yùn)算時,系統(tǒng)會先自動地將所有數(shù)據(jù)轉(zhuǎn)換成容量最大的那一種數(shù)據(jù)類型,然后再進(jìn)行計(jì)算。(2)強(qiáng)制類型轉(zhuǎn)換當(dāng)需要從高級數(shù)據(jù)類型轉(zhuǎn)換為低級數(shù)據(jù)類型時,就需要進(jìn)行強(qiáng)制類型轉(zhuǎn)換,下表給出了強(qiáng)制類型轉(zhuǎn)換的規(guī)則。強(qiáng)制類型轉(zhuǎn)換的規(guī)則原操作數(shù)的類型轉(zhuǎn)換后操作數(shù)的類型bytecharcharbytecharshortbytecharintbyteshortcharlongbyteshortcharintfloatbyteshortcharintlongdoublebyteshortcharintlongdouble

需要注意的是,在進(jìn)行強(qiáng)制類型轉(zhuǎn)換時可能會損失精度。

常見筆試題:

1.下面程序的運(yùn)行結(jié)果是什么?

inti=1;

if(i)

System.out.println("true");

else

System.out.println("false");

答案:編譯錯誤。因?yàn)閕f條件只接受boolean類型的值(true或false),而i的類型為int,int類型不能被隱式地轉(zhuǎn)換為boolean類型。

2.對于下述代碼結(jié)果強(qiáng)制類型轉(zhuǎn)換后,變量a和b的值分別為______。

shorta=128;

byteb=(byte)a

答案:a=128,b=-128。short類型變量占兩個字節(jié),a對應(yīng)的二進(jìn)制為:0000000010000000,由于byte只占一個字節(jié),在強(qiáng)制轉(zhuǎn)換為byte的時候只截取低字節(jié):10000000,10000000是-128的補(bǔ)碼,因此b的值為-128。

13.

強(qiáng)制類型轉(zhuǎn)換的注意事項(xiàng)有哪正確答案:Java語言在涉及byte、short和char類型的運(yùn)算時,首先會把這些類型的變量值強(qiáng)制轉(zhuǎn)換為int類型,然后對int類型的值進(jìn)行計(jì)算,最后得到的值也是int類型。因此,如果把兩個short類型的值相加,最后得到的結(jié)果是int類型;如果把兩個byte類型的值相加,最后也會得到一個int類型的值。如果需要得到short類型的結(jié)果,就必須顯式地把運(yùn)算結(jié)果轉(zhuǎn)換為short類型,例如對于語句shorts1=1;s1=s1+1,由于在運(yùn)行時會首先將s1轉(zhuǎn)換成int類型,因此s1+1的結(jié)果為int類型,這樣編譯器會報(bào)錯,所以,正確的寫法應(yīng)該shorts1=1;s1=(short)(s1+1)。

有一種例外情況?!?=”為Java語言規(guī)定的運(yùn)算法,Java編譯器會對其進(jìn)行特殊處理,因此,語句shorts1=1;s1+=1能夠編譯通過。

14.

運(yùn)算符優(yōu)先級是什么正確答案:Java語言中有很多運(yùn)算符,由于運(yùn)算符優(yōu)先級的問題經(jīng)常會導(dǎo)致程序出現(xiàn)意想不到的結(jié)果,下表詳細(xì)介紹了運(yùn)算符的優(yōu)先級。運(yùn)算符的優(yōu)先級優(yōu)先級運(yùn)算符結(jié)合性1.()[]從左向右2+(正)-(負(fù))++--~!3*/%4+(加)-(減)5<<>>(無符號右移)>>>(有符號右移)6<<=>>=instanceof7==!=8&9|10^11&&12||13?:14=

+=-=*=/=%=&==|=^=~=<<=>>=>>>=

在實(shí)際使用時,如果不確定運(yùn)算符的優(yōu)先級,最好運(yùn)用括號運(yùn)算符來控制運(yùn)算順序。

常見筆試題:

下面程序的運(yùn)行結(jié)果是什么?

publicclassTest{

publicstaticvoidmain(String[]args){

bytea=5;

intb=10;

intc=a>>2+b>>2;

System.out.println(c);

}

}

答案:0。由于“+”的優(yōu)先級比“>>”高,因此程序中的表達(dá)式等價于a>>(2+b)>>2,相當(dāng)于a>>12>>2,因此運(yùn)行結(jié)果為0。

15.

Math類中round、ceil和floor方法的功能各是什么正確答案:round、ceil和floor方法位于Math類中,Math是一個包含了很多數(shù)學(xué)常量與計(jì)算方法的類,位于java.lang包下,能自動導(dǎo)入,而且Math類里邊的方法全是靜態(tài)方法。下面重點(diǎn)介紹這3個方法代表的含義。

1)round方法表示四舍五入。round,意為“環(huán)繞”,其實(shí)現(xiàn)原理是在原來數(shù)字的基礎(chǔ)上先增加0.5然后再向下取整,等同于(int)Math.floor(x+0.5f)。它的返回值類型為int型,例如,Math.round(11.5)的結(jié)果為12,Math.round(-11.5)的結(jié)果為-11。

2)ceil方法的功能是向上取整。ceil,意為“天花板”,顧名思義是對操作數(shù)取頂,Math.ceil(a),就是取大于a的最小的整數(shù)值。需要注意的是,它的返回值類型并不是int型,而是double型。若a是正數(shù),則把小數(shù)“入”,若a是負(fù)數(shù),則把小數(shù)“舍”。

3)floor方法的功能是向下取整。floor,意為“地板”,顧名思義是對操作數(shù)取底。Math.floor(a),就是取小于a的最大的整數(shù)值。它的返回值類型與ceil方法一樣,也是double型。若a是正數(shù),則把小數(shù)“舍”;若a是負(fù)數(shù),則把小數(shù)“入”。

下表是一個實(shí)例分析。floor、round與ceil的區(qū)別數(shù)字Math.floor方法Math.round方法Math.ceil方法1.41.012.01.51.022.01.61.022.0-1.4-2.0-1-1.0-1.5-2.0-1-1.0-1.6-2.0-2-1.0

以下是一段測試代碼:

classMathTest{

publicstaticvoidmain(String[]args){

floatm=6.4f;

floatn=-6.4f;

System.out.println("Math.round("+m+")="+Math.round(m));

System.out.println("Math.round("+n+")="+Math.round(n));

System.out.println("Math.ceil("+m+")="+Math.ceil(m));

System.out.println("Math.ceil("+n+")="+Math.ceil(n));

System.out.println("Math.floor("+m+")="+Math.floor(m));

System.out.println("Math.floor("+n+")="+Math.floor(n));

}

}

上例的運(yùn)行結(jié)果為:

Math.round(6.4)=6

Math.round(-6.4)=-6

Math.ceil(6.4)=7.0

Math.ceil(-6.4)=-6.0

Math.floor(6.4)=6.0

Math.floor(-6.4)=-7.0

常見筆試題:

Math.round(11.5)等于多少?Math.round(-11.5)等于多少?

答案:12,-11。見上面講解。

16.

++i與i++有什么區(qū)別正確答案:在編程時,經(jīng)常會用到變量的自增或自減操作,尤其在循環(huán)中用得最多。以自增為例,有兩種自增方式:前置與后置,即++i和i++,它們的不同點(diǎn)在于i++是在程序執(zhí)行完畢后進(jìn)行自增,而++i是在程序開始執(zhí)行前進(jìn)行自增,示例如下:

publicclassTest{

publicstaticvoidmain(String[]a){

inti=1;

System.out.println(i+++i++);

System.out.println("i="+i);

System.out.println(i+++++i);

System.out.println("i="+i);

System.out.println(i+++i+++i++);

System.out.println("i="+i);

}

}

程序運(yùn)行結(jié)果為:

3

i=3

8

i=5

18

i=8

上例中的程序運(yùn)行結(jié)果讓很多讀者感到困惑不解,其實(shí)稍作分析,問題便迎刃而解了。表達(dá)式i+++i++首先執(zhí)行第一個i++操作,由于自增操作會稍后執(zhí)行,因此,運(yùn)算時i的值還是1,但自增操作后,i的值變?yōu)榱?,接著執(zhí)行第二個i++,運(yùn)算時,i的值已經(jīng)為2了,而執(zhí)行了一個自增操作后,i的值變?yōu)榱?,所以i+++i++=1+2=3,而運(yùn)算完成后,i的值變?yōu)?。

表達(dá)式i+++++i首先執(zhí)行第一個i++,但是自增操作會稍后執(zhí)行。因此,此時i的值還是3,接著執(zhí)行++i,此時i的值變?yōu)?,同時還要補(bǔ)執(zhí)行i++的自增操作,因此此時i的值變?yōu)?,所以i+++++i=3+5=8。

同理,i+++i+++i++=5+6+7=18。

常見筆試題:

假設(shè)x=1,y=2,z=3,則表達(dá)式y(tǒng)+=z--/++x的值是______。

A.3

B.3.5

C.4

D.5

答案:A。見上面講解。

17.

如何實(shí)現(xiàn)無符號數(shù)的右移操作正確答案:Java提供了兩種右移運(yùn)算符:“>>”和“>>>”。其中,“>>”被稱為有符號右移運(yùn)算符,“>>>”被稱為無符號右移運(yùn)算符,它們的功能是將參與運(yùn)算的對象對應(yīng)的二進(jìn)制數(shù)右移指定的位數(shù)。二者的不同點(diǎn)在于“>>”在執(zhí)行右移操作時,若參與運(yùn)算的數(shù)字為正數(shù),則在高位補(bǔ)0;若為負(fù)數(shù),則在高位補(bǔ)1。而“>>>”則不同,無論參與運(yùn)算的數(shù)字為正數(shù)或?yàn)樨?fù)數(shù),在執(zhí)行運(yùn)算時,都會在高位補(bǔ)0。

此外,需要特別注意的是,在對char、byte、short等類型的數(shù)進(jìn)行移位操作前,編譯器都會自動地將數(shù)值轉(zhuǎn)化為int類型,然后才進(jìn)行移位操作。由于int型變量只占4Byte(32bit),因此當(dāng)右移的位數(shù)超過32bit時,移位運(yùn)算沒有任何意義。所以,在Java語言中,為了保證移動位數(shù)的有效性,以使右移的位數(shù)不超過32bit,采用了取余的操作,即a>>n等價于a>>(n%32),示例如下:

publicclassTest{

publicstaticvoidmain(String[]a){

inti=-4;

System.out.println("-----int>>:"+i);

System.out.println("移位前二進(jìn)制:"+Integer.toBinaryString(i));

i>>=1;

System.out.println("移位后二進(jìn)制:"+Integer.toBinaryString(i));

System.out.println("-----int>>:"+i);

i=-4;

System.out.println("------int>>>”+i);

System.out.println("移位前二進(jìn)制:"+Integer.toBinaryString(i));

i>>>=1;

System.out.println("移位后二進(jìn)制:"+Integer.toBinaryString(i));

System.out.println("-----int>>>:"+i);

shortj=-4;

System.out.println("-----short>>>:"+J);

System.out.println(”移位前二進(jìn)制:"+Integer.toBinaryString(j));

j>>>=1;

System.out.println("移位后二進(jìn)制:"+Integer.toBinaryString(j));

System.out.println("-----short>>>:"+j);

i=5;

System.out.println("-----int>>:"+i);

System.out.println("位前二進(jìn)制:"+Integer.toBinaryString(i));

i>>=32;

System.out.println("移位后二進(jìn)制:"+Integer.toBinaryString(i));

System.out.println("------int>>:“+i);

}

}

程序運(yùn)行結(jié)果為:

-----int>>:-4

移位前二進(jìn)制:11111111111111111111111111111100

移位后二進(jìn)制:11111111111111111111111111111110

-----int>>:-2

-----int>>>:-4

移位前二進(jìn)制:11111111111111111111111111111100

移位后二進(jìn)制:1111111111111111111111111111110

-----int>>>:2147483646

-----short>>>:-4

移位前二進(jìn)制:11111111111111111111111111111100

移位后二進(jìn)制:11111111111111111111111111111110

-----short>>>:-2

-----int>>:5

移位前二進(jìn)制:101

移位后二進(jìn)制:101

-----int>>:5

需要特別說明的是,對于short類型來說,由于short只占2Byte,在移位操作時會先轉(zhuǎn)換為int類型,雖然在進(jìn)行無符號右移時會在高位補(bǔ)1,但當(dāng)把運(yùn)算結(jié)果再賦值給short類型變量時,只會取其中低位的兩個字節(jié),因此,高位無論補(bǔ)0還是補(bǔ)1對運(yùn)算結(jié)果無影響。在上例中,-4的二進(jìn)制

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論