一個HelloWorld,居然和面試官聊了半小時!
大家好,我是老田,今天給大家分享的是群里小伙伴的面經(jīng)。
這位小伙伴入行搞java開發(fā),入坑三年不到。最近,私下跟我說,自己在團(tuán)隊(duì)沒有存在感,決定騎馬找驢。
真的,面試多了,自然也會遇到一些奇葩的面試官(不按套路出牌)。
背景
他就遇到這么以為奇葩的面試官,面試官要求當(dāng)場手寫一個HelloWorld類,并輸出“Hello World!”,幸運(yùn)的是這位小伙伴平時有留言過,也平時默寫過。所以這一步壓根兒就沒有難倒他。
其實(shí),地球人都知道,編程都從HelloWorld開始。
既然如此,請大家自行默寫一個java入門程序HelloWorld。
希望大家填寫真實(shí)情況,可以看看到底有多少人是手寫不來的。

是的,我們剛開始學(xué)java的時候也是這樣的,上來寫的第一個程序就是HelloWorld:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World");
}
}
當(dāng)初也是老師教咱們使用javac 對java文件進(jìn)行編譯,編譯成.class文件后,然后再使用java命令運(yùn)行,最后輸出"Hello World"。
對此面試題,我也問過很多工作不到三年的朋友,發(fā)現(xiàn)手寫起來好像并沒有那么簡單(部分人忘記寫參數(shù)、部分人沒有寫錯數(shù)組類型的參數(shù)、還有部分人System.out.println()沒寫出來)。
如果你是覺得 so easy!!! 并且能一口氣都可以把HeeloWorld類創(chuàng)建的代碼給說出來,那恭喜你,第一關(guān)過了。
精彩繼續(xù),面試官針對這個HelloWorld進(jìn)行詳細(xì)的詢問。
問題
1,為什么是靜態(tài)方法?
2,為什么方法沒有返回參數(shù)?
3,為什么方法名叫main?
4,為什么方法參數(shù)是數(shù)組?
5,System類你熟悉嗎?System類有哪些常見方法?
其實(shí),遠(yuǎn)不止5個問題,比如:
能不能把public改成protected、private?
一個類里可以對main方法進(jìn)行重載嗎?
問題解析
為什么是靜態(tài)方法
static修飾符:該修飾符表示靜態(tài)的意思,簡單理解被static修飾符修飾的成員都屬于類本身,而不屬于類的某個實(shí)例,靜態(tài)成員不能能直接訪問非靜態(tài)成員。
JVM調(diào)用這個主方法時肯定不是先創(chuàng)建這個主類的對象,再通過對象來調(diào)用方法,而是直接通過該類來調(diào)用這個方法,因此需要使用static修飾符修飾這個類。
其實(shí),這里要拓展的話,還可以把靜態(tài)和實(shí)例進(jìn)行比較等。
為什么方法沒有返回參數(shù)
方法被void修飾,表示此方法不需要返回值。由于main方法被JVM調(diào)用,將返回值返回給JVM沒有任何意義,因此該方法沒有返回值,所以使用void。
為什么方法名叫main
這個main()方法的聲明為:public static void main(String args[]) 。必須這么定義,這是Java的規(guī)范。
為什么要這么定義,和JVM的運(yùn)行有關(guān)系。
當(dāng)一個類中有main()方法,執(zhí)行命令“java 類名”則會啟動虛擬機(jī)執(zhí)行該類中的main方法。
用過Spring Boot、Dubbo的朋友應(yīng)該知道,都是以main方法啟動的。另外,還有我們使用的Tomcat,啟動Tomcat的時候,也是調(diào)用main方法的。
記?。?code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">main方法是Java程序的入口。
為什么方法參數(shù)是數(shù)組?
main()方法中字符串參數(shù)數(shù)組作用是接收命令行輸入?yún)?shù)的,命令行的參數(shù)之間用空格隔開。
如果我們使用dos命令運(yùn)行程序時,在類名后加上一個或者多個字符串(以空格隔開),這時JVM會依次將這些數(shù)值賦給args數(shù)組。
System類你熟悉嗎?
System類的全路徑名為java.lang.System。代表翻譯過來就是系統(tǒng),很多系統(tǒng)級的屬性和控制方法都在這個類里。
構(gòu)造方法
/** Don't let anyone instantiate this class */
private System() {
}
構(gòu)造方式是private修飾的,主食中也注明了"不要讓任何人實(shí)例化這個類",也就是無法實(shí)例化該類。
成員變量/方法
System類中,不管是成員變量,還是成員方法都是static修飾的(靜態(tài)的),這樣我們就可以很方便的使用了。
成員變量使用
控制臺上輸出"老田,您好!"
System.out.println("老田,您好!")
這就是調(diào)用了System的成員變量out,out變量定義如下:
public final static PrintStream out = null;
成員方法的使用
上面已經(jīng)說過了,System的成員方法也都是靜態(tài)的。

獲取當(dāng)前毫秒
System.currentTimeMillis()
其中,currentTimeMillis方法的定義:
public static native long currentTimeMillis();
在開發(fā)過程中,通常很多人都習(xí)慣使用new Date()來獲取當(dāng)前時間。new Date()所做的事情其實(shí)就是調(diào)用了System.currentTimeMillis()。如果僅僅是需要毫秒數(shù),那么完全可以使用System.currentTimeMillis()去代替new Date(),效率上會高一點(diǎn)。
三個成員變量in、out和err
System中包含了in、out和err三個成員變量,分別代表標(biāo)準(zhǔn)輸入流(鍵盤輸入)、標(biāo)準(zhǔn)輸出流(顯示器)和標(biāo)準(zhǔn)錯誤輸出流(顯示器) 。
//標(biāo)準(zhǔn)輸入流
public final static InputStream in;
//標(biāo)準(zhǔn)輸出流
public final static PrintStream out;
//標(biāo)準(zhǔn)錯誤流
public final static PrintStream err;
由此可見,System中的out和in都不是內(nèi)部類,是成員變量。out是PrintStream的final static來修飾變量,另外,out是可以調(diào)用PrintStream中的方法的。例如,System.out.println()中的println()就是PrintStream中的一種輸出方法。
常用方法
System中有很多方法,我們也沒必要把全部學(xué)完,我們只要把常用的搞定就可以了,只是太多,搞點(diǎn)實(shí)際有用的就行。
arraycopy ()方法
方法定義為native級的,數(shù)組拷貝。
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
參數(shù)解釋:
a是被復(fù)制的數(shù)組 b是復(fù)制的起始位置 c是復(fù)制到的數(shù)組 d是復(fù)制到這個數(shù)組的起始位置 e是復(fù)制到這個數(shù)組的結(jié)束位置。
currentTimeMillis() 方法
返回毫秒數(shù),這個就比較簡單了,和Date類中的getTime方法一樣。
public static native long currentTimeMillis();
補(bǔ)充
時間單位換算:
1秒=1000毫秒(ms) 1毫秒=1/1,000秒(s)
1秒=1,000,000 微秒(μs) 1微秒=1/1,000,000秒(s)
1秒=1,000,000,000 納秒(ns) 1納秒=1/1,000,000,000秒(s)
1秒=1,000,000,000,000 皮秒(ps) 1皮秒=1/1,000,000,000,000秒(s)
1分鐘=60秒
1小時=60分鐘=3600秒
getProperty ()方法
該方法是獲取系統(tǒng)屬性 。

方法定義:
private static Properties props;
public static String getProperty(String key, String def) {
checkKey(key);
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPropertyAccess(key);
}
return props.getProperty(key, def);
}
//Properties是Hashtable的子類
public class Properties extends Hashtable<Object,Object> {
...
}
這里的Properties,可能有些不是很熟悉,它就是Hashtable的子類。很少看到Hashtable的身影,今天終于見到了。
String userHome = System.getProperty("user.home");
System.out.println(userHome);
這個方法估計很多人沒用過,你也可以找時間試試。
gc()方法
告訴JVM,建議執(zhí)行垃圾回收。
方法定義:
public static void gc() {
Runtime.getRuntime().gc();
}
從定義上可知,gc()方法里封裝的是Runtime.getRuntime().gc()。
注意
這個
gc()方法只是建議JVM執(zhí)行垃圾回收,JVM可能會決絕。
GC本身是會周期性的自動運(yùn)行的,由JVM決定運(yùn)行的時機(jī),而且現(xiàn)在的版本有多種更智能的模式可以選擇,還會根據(jù)運(yùn)行的機(jī)器自動去做選擇,就算真的有性能上的需求,也應(yīng)該去對GC的運(yùn)行機(jī)制進(jìn)行微調(diào),而不是通過使用這個方法來實(shí)現(xiàn)性能的優(yōu)化。
exit()方法
退出虛擬機(jī)。
方法定義:
public static void exit(int status) {
Runtime.getRuntime().exit(status);
}
方法注釋
Terminates the currently running Java Virtual Machine. The argument serves as a status code; by convention, a nonzero status code indicates abnormal termination.This method never returns normally.
翻譯過來,大致為:exit(int)方法是終止當(dāng)前正在運(yùn)行的java虛擬機(jī)。參數(shù)是狀態(tài)碼。根據(jù)慣例,非0的狀態(tài)碼表示異常終止,0表是終止。而且,該方法永遠(yuǎn)不會正常返回。
總結(jié)
一個HelloWorld類引發(fā)了這么多問題,你學(xué)到了嗎?
關(guān)注我,分享更多技術(shù)知識,記得把我公眾號設(shè)置為“星標(biāo)”!
— 【 THE END 】— 本公眾號全部博文已整理成一個目錄,請?jiān)诠娞柪锘貜?fù)「m」獲??! 最近面試BAT,整理一份面試資料《Java面試BATJ通關(guān)手冊》,覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫、數(shù)據(jù)結(jié)構(gòu)等等。
獲取方式:點(diǎn)“在看”,關(guān)注公眾號并回復(fù) PDF 領(lǐng)取,更多內(nèi)容陸續(xù)奉上。
文章有幫助的話,在看,轉(zhuǎn)發(fā)吧。
謝謝支持喲 (*^__^*)
