作者:
逍遙Sean
簡(jiǎn)介:一個(gè)主修Java的Web網(wǎng)站\游戲服務(wù)器后端開發(fā)者
主頁(yè):https://blog.csdn.net/Ureliable
覺得博主文章不錯(cuò)的話,可以三連支持一下~ 如有需要我的支持,請(qǐng)私信或評(píng)論留言!
前言
前幾天參加了一個(gè)做web開發(fā)的面試,被問(wèn)了幾個(gè)問(wèn)題,雖然有些題目比較偏,但是確實(shí)是Java開發(fā)必須了解的內(nèi)容。我覺得比較簡(jiǎn)單的問(wèn)題,卻回答的不是很好,事后總結(jié)一下~
說(shuō)一下finally吧
Java的finally關(guān)鍵字是用于定義在try/catch語(yǔ)句塊中必須執(zhí)行的代碼塊。不論是否有異常拋出,finally塊都會(huì)被執(zhí)行
。通常在finally塊中釋放資源,如關(guān)閉文件、釋放數(shù)據(jù)庫(kù)連接等。finally塊也可以用于判斷try塊中的異常是否被捕獲和處理了,從而調(diào)用其他方法或拋出異常。finally塊可以在try塊和catch塊之后添加,但只能有一個(gè)finally塊。例如:
try {
// 執(zhí)行代碼
} catch(Exception e) {
// 處理異常
} finally {
// 釋放資源
}
說(shuō)一下public吧
- 在Java中,public是一個(gè)訪問(wèn)修飾符,它用于指定一個(gè)類、方法或變量可以從任何其他類或代碼中訪問(wèn)。
- 使用public修飾的類、方法或變量可以被任何其他的類或代碼訪問(wèn),而不限于同一個(gè)包。
- 對(duì)于面向?qū)ο缶幊虂?lái)說(shuō),public是最常用的訪問(wèn)修飾符之一。
- Java一個(gè)源程序只能有一個(gè)public類存在,且類名與文件名相同。
- Java程序是從main方法開始執(zhí)行的,
public
為類加載器提供入口,然后找到public
類中的main方法開始執(zhí)行。如果存在多個(gè)public
類,程序?qū)⒉恢涝搹哪睦飯?zhí)行。 - 注意,內(nèi)部類可以是
public
的,因?yàn)閮?nèi)部類是作為外部類的成員存在的。
靜態(tài)成員和靜態(tài)方法是什么
簡(jiǎn)單來(lái)講:靜態(tài)成員和靜態(tài)方法,可以直接通過(guò)類名進(jìn)行調(diào)用;其他的成員和方法則需要進(jìn)行實(shí)例化成對(duì)象之后,通過(guò)對(duì)象來(lái)調(diào)用。
Java的靜態(tài)成員和靜態(tài)方法都是屬于類而不是對(duì)象的,因此不需要實(shí)例化類就可以直接訪問(wèn)它們。靜態(tài)成員通常用于保存所有實(shí)例共享的數(shù)據(jù),而靜態(tài)方法通常用于提供不依賴于對(duì)象狀態(tài)的功能。
靜態(tài)成員可以通過(guò)以下方式聲明:
public class MyClass {
public static int staticVariable;
public static void staticMethod() {
// do something
}
}
靜態(tài)成員可以通過(guò)類名直接訪問(wèn),如下所示:
int i = MyClass.staticVariable;
MyClass.staticMethod();
注意到靜態(tài)方法中不能訪問(wèn)非靜態(tài)成員,因?yàn)榉庆o態(tài)成員必須依賴于對(duì)象狀態(tài),而靜態(tài)方法不依賴于對(duì)象狀態(tài)。
說(shuō)一下abstract
Java中的abstract是一個(gè)關(guān)鍵字,用于修飾類、方法或者成員變量。用abstract修飾的類稱為抽象類,用abstract修飾的方法稱為抽象方法,用abstract修飾的成員變量稱為抽象成員變量。
抽象類是一種特殊的類,不能被實(shí)例化,只能被繼承。抽象類中可以包含抽象方法和非抽象方法,抽象方法是沒有實(shí)現(xiàn)的方法,需要子類去實(shí)現(xiàn)。
抽象方法必須在抽象類中聲明,不能在普通類中聲明。子類繼承抽象類時(shí),必須實(shí)現(xiàn)抽象方法,否則子類也必須是抽象類。
抽象成員變量必須被子類實(shí)現(xiàn),否則子類也必須是抽象類。抽象成員變量必須以分號(hào)結(jié)尾,不可定義為private、static、final或native類型。
使用abstract應(yīng)注意:
abstract
不能與final
并列修飾同一個(gè)類 對(duì)的;abstract
類中不應(yīng)該有private
的成員 對(duì)的 :abstract
類中可以有private
但是不應(yīng)該有;abstract
方法必須在abstract
類或接口中 對(duì)的 : 若類中方法有abstract
修飾的,該類必須abstract
修改。接口方法默認(rèn)public abstract
;static
方法中能處理非static的屬性 錯(cuò)誤 :在JVM中static
方法在靜態(tài)區(qū),靜態(tài)區(qū)無(wú)法調(diào)用非靜態(tài)區(qū)屬性。
java的內(nèi)存模型
Java的內(nèi)存模型(Java Memory Model,JMM)指定了Java虛擬機(jī)如何管理內(nèi)存和線程之間的交互。它定義了在多線程環(huán)境下共享變量的可見性和順序性保證,以及線程之間的同步和互斥機(jī)制。
Java內(nèi)存模型規(guī)定了所有的變量都存儲(chǔ)在主內(nèi)存中,但是每個(gè)線程會(huì)有自己的工作內(nèi)存,線程的工作內(nèi)存保存了該線程中使用了的變量(從主內(nèi)存中拷貝的),線程對(duì)變量的操作都必須在工作內(nèi)存中進(jìn)行,不同線程之間無(wú)法直接訪問(wèn)對(duì)方工作內(nèi)存中的變量,線程間變量值從傳遞都要經(jīng)過(guò)主內(nèi)存完成
Java內(nèi)存模型中的主要概念包括:
- 主內(nèi)存:Java虛擬機(jī)中所有線程所共享的內(nèi)存區(qū)域,用于存儲(chǔ)所有變量的值。
- 工作內(nèi)存:每個(gè)線程獨(dú)立擁有的內(nèi)存區(qū)域,用于讀寫變量的值。線程之間不能直接訪問(wèn)對(duì)方的工作內(nèi)存,所有的變量值都要先從主內(nèi)存中讀取到工作內(nèi)存中,再進(jìn)行操作。
- 內(nèi)存屏障:Java虛擬機(jī)提供的一種同步機(jī)制,用于保證內(nèi)存操作的可見性和順序性。
Java內(nèi)存模型中規(guī)定了以下規(guī)則:
- 原子性:對(duì)于基本數(shù)據(jù)類型如int和long,讀寫操作具有原子性。對(duì)于引用類型和一些復(fù)合操作,如i++,并不具有原子性。
- 可見性:一個(gè)線程修改了變量的值,另一個(gè)線程必須能夠看到變量的最新值。JMM通過(guò)內(nèi)存屏障來(lái)保證可見性。
- 順序性:在沒有使用同步機(jī)制的情況下,JMM不能保證代碼的執(zhí)行順序,可能會(huì)出現(xiàn)指令重排等情況。使用volatile和synchronized等機(jī)制可以保證代碼的順序性。
- 原則上不保證讀線程能夠獲得寫線程的最新值。使用volatile保證了變量的可見性和順序性。
- 線程操作內(nèi)存必須先將內(nèi)存中的數(shù)據(jù)拷貝到線程的本地內(nèi)存中,線程之間的共享變量只能通過(guò)主內(nèi)存來(lái)傳遞。
什么是原子性
簡(jiǎn)單講:一個(gè)操作是不可中斷的,要么全部執(zhí)行成功要么全部執(zhí)行失敗,比如銀行轉(zhuǎn)賬
原子性是指一組操作要么全部完成,要么全部不完成,不會(huì)出現(xiàn)部分完成的情況,保證操作的完整性和一致性。在多線程編程中,如果一個(gè)操作需要被多個(gè)線程同時(shí)訪問(wèn),為了保證正確性,必須保證操作的原子性??梢允褂猛綑C(jī)制如鎖或原子變量等來(lái)實(shí)現(xiàn)原子性。
什么是可見性
當(dāng)多個(gè)線程訪問(wèn)同一變量時(shí),一個(gè)線程修改了這個(gè)變量的值,其他線程就能夠立即看到修改的值
可見性指的是一個(gè)程序中變量在多線程環(huán)境下的可見性。當(dāng)一個(gè)變量被一個(gè)線程修改后,其他線程是否能夠立即看到修改的結(jié)果就是可見性問(wèn)題。如果一個(gè)變量的值被修改后,其他線程不能立即看到變量的修改結(jié)果,那么就會(huì)出現(xiàn)數(shù)據(jù)不一致的問(wèn)題。在并發(fā)編程中,保證可見性是非常重要的一項(xiàng)技術(shù)。常見的解決可見性問(wèn)題的方式包括使用volatile關(guān)鍵字、synchronized關(guān)鍵字、Lock對(duì)象等。
什么是有序性
程序執(zhí)行的順序按照代碼的先后順序執(zhí)行int a = 0; //1
int b = 2; //2
像這2句代碼1會(huì)比2先執(zhí)行,但是jvm在正真執(zhí)行時(shí)不一定是1在2之前,這里涉及一個(gè)概念叫做指令重排,處理器為了提高程序運(yùn)行效率,可能會(huì)對(duì)輸入代碼進(jìn)行優(yōu)化,它不保證程序中各個(gè)語(yǔ)句的執(zhí)行先后順序同代碼中的順序一致,但是它會(huì)保證程序最終執(zhí)行結(jié)果和代碼順序執(zhí)行的結(jié)果是一致的。比如上面的代碼語(yǔ)句1和語(yǔ)句2誰(shuí)先執(zhí)行對(duì)最終的程序結(jié)果并沒有影響,那么就有可能在執(zhí)行過(guò)程中,語(yǔ)句2先執(zhí)行而語(yǔ)句1后執(zhí)行。
在指令重排時(shí)會(huì)考慮指令之間的數(shù)據(jù)依賴性,比如2依賴了1的數(shù)值,那么處理器會(huì)保證1在2之前執(zhí)行。
但是在多線程的情況下,指令重排就會(huì)有影響了。
volatile到底做了什么
在 Java 中,volatile 是一種關(guān)鍵字,用于修飾變量。當(dāng)一個(gè)變量被聲明為 volatile
時(shí),它的值可能會(huì)被并發(fā)修改,因此多個(gè)線程之間對(duì)該變量的讀寫操作是相互可見的。 具體來(lái)說(shuō),當(dāng)一個(gè)線程對(duì)一個(gè) volatile
變量進(jìn)行寫操作時(shí),它會(huì)強(qiáng)制刷新該變量的值到主內(nèi)存中,并通知其他線程該變量的值已經(jīng)發(fā)生改變。同理,當(dāng)一個(gè)線程對(duì)一個(gè) volatile
變量進(jìn)行讀操作時(shí),它會(huì)從主內(nèi)存中讀取最新的值而不是寄存器緩存中的值。因此,volatile 變量的讀寫操作具有原子性,可以保證線程安全。
需要注意的是,volatile 變量不能保證多個(gè)線程對(duì)該變量的復(fù)合操作(例如 i++)是原子性的,因此對(duì)于這類操作,仍然需要使用
synchronized 或者使用原子類來(lái)保證線程安全。
volatile實(shí)現(xiàn)了以下工作:
- 禁止了指令重排
- 保證了不同線程對(duì)這個(gè)變量進(jìn)行操作時(shí)的可見性,即一個(gè)線程修改了某個(gè)變量值,這個(gè)新值對(duì)其他線程是立即可見的
- 不保證原子性(線程不安全)
基本數(shù)據(jù)類型
Java基本數(shù)據(jù)類型包括八種:
-
byte(字節(jié)型):8位有符號(hào)二進(jìn)制數(shù),取值范圍為-128~127。
-
short(短整型):16位有符號(hào)二進(jìn)制數(shù),取值范圍為-32768~32767。
-
int(整型):32位有符號(hào)二進(jìn)制數(shù),取值范圍為-2147483648~2147483647。
-
long(長(zhǎng)整型):64位有符號(hào)二進(jìn)制數(shù),取值范圍為-9223372036854775808~9223372036854775807。
-
float(單精度浮點(diǎn)型):32位IEEE-754標(biāo)準(zhǔn)浮點(diǎn)數(shù)。
-
double(雙精度浮點(diǎn)型):64位IEEE-754標(biāo)準(zhǔn)浮點(diǎn)數(shù)。
-
char(字符型):16位Unicode字符,取值范圍為0~65535。
-
boolean(布爾型):true或false。
除了基本數(shù)據(jù)類型,Java還有引用數(shù)據(jù)類型,如類、接口、數(shù)組等。
什么是內(nèi)部類
內(nèi)部類是一個(gè)定義在另一個(gè)類中的類。它可以訪問(wèn)外部類的成員(包括私有成員),并且可以用來(lái)實(shí)現(xiàn)一些特定的功能,如事件處理、回調(diào)等。內(nèi)部類的作用主要是為了增強(qiáng)可讀性、安全性和封裝性。內(nèi)部類分為成員內(nèi)部類、局部?jī)?nèi)部類、匿名內(nèi)部類和靜態(tài)內(nèi)部類等幾種類型。
靜態(tài)內(nèi)部類里面一定是靜態(tài)方法嗎
不是必須的。靜態(tài)內(nèi)部類可以聲明靜態(tài)方法,但也可以聲明非靜態(tài)方法。另外,非靜態(tài)內(nèi)部類則不能聲明靜態(tài)方法,因?yàn)樗呀?jīng)默認(rèn)包含了外部類的實(shí)例,而靜態(tài)方法不能訪問(wèn)任何實(shí)例變量和實(shí)例方法。
靜態(tài)方法可以不可以使用非靜態(tài)變量
靜態(tài)方法不能直接使用非靜態(tài)變量,因?yàn)榉庆o態(tài)變量是屬于對(duì)象實(shí)例的,而靜態(tài)方法是獨(dú)立于對(duì)象實(shí)例的。如果要在靜態(tài)方法中使用非靜態(tài)變量,需要通過(guò)實(shí)例化對(duì)象來(lái)訪問(wèn)非靜態(tài)變量?;蛘邔⒎庆o態(tài)變量作為參數(shù)傳遞給靜態(tài)方法。
抽象方法可以不可以有函數(shù)體
抽象方法不能有函數(shù)體。抽象方法是一種特殊的方法聲明,它沒有具體的實(shí)現(xiàn),只有方法名、參數(shù)和返回值類型。在Java中,抽象方法必須聲明在抽象類中,并且抽象類必須用“abstract”關(guān)鍵字修飾。子類必須覆蓋重寫所有抽象方法才能被實(shí)例化,否則子類也必須是一個(gè)抽象類。因此,抽象方法不能有函數(shù)體,否則它就不再是一個(gè)抽象方法,而是一個(gè)普通的方法。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-718017.html
說(shuō)一下抽象類和接口
- 一個(gè)子類只能繼承一個(gè)抽象類(虛類),但能實(shí)現(xiàn)多個(gè)接口;
- 一個(gè)抽象類可以有構(gòu)造方法,接口沒有構(gòu)造方法;
- 一個(gè)抽象類中的方法不一定是抽象方法,即其中的方法可以有實(shí)現(xiàn)(有方法體),接口中的方法都是抽象方法,不能有方法體,只有聲明;
- 一個(gè)抽象類可以是
public、private、protected、default
, 接口只有public;- 一個(gè)抽象類中的方法可以是
public、private、protected、default
, 接口中的方法只能是public
和default
。
從使用上來(lái)說(shuō),抽象類適合用于創(chuàng)建一些共性較強(qiáng)的類和方法,而接口則適合用于實(shí)現(xiàn)某些特定的行為,以及在不同類之間進(jìn)行統(tǒng)一的操作。通常情況下,如果需要更好的擴(kuò)展性和靈活性,應(yīng)該優(yōu)先使用接口,如果需要提供一些默認(rèn)的實(shí)現(xiàn)或是定義某些共有的行為,應(yīng)該優(yōu)先使用抽象類。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-718017.html
到了這里,關(guān)于Java面試被問(wèn)了幾個(gè)簡(jiǎn)單的問(wèn)題,卻回答的不是很好的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!