- Java程序員面試秘笈
- 陳浩編著
- 1353字
- 2019-01-02 07:03:51
第2章 Java語(yǔ)言基礎(chǔ)
在用人單位的面試中,Java語(yǔ)言基礎(chǔ)知識(shí)是考察的重點(diǎn)之一,也是一個(gè)合格Java程序員必須掌握的知識(shí)。一個(gè)對(duì)于Java語(yǔ)言基礎(chǔ)知識(shí)一知半解的程序員,會(huì)在實(shí)際的項(xiàng)目開(kāi)發(fā)工作中犯一些低級(jí)錯(cuò)誤,對(duì)項(xiàng)目開(kāi)發(fā)的質(zhì)量和團(tuán)隊(duì)的開(kāi)發(fā)進(jìn)度都有很大的影響。代碼的質(zhì)量,直接影響了軟件工程的質(zhì)量。
Java語(yǔ)言基礎(chǔ)主要涉及以下幾個(gè)方面。
? Java的基本語(yǔ)言元素。
? 原始數(shù)據(jù)類型。
? 變量聲明。
? 變量的初始化。
? Java源文件的結(jié)構(gòu)。
? main()方法。
面試題1 掌握J(rèn)ava標(biāo)識(shí)符
請(qǐng)標(biāo)記出下面代碼中的錯(cuò)誤。
public class JavaSign { public int 48abc=20; private int Num=100; private int m-48abc; private int m_abc=30; private int number=60; private String $hk; private double ¥money; public String我的變量="我是一個(gè)兵!"; private String my@email="helloworld"; public static void main(String[] args) { System.out.println(num); System.out.println(my@email); System.out.println(48abc+m_abc); System.out.println(number); } }
考點(diǎn):這是一個(gè)比較有代表性的面試題,考察求職者Java語(yǔ)言基礎(chǔ)的基本功,重點(diǎn)考察求職者對(duì)Java標(biāo)識(shí)符的掌握。
出現(xiàn)頻率:★★★★★
【面試題解析】標(biāo)識(shí)符是一個(gè)語(yǔ)言的基本元素,在Java開(kāi)發(fā)語(yǔ)言中,標(biāo)識(shí)符可以用來(lái)表示類、方法、變量和標(biāo)簽。標(biāo)識(shí)符是由一系列的字符組成,每個(gè)字符可以是字母、數(shù)字、連接符號(hào)(例如_)或者任意的貨幣符(如$、¥等)。
求職者必須要注意的是,Java標(biāo)識(shí)符的第1個(gè)字母不能為數(shù)字,Java語(yǔ)言是區(qū)分字母大小寫的,Num和num是兩個(gè)毫不相干的標(biāo)識(shí)。
注意:Java使用的是Unicode編碼。Unicode中每個(gè)字符都對(duì)應(yīng)了一個(gè)唯一的數(shù)字,而不論是什么平臺(tái)、使用什么語(yǔ)言、編寫什么程序。Unicode標(biāo)準(zhǔn)已經(jīng)被當(dāng)今工業(yè)界的領(lǐng)導(dǎo)們所采用,例如Apple、HP、IBM、JustSystem、Microsoft、Oracle、SAP、Sun、Sybase、Unisys和其他許多公司。最新的標(biāo)準(zhǔn)例如XML、Java、ECMAScript(JavaScript)、LDAP、CORBA 2.0、WML等,以及許多操作系統(tǒng)、所有最新的瀏覽器和許多其他產(chǎn)品都支持。Unicode標(biāo)準(zhǔn)的出現(xiàn)和支持它的工具存在,是近來(lái)全球軟件技術(shù)最重要的發(fā)展趨勢(shì)。
基本上,計(jì)算機(jī)只是處理數(shù)字,輸入或輸出的字母或其他字符都被編碼為一個(gè)數(shù)字。在創(chuàng)造Unicode之前,有數(shù)百種指定這些數(shù)字的編碼系統(tǒng),沒(méi)有一個(gè)編碼可以包含足夠的字符。例如,歐州共同體就需要好幾種不同的編碼系統(tǒng)來(lái)包括所有的語(yǔ)言。即使是單一種語(yǔ)言,例如英語(yǔ),也沒(méi)有哪一個(gè)編碼可以適用于所有的字母、標(biāo)點(diǎn)符號(hào)和常用的技術(shù)符號(hào)。不同編碼系統(tǒng)也會(huì)互相沖突。也就是說(shuō),兩種編碼可能使用相同的數(shù)字代表兩個(gè)不同的字符,或使用不同的數(shù)字代表相同的字符。因此任何一臺(tái)特定的計(jì)算機(jī)(特別是服務(wù)器)都需要支持許多不同的編碼,而且不論什么時(shí)候數(shù)據(jù)通過(guò)不同的編碼或平臺(tái)之間,數(shù)據(jù)總會(huì)存在損壞的風(fēng)險(xiǎn)。
例如,在簡(jiǎn)體中文(GB)、繁體中文(BIG5)、日文中,“趙”都是同一個(gè)字,但是編碼方式不同。BIG5的趙對(duì)應(yīng)0xBBAF,而0xBBAF在GB里面就被顯示為“化”,這就是我們常見(jiàn)的亂碼的原因之一。Unicode采用統(tǒng)一的編碼,“趙”只對(duì)應(yīng)一個(gè)數(shù)字,不必管它來(lái)自哪種語(yǔ)系。
下面舉例來(lái)說(shuō)明如何區(qū)分正確和錯(cuò)誤的標(biāo)識(shí)符。
正確的Java標(biāo)識(shí)符示例:
Abc123、abc、¥m、$kill、my_code、gач
非法的Java標(biāo)識(shí)符:
46m、my@email、 int-1
面試題中,求職者容易忽略一點(diǎn),中文變量和中文字符是合法的。
參考答案:
public class JavaSign { // 錯(cuò)誤:Java的標(biāo)識(shí)符不能以數(shù)字開(kāi)頭 public int 48abc=20; private int Num=100; // 錯(cuò)誤:Java的標(biāo)識(shí)符不能包含-,只能在表達(dá)式中使用 private int m-48abc; private int m_abc=30; private String $hk; private double ¥money; public String我的變量="我是一個(gè)兵!"; private int number=60; // 錯(cuò)誤:不能在變量中使用@,為不合法標(biāo)識(shí)符 private String my@email="helloworld"; public static void main(String[] args) { // 錯(cuò)誤:沒(méi)有定義num變量,因?yàn)镴ava是區(qū)分大小寫的 System.out.println(num); // my@email定義錯(cuò)誤 System.out.println(my@email); // 48abc定義錯(cuò)誤 System.out.println(48abc+m_abc); // 錯(cuò)誤:不能在靜態(tài)方法中引用一個(gè)非靜態(tài)變量 System.out.println(number); } }
面試題2 掌握J(rèn)ava關(guān)鍵字
編譯、運(yùn)行如下代碼,請(qǐng)選擇正確的一項(xiàng)描述。
public class JavaKey { private int java=100;//(1) public String True="my Java";//(2) public static void main(String[] args) { int ingeter=20;(3) JavaKey key=new JavaKey(); //(4) System.out.println(key.java);//(5) } }
(a)編譯成功,打印100。
(b)編譯不通過(guò),提示(1)處有錯(cuò)誤。
(c)編譯不通過(guò),提示(2)處有錯(cuò)誤。
(d)編譯不通過(guò),提示(3)處有錯(cuò)誤。
(e)編譯不通過(guò),提示(4)、(5)處有錯(cuò)誤。
考點(diǎn):主要考察求職者對(duì)于Java關(guān)鍵字的掌握,一般都會(huì)在面試題中出現(xiàn)開(kāi)發(fā)中容易出現(xiàn)的混淆關(guān)鍵字。
出現(xiàn)頻率:★★★★
【面試題解析】Java語(yǔ)言中的關(guān)鍵字是開(kāi)發(fā)語(yǔ)言中預(yù)定義的保留標(biāo)識(shí)符,不能在程序代碼中表示類、變量、方法等成員。Java的關(guān)鍵字有如下特征。
? Java的關(guān)鍵字都是小寫的。
? then和sizeof都不是Java的關(guān)鍵字。熟悉C或者C++,寫慣了ASP的程序員一定要注意。
? 大寫的NULL不是java語(yǔ)言的關(guān)鍵字。String是Java語(yǔ)言的一個(gè)封裝類的類名,也不是關(guān)鍵字。
下面給出Java語(yǔ)言的關(guān)鍵字,如表2.1所示。
表2.1 Java語(yǔ)言的關(guān)鍵字

Java語(yǔ)言中的保留字:null、true和false。
Java語(yǔ)言中保留但是未使用的關(guān)鍵字:const和goto。
參考答案:(a)。
面試題3 找出Java關(guān)鍵字
Which of the following are keyWords or reserved words in Java?(下面哪些是Java語(yǔ)言的關(guān)鍵字或者是保留字?)
(a)if
(b)then
(c)goto
(d)while
(e)case
(f)sizeof
考點(diǎn):主要考察求職者對(duì)于Java關(guān)鍵字的掌握。
出現(xiàn)頻率:★★★★
【面試題解析】請(qǐng)參考Java關(guān)鍵字表。
參考答案:(a)(c)(d)(e)。
面試題4 挑選Java關(guān)鍵字
Which of these are key words in java?(下面哪些是Java關(guān)鍵字?)
(a)default
(b)NULL
(c)String
(d)throws
(e)long
(f)true
考點(diǎn):主要考察求職者對(duì)于Java關(guān)鍵字的掌握。
出現(xiàn)頻率:★★★★
【面試題解析】請(qǐng)參考Java關(guān)鍵字表。
參考答案:(a)、(d)、(e)、(f)。
面試題5 選擇完整合法的Java注釋
下面是否為一條完整而且合法的Java注釋?
/*//*/
(a)不是,塊狀注釋(/*…*/)尚未閉合,因?yàn)檫@里單行注釋(//…)注釋掉了塊狀注釋的閉合部分。
(b)這是一個(gè)完全有效的注釋。編譯器會(huì)忽略//部分。
(c)是一個(gè)非法注釋,編譯器會(huì)報(bào)錯(cuò)。
考點(diǎn):考察求職者對(duì)Java注釋的熟悉程度。在軟件項(xiàng)目開(kāi)發(fā)中,規(guī)范而且完整的注釋可以提高代碼的可讀性和可維護(hù)性。
出現(xiàn)頻率:★★★★
【面試題解析】Java語(yǔ)言提供了3種用于程序的注釋。
? 單行注釋://…到行尾。
? 多行注釋:/*…*/。
? 歸檔(Javadoc)注釋:/**…*/。
多行注釋可以跨越多行,以/*開(kāi)頭,*/結(jié)尾,例如:
/* a mothed Test Hello */
注意:如果多行注釋內(nèi)容出現(xiàn)注釋起始符號(hào),例如//、/*、//*等,編譯器視為普通字符,并不做任何處理。但是多行注釋不能嵌套,如下注釋會(huì)引發(fā)錯(cuò)誤:
/* hello Test /* a sub */ */
注釋在軟件開(kāi)發(fā)中的使用。
1.文件頭注釋
文件頭注釋以 /*開(kāi)始,以*/結(jié)束,需要注明該文件的創(chuàng)建時(shí)間、文件名、命名空間信息。
例如:
/* * Created on 2005-7-2 * File Test.java * Package com.cn * Create Date:2008-08-01 * /
2.類、接口注釋
類、接口的注釋采用 /** … */,描述部分用來(lái)書寫該類的作用或者相關(guān)信息,塊標(biāo)記部分必須注明作者和版本。注釋代碼示例如下:
/**Title: XXXX DRIVER 2.0 *Description: XXXX DRIVER 2.0 *Copyright: Copyright (c) 2003 *Company:XXXX有限公司 * * @author Java Development Group * @version 2.0 */
如下示例也很常見(jiàn):
/** * A class representing a window on the screen. * For example: * * Window win = new Window(parent); * win.show(); * * * @author Sami Shaio * @version %I%, %G% * @see java.awt.BaseWindow * @see java.awt.Button */ class Window extends BaseWindow { ... }
3.構(gòu)造函數(shù)注釋
構(gòu)造函數(shù)注釋采用 /** … */,描述部分注明構(gòu)造函數(shù)的作用,不一定有塊標(biāo)記部分。
無(wú)塊標(biāo)記的示例如下:
/** * 默認(rèn)構(gòu)造函數(shù) */
帶塊標(biāo)記的示例如下:
/** * 帶參數(shù)構(gòu)造函數(shù),初始化模式名、變量名稱和數(shù)據(jù)源類型 * @param schema * Ref模式名 * @param name * Ref變量名稱 * @param type * byVal數(shù)據(jù)源類型 */
4.域注釋
域注釋可以出現(xiàn)在注釋文檔里面,也可以不出現(xiàn)在注釋文檔里面。用/** … */的域注釋將會(huì)被認(rèn)為是注釋文檔而出現(xiàn)在最終生成的HTML報(bào)告里面(Javadoc),而使用/* … */的注釋則會(huì)被忽略。例如:
/** * @作者 閆術(shù)卓 * @創(chuàng)建時(shí)間Sep 1, 2008 2:10:30 PM */
上面的域注釋會(huì)生成下面的HTML報(bào)告:
@作者 閆術(shù)卓 @創(chuàng)建時(shí)間 Sep 1, 2008 2:10:30 PM
5.方法注釋
方法注釋采用 /** … */,描述部分注明方法的功能,塊標(biāo)記部分注明方法的參數(shù),返回值、異常等信息。例如:
/** * 設(shè)置是否有外碼約束 * * @param conn * Connection與數(shù)據(jù)庫(kù)的連接 */
注意:初級(jí)程序員容易忽略Java代碼的注釋,而往往只關(guān)注代碼的實(shí)現(xiàn)邏輯,高級(jí)程序員更加注重代碼的規(guī)范性和可讀性。
參考答案:(b)。
面試題6 int和Integer的區(qū)別是什么
考點(diǎn):考察求職者對(duì)引用類型和原始類型的區(qū)分和理解。
出現(xiàn)頻率:★★★★★
【面試題解析】Java提供引用類型和原始類型(或內(nèi)置類型)兩種不同的類型。另外,Java還為每個(gè)原始類型提供了封裝類(Wrapper)。
表2.2列出了原始類型以及對(duì)應(yīng)的對(duì)象封裝類。
表2.2 原始類型和對(duì)應(yīng)的封裝類

引用類型和原始類型的行為完全不同,并且分別具有不同的語(yǔ)義。假定一個(gè)方法中有兩個(gè)局部變量,一個(gè)變量為int原始類型,另一個(gè)變量是對(duì)一個(gè)Integer對(duì)象的對(duì)象引用,如下所示:
int i = 5; // 原始類型 Integer j = new Integer(10); // 對(duì)象引用
這兩個(gè)變量都存儲(chǔ)在局部變量表中,并且都是在Java操作數(shù)堆棧中被操作的。原始類型int和對(duì)象引用各占堆棧的32位(要表示一個(gè)int或一個(gè)對(duì)象引用,Java虛擬機(jī)實(shí)現(xiàn)至少需要使用32 位存儲(chǔ))。Integer對(duì)象對(duì)應(yīng)的堆棧項(xiàng)并不是對(duì)象本身,而是一個(gè)對(duì)象引用。對(duì)象引用是指向?qū)ο蟠鎯?chǔ)所在堆中的某個(gè)區(qū)域的指針。Java中的所有對(duì)象都要通過(guò)對(duì)象引用訪問(wèn)。而當(dāng)聲明一個(gè)原始類型時(shí),就為類型本身聲明了存儲(chǔ)。
引用類型和原始類型具有不同的特征和用法。以哪種類型的數(shù)據(jù)結(jié)構(gòu)存儲(chǔ),決定了以此類型作為某個(gè)類的實(shí)例數(shù)據(jù)時(shí)所指定的默認(rèn)值。對(duì)象引用實(shí)例變量的默認(rèn)值為null,而原始類型實(shí)例變量的默認(rèn)值與具體的類型有關(guān)。
許多程序的代碼將同時(shí)包含原始類型以及它們的對(duì)象封裝。程序員必須了解這兩種類型是如何工作和相互作用的,以避免代碼出錯(cuò)。
例如,不能對(duì)原始類型調(diào)用方法,但可以對(duì)對(duì)象調(diào)用方法。
int j = 5; j.hashCode(); // 錯(cuò)誤 //... Integer i = new Integer(5); i.hashCode(); // 正確
使用原始類型無(wú)須調(diào)用new,也無(wú)須創(chuàng)建對(duì)象,這節(jié)省了時(shí)間和空間。混合使用原始類型和對(duì)象,也可能導(dǎo)致與賦值有關(guān)的意外結(jié)果,看起來(lái)沒(méi)有錯(cuò)誤的代碼,可能無(wú)法完成預(yù)期工作。示例代碼如下:
import java.awt.Point; class Assign { public static void main(String args[]) { int a = 1; int b = 2; Point x = new Point(0,0); Point y = new Point(1,1); // 1 System.out.println("a is " + a); System.out.println("b is " + b); System.out.println("x is " + x); System.out.println("y is " + y); System.out.println("Performing assignment and " + "setLocation..."); a = b; a++; x = y; // 2 x.setLocation(5,5); // 3 System.out.println("a is "+a); System.out.println("b is "+b); System.out.println("x is "+x); System.out.println("y is "+y); } }
這段代碼生成以下輸出:
a is 1 b is 2 x is java.awt.Point[x=0,y=0] y is java.awt.Point[x=1,y=1] Performing assignment and setLocation... a is 3 b is 2 x is java.awt.Point[x=5,y=5] y is java.awt.Point[x=5,y=5]
修改整數(shù)a和b后結(jié)果沒(méi)意外。b的值被賦予整型變量a,a值增加了1。令人感到意外是在賦值并調(diào)用setLocation()函數(shù)之后,x和y對(duì)象的輸出結(jié)果。我們?cè)谕瓿蓌=y賦值之后,特意對(duì)x調(diào)用了setLocation,x和y的值怎么會(huì)相同呢?將y賦予x,然后更改了x,這與我們對(duì)整數(shù)a和b進(jìn)行的操作沒(méi)什么不同。
這種混淆是由原始類型和對(duì)象的使用造成的。賦值對(duì)這兩種類型所起的作用沒(méi)什么不同。賦值運(yùn)算符“=”左邊的值等于右邊的值,這一點(diǎn)對(duì)于原始類型(如前面的int類型值a和b)是顯而易見(jiàn)的。對(duì)于非原始類型(如Point對(duì)象),賦值修改的是對(duì)象引用,而不是對(duì)象本身。
換句話說(shuō),x和y是對(duì)象引用,因此,在語(yǔ)句“x=y;”之后,x和y引用同一個(gè)對(duì)象,對(duì)x執(zhí)行的所有方法與對(duì)y執(zhí)行的方法都作用于同一個(gè)對(duì)象。
面試題7 哪些不屬于Java的原始類型
請(qǐng)選擇兩個(gè)答案。
(a)"abc"
(b)'x'
(c)100.09F
(d)"hello"
(e)false
考點(diǎn):考察求職者對(duì)Java原始類型的掌握。
出現(xiàn)頻率:★★★★
【面試題解析】應(yīng)該記住Java語(yǔ)言的8個(gè)原始類型:boolean、char、byte、short、int、long、float和double。
參考答案:
(a)、(d)。其他都是原始類型,而(a)、(d)是字符串,即一個(gè)String對(duì)象類型。
面試題8 String和StringBuffer的區(qū)別
考點(diǎn):考察求職者對(duì)常用的字符串處理對(duì)象的掌握。
出現(xiàn)頻率:★★★★
參考答案:
Java提供了兩個(gè)字符串類:String和StringBuffer。它們可以儲(chǔ)存和操作字符串,即包含多個(gè)字符的字符串?dāng)?shù)據(jù)。字符串String類提供了數(shù)值不可改變的字符串,而StringBuffer類提供的字符串對(duì)象可以進(jìn)行修改。當(dāng)知道字符數(shù)據(jù)要改變的時(shí)候,就可以使用StringBuffer類創(chuàng)建,典型地,可以使用StringBuffers來(lái)動(dòng)態(tài)構(gòu)造字符數(shù)據(jù)。
面試題9 指出Java的原始數(shù)據(jù)類型并說(shuō)出其分類
考點(diǎn):考察求職者對(duì)Java原始數(shù)據(jù)類型的掌握。
出現(xiàn)頻率:★★★★
【面試題解析】Java的原始數(shù)據(jù)類型可以分為以下幾種。
1.基本的整數(shù)類型
整數(shù)是從負(fù)無(wú)窮到正無(wú)窮之間的任意整型的數(shù)據(jù),例如5、0、-128。因?yàn)橛?jì)算機(jī)資源有限,并且需要存儲(chǔ)器來(lái)存儲(chǔ)變量,所以必須要靈活地定義數(shù)量。Java中有4 種已定義的整數(shù)類型:byte、short、int和long。每種類型以及它們的存儲(chǔ)空間需求和取值范圍,如表2.3所示。
整數(shù)類型的取值范圍由各自的存儲(chǔ)大小決定。例如,int類型需要32位,這使得一個(gè)int變量有232=4294967296個(gè)不同的取值。由于所有的Java變量都是有符號(hào)的(意思是它們必須隱性地傳送正或負(fù)的值),有效范圍變?yōu)?231(-2147483648)~231-1(2147483647)。Int類型變量的最大值是2147483647而不是2147483648,這是由于0作為一個(gè)有效值被包含進(jìn)來(lái)了。
表2.3 整數(shù)類型范圍

2.浮點(diǎn)類型
有時(shí)整型數(shù)據(jù)不夠用,一些在數(shù)學(xué)和物理中使用的值通常用十進(jìn)制小數(shù)表示。Java和C++一樣,支持兩種小數(shù)類型:float和double。表2.4給出了它們的存儲(chǔ)方式和有效范圍。
聲明浮點(diǎn)變量的示例如下:
double pi = 2.141592653589793d; float velocity = 30.65f; double gravity = 9.81;
注意,聲明一個(gè)float類型的值,必須以f(或F)作為后綴;否則,會(huì)被當(dāng)作double類型。對(duì)于double值來(lái)說(shuō),d(或D)后綴是可選的。
表2.4 浮點(diǎn)類型范圍

雙精度數(shù)在本質(zhì)上給出了相對(duì)于浮點(diǎn)數(shù)兩倍的精度,但是,這是有代價(jià)的——通常是內(nèi)存的消耗。在Java API中,大部分的方法返回類型和數(shù)據(jù)成員時(shí)使用double型。這在實(shí)際開(kāi)發(fā)中值得注意。
3.Char類型
Java中一個(gè)字符(用char表達(dá))表示Unicode字符集中的一個(gè)元素。Unicode字符由16位組成,因此,有65536個(gè)不同的字符可用,這與C++的標(biāo)準(zhǔn)128個(gè)ASCII字符不同。Unicode字符集提供了很大的靈活性,它能包含所有不同語(yǔ)言的字符以及常用符號(hào)。
字符由單引號(hào)括起來(lái)的單個(gè)字符表達(dá),通常以16進(jìn)制表示,范圍為'\u0000'~'\uFFFF '(' u '告訴編譯器用戶在用兩個(gè)字節(jié)字符信息表示一個(gè)Unicode字符)。正確使用字符的示例如下:
char letter; char lastInitial = 'R';
注意:與C++中不同,Java中一個(gè)字符數(shù)組沒(méi)有必要組成一個(gè)字符串。Java API定義了自己的String類型。一般只有敏感信息,如密碼字段,才會(huì)作為字符數(shù)組處理。這是因?yàn)椋琂ava對(duì)象在沒(méi)有被Java虛擬機(jī)作為不被引用的對(duì)象清空之前一直駐留在內(nèi)存中,把敏感數(shù)據(jù)留在內(nèi)存中可能會(huì)造成危險(xiǎn)的局面。
4.布爾型
布爾型(以19世紀(jì)的數(shù)學(xué)家George Boole的名字命名)給了程序員為變量設(shè)置真值的能力。很多語(yǔ)言雖然使用boolean變量,但不把它看作一種獨(dú)立的數(shù)據(jù)類型。在Java中,任何一個(gè)boolean變量只有兩個(gè)有效值:true和false。boolean型沒(méi)有等價(jià)的數(shù)值賦值,也不允許類型轉(zhuǎn)換。還有,注意所有的if和while聲明都相當(dāng)于一個(gè)boolean結(jié)果。正確使用boolean型示例如下:
boolean isAlive = true; while(isAlive) { // 程序代碼 }
參考答案:
Java的原始數(shù)據(jù)類型可以分為4類,如下所述。
? 整型:byte、short、int和long。
? 浮點(diǎn)型:float和double。
? Char型:char。
? 布爾型:boolean。
面試題10 理解和掌握J(rèn)ava語(yǔ)言中的變量初始化
編譯并運(yùn)行下面代碼,請(qǐng)選擇正確的一項(xiàng)。
public class TestVariableInit { public static void main(String[] args) { TestClass tc = new TestClass(); int j; System.out.println("tc.iStr = " + tc.iStr); System.out.println("tc.i =" + tc.i); System.out.println("j =" + j); } } class TestClass { int i; String iStr; }
(a)編譯通過(guò),輸出:
tc.iStr = null tc.i =0 j =0
(b)編譯通過(guò),輸出:
tc.iStr = tc.i =0 j =0
(c)編譯錯(cuò)誤,提示j未初始化。
考點(diǎn):考察求職者對(duì)Java語(yǔ)言中的變量初始化的理解和掌握,特別是考察求職者對(duì)于對(duì)象變量的初始值null的理解。筆者在開(kāi)發(fā)項(xiàng)目時(shí),對(duì)這個(gè)問(wèn)題深有體會(huì),在項(xiàng)目試用階段頻繁產(chǎn)生錯(cuò)誤,耗費(fèi)了很多精力才找到癥結(jié),發(fā)現(xiàn)竟然是一個(gè)小小的null引發(fā)的。
出現(xiàn)頻率:★★★★★
【面試題解析】Java語(yǔ)言中,變量存放著某一個(gè)具體類型的值,一般變量對(duì)應(yīng)著一個(gè)名稱標(biāo)識(shí)符、指向一個(gè)類型和一個(gè)與之關(guān)聯(lián)的值。Java變量的值有兩種,一種是原始數(shù)據(jù)類型,另外一種是指向?qū)ο蟮囊茫鐖D2.1所示。

圖2.1 Java的變量類型示意圖
在Java(TM) 編程語(yǔ)言中,變量的初始化依靠于其所在的上下文。請(qǐng)看下面代碼:
int x; Dog fido;
假如x和fido都是實(shí)例變量,它們就分別被自動(dòng)初始化為0和null。null是一個(gè)非凡的字面值,它能賦值給任何引用變量。一般說(shuō)來(lái),假如實(shí)例變量在定義的時(shí)候沒(méi)有被顯式地初始化,那么Java將變量自動(dòng)初始化為“似零”的值,具體值由變量的數(shù)據(jù)類型決定,如表2.5所示。
表2.5 Java變量的默認(rèn)初始化值

請(qǐng)參考如下代碼:
public class TestVariableInit { public static void main(String[] args) { TestClass tc = new TestClass(); //打印出變量的初始化值 System.out.println("tc.iStr = " + tc.iStr); System.out.println("tc.i = " + tc.i); } } class TestClass { int i; // 初始化變量 String iStr; // 初始化變量 }
TestVariableInit運(yùn)行后輸出如下結(jié)果:
D:\>java TestVariableInit tc.iStr = null tc.i = 0
這種變量的默認(rèn)初始化并不是在所有的情況下都適用,例如,一個(gè)局部變量(在方法體內(nèi)聲明的變量)假如沒(méi)有顯式初始化,根據(jù)所在Java環(huán)境不同,編譯器會(huì)給出一個(gè)警告或者是報(bào)出一個(gè)錯(cuò)誤。
實(shí)際情況是,以前有些Java環(huán)境對(duì)局部變量不提供初始化,也不給出警告或者錯(cuò)誤。在這種情況下,值是垃圾,可能造成非常難于診斷的運(yùn)行錯(cuò)誤。
Oracle公司發(fā)布的Java開(kāi)發(fā)包(JDK)中,編譯器將在未初始化的局部變量的引用位置處報(bào)錯(cuò)。假如我們將TestVariableInit中的main()方法修改入下:
public static void main(String[] args) { TestClass tc = new TestClass(); String lStr; // 局部變量 int i; //局部變量 System.out.println("tc.iStr = " + tc.iStr); System.out.println("tc.i = " + tc.i); System.out.println("lStr = " + lStr); System.out.println("i = " + i); }
試圖編譯TestVariableInit會(huì)產(chǎn)生下面的輸出:
D:\>javac TestVariableInit.java TestVariableInit.java:8: Variable lStr may not have been initialized. System.out.println("lStr = " + lStr); TestVariableInit.java:9: Variable i may not have been initialized. System.out.println("i = " + i); ^ 2 errors
對(duì)于此類情況,Java環(huán)境保證給出一個(gè)默認(rèn)值,但是不答應(yīng)開(kāi)發(fā)者使用它,這有些不可思議。大部分的程序員都贊成為了可讀性更好,實(shí)例變量應(yīng)該初始化,并且局部變量必須初始化,這樣不管在哪種Java環(huán)境中,源代碼都可以被編譯,而不必關(guān)心源代碼的編寫者是誰(shuí)。
注意:對(duì)象的默認(rèn)初始值為null,但是系統(tǒng)并沒(méi)有創(chuàng)建一個(gè)相對(duì)應(yīng)的對(duì)象,只是創(chuàng)建了一個(gè)可以存儲(chǔ)對(duì)象引用的變量。這是Java程序員在軟件開(kāi)發(fā)中遇到的最常見(jiàn)的一個(gè)錯(cuò)誤。令人惱火的是,這些錯(cuò)誤只有在運(yùn)行的時(shí)候才會(huì)出現(xiàn)。在一個(gè)大型軟件項(xiàng)目的開(kāi)發(fā)中,由于這個(gè)小小的錯(cuò)誤導(dǎo)致大問(wèn)題屢見(jiàn)不鮮。
例如,變量聲明如下:
String str;
由于str是一個(gè)String類型的變量,系統(tǒng)會(huì)自動(dòng)分配一個(gè)存儲(chǔ)單元,用來(lái)存放String對(duì)象的引用,但是并沒(méi)有創(chuàng)建一個(gè)String對(duì)象。代碼如下:
public class TestVariableInit { public static void main(String[] args) { TestClass tc = new TestClass(); //千萬(wàn)注意,這里并沒(méi)有編譯錯(cuò)誤,會(huì)產(chǎn)生運(yùn)行時(shí)錯(cuò)誤! System.out.println("tc.i =" + tc.iStr.length()); } } class TestClass { int i; String iStr; }
使用javac命令編譯的時(shí)候是沒(méi)有任何錯(cuò)誤提示的,但是在運(yùn)行該程序時(shí),會(huì)返回一個(gè)空指針錯(cuò)誤:
Exception in thread "main" java.lang.NullPointerException at TestVariableInit.main(TestVariableInit.java:10)
從這個(gè)示例可以看出,iStr的值為null,但不是一個(gè)String對(duì)象,所以tc.iStr.length()是錯(cuò)誤的。
面試題11 哪幾個(gè)是有效的聲明語(yǔ)句
(a)char a='\u0061';
(b)char 'a'= 'a';
(c)char \u0061= 'a ';
(d)ch\u0061r a= 'a ';
(e)ch'a'r a='a';
考點(diǎn):考察求職者對(duì)Java語(yǔ)言的變量聲明和轉(zhuǎn)義符的認(rèn)識(shí)。
出現(xiàn)頻率:★★★★
【面試題解析】在Java源代碼中,可以使用Unicode值來(lái)表示字符型字,一般形式為\uxxxx,Java編譯器會(huì)將這些Unicode值轉(zhuǎn)換為字符來(lái)處理。
例如:
char \u0061='a ';
編譯器會(huì)將其翻譯為:
char a= 'a ';
表2.6給出了常見(jiàn)的Java轉(zhuǎn)義符。
表2.6 Java常用的轉(zhuǎn)義符

注意:在Java源代碼中,不能使用\u000a和\u000d來(lái)替代換行和回車,這樣編譯器會(huì)將這些值解釋為終止符,導(dǎo)致編譯錯(cuò)誤。
【面試題解析】參考前面介紹。
參考答案:(a)、(c)、(d)。
面試題12 選擇正確的代碼運(yùn)行結(jié)果
編譯運(yùn)行下面代碼,正確的運(yùn)行結(jié)果是?
public class TestVariableInit { char \u0061='a'; String s="\u0061"; public static void main(String[] args) { TestVariableInit tc = new TestVariableInit(); System.out.println(tc.a); System.out.println(tc.s); } }
(a)編譯錯(cuò)誤;
(b)輸出:a a;
(c)輸出:a \u0061;
(d)編譯正常,運(yùn)行出現(xiàn)錯(cuò)誤。
考點(diǎn):考察求職者對(duì)Java語(yǔ)言的變量聲明和轉(zhuǎn)義符的認(rèn)識(shí)。
出現(xiàn)頻率:★★★★
參考答案:(b)。
面試題13 空文件是否為一個(gè)有效的Java程序源文件
考點(diǎn):考察求職者對(duì)Java源文件結(jié)構(gòu)的理解。
出現(xiàn)頻率:★★★
【面試題解析】Java程序員最基本的知識(shí)之一就是掌握J(rèn)ava源文件的結(jié)構(gòu)。Java源文件可以包括如下幾個(gè)結(jié)構(gòu):
? package包;
? import內(nèi)容;
? 類型聲明。
其中,package用來(lái)制定該文件所處的包的名稱,必須位于源文件頂端;import用來(lái)指定所引入的一個(gè)或者多個(gè)包;類型聲明是任意的頂層類聲明和接口的聲明。
類和接口的定義次序是任意的,二者合起來(lái)稱為類型聲明。實(shí)際上,源文件可以不需要任何這樣的定義。Java SDK要求一個(gè)源文件中最多只能定義一個(gè)公共類,同時(shí)該源文件的文件名必須同該類相同。例如,某個(gè)公共類名稱為Hello,那么源文件名稱必須為Hello.java。
參考答案:是。
面試題14 嘗試編譯代碼并判斷結(jié)果
編譯下面的代碼,檢查結(jié)果。
import java.util.*; package com.dir; public Hello{ …… } Class Other{ …… }
請(qǐng)選擇一個(gè)正確的答案。
(a)編譯錯(cuò)誤,類Hello和Other不能出現(xiàn)在一個(gè)源文件中。
(b)編譯正確。
(c)編譯錯(cuò)誤,因?yàn)閕mport不能位于源文件的頂端。
(d)編譯錯(cuò)誤,因?yàn)閜ackage必須在import之前。
(e)編譯錯(cuò)誤,因?yàn)镠ello不能聲明為公共的。
【面試題解析】從前面的講解來(lái)看,明顯的答案是(d),因?yàn)镴ava源文件的包聲明必須在頂端。
參考答案:(d)。
面試題15 關(guān)于main()方法正確的描述是
(a)static void main(String[] args)。
(b)public static int main(String[] args)。
(c)public static void main(String args)。
(d)final static void main(String[] args)。
(e)public int main(String[] args,int argc)。
(f)static public void main(String[] args)。
考點(diǎn):考察求職者對(duì)于Java源文件中的main()方法的掌握。
出現(xiàn)頻率:★★★★
【面試題解析】在Java中,main()方法是Java應(yīng)用程序的入口方法,也就是說(shuō),程序在運(yùn)行的時(shí)候,第1個(gè)執(zhí)行的方法就是main()方法。這個(gè)方法和其他的方法有很大的不同。方法的名字必須是main,方法必須是public static void類型的,方法必須接收一個(gè)字符串?dāng)?shù)組的參數(shù)等。
通過(guò)一個(gè)最簡(jiǎn)單的Java應(yīng)用程序HelloWorld,來(lái)說(shuō)明Java類中main()方法,程序的代碼如下:
/** * Created by IntelliJ IDEA. * Date: 2013-08-03 * Time: 8:46:50 * Java中的main()方法詳解 */ public class HelloWorld { public static void main(String args[]) { System.out.println("Hello World!"); } }
1.類
HelloWorld類中有main()方法,說(shuō)明這是個(gè)Java應(yīng)用程序,通過(guò)JVM直接啟動(dòng)運(yùn)行的程序。既然是類,java允許類不加public關(guān)鍵字約束,當(dāng)然類的定義只能限制為public或者無(wú)限制關(guān)鍵字(默認(rèn)的)。
2.main()方法
這個(gè)main()方法的聲明為:public static void main(String args[])。必須這么定義,這是Java的規(guī)范,和JVM的運(yùn)行有關(guān)系。
當(dāng)一個(gè)類中有main()方法,執(zhí)行命令“java類名”,則會(huì)啟動(dòng)JVM執(zhí)行該類中的main()方法。由于JVM在運(yùn)行這個(gè)Java應(yīng)用程序的時(shí)候,首先會(huì)調(diào)用main()方法,調(diào)用時(shí)不實(shí)例化這個(gè)類的對(duì)象,而是通過(guò)類名直接調(diào)用,因此需要是限制為公共(public)和靜態(tài)(static)的。對(duì)于Java中的main()方法,JVM有限制,不能有返回值,因此返回值類型為void。
main()方法中需要一個(gè)輸入?yún)?shù),類型為String[],這個(gè)也是Java的規(guī)范,至于字符串?dāng)?shù)組的名字,是可以自己設(shè)定的。根據(jù)習(xí)慣,這個(gè)字符串?dāng)?shù)組的名字一般和Java規(guī)范范例中mian()方法的參數(shù)名保持一致(args)。
3.main()方法不能拋出異常
main()方法中的異常要么處理,要么不處理,不能繼續(xù)拋出。public static int main(String args[]) throws Exception來(lái)定義main()方法是錯(cuò)誤的。
4.main()方法中字符串參數(shù)數(shù)組作用
main()方法中字符串參數(shù)數(shù)組作用是接收命令行輸入?yún)?shù)的,命令行的參數(shù)之間用空格隔開(kāi)。下面給出一個(gè)例子,看看如何初始化和使用這個(gè)數(shù)組。
/** * Created by IntelliJ IDEA. * Date: 2013-08-03 * Time: 10:22:15 * 打印main()方法中的輸入?yún)?shù) */ public class TestMain { public static void main(String args[]){ System.out.println("打印main()方法中的輸入?yún)?shù)!"); for(int i=0;i System.out.println(args[i]); } } }
執(zhí)行方法和運(yùn)行結(jié)果如下:
D:\Study\basetest\src>javac TestMain.java D:\Study\basetest\src>java TestMain 1 2 3 打印main()方法中的輸入?yún)?shù)! 1 2 3
注意:main()方法作為一個(gè)特殊的規(guī)范,與普通的方法有很大區(qū)別,限制很多,理解其原理需要學(xué)習(xí)JVM相關(guān)知識(shí)。這是Java學(xué)習(xí)中大的障礙。
參考答案:(d)、(f)。
- 企業(yè)性能測(cè)試:體系構(gòu)建、落地指導(dǎo)與案例解讀
- 一線架構(gòu)師實(shí)踐指南
- MATLAB 2018從入門到精通
- 實(shí)用軟件工程
- 建筑運(yùn)維智慧管控平臺(tái)設(shè)計(jì)與實(shí)現(xiàn)
- 深入淺出數(shù)據(jù)結(jié)構(gòu)與算法(微課視頻版)
- 區(qū)塊鏈核心算法解析
- 軟件開(kāi)發(fā)大講堂·從入門到精通-第一輯(套裝共5冊(cè))
- 大數(shù)據(jù)實(shí)時(shí)流處理技術(shù)實(shí)戰(zhàn):基于Flink+Kafka技術(shù)
- Kubernetes Operator開(kāi)發(fā)進(jìn)階
- 軟件項(xiàng)目管理案例教程(第5版)
- 獵豹行動(dòng):硝煙中的敏捷轉(zhuǎn)型之旅
- C#從入門到精通(第2版)
- OpenGL ES 2.0游戲開(kāi)發(fā)(下卷)
- 大數(shù)據(jù)測(cè)試技術(shù)與實(shí)踐