圖解學(xué)習(xí)網(wǎng)站:https://xiaolincoding.com
大家好,我是小林。
周末有很多校招同學(xué)跟我反饋,今天美團(tuán)面試新增了 AI 面試。
也就是模擬真人的場景來面試,而你面對的面試官就是 AI 面試官,也屬于技術(shù)面試,面試時長大概 30 分鐘。
但是,不要覺得對面不是真人,就覺得很容易”作弊“,實(shí)際上AI面試的時候,會要求你不能離開攝像頭,要看著屏幕,并且檢測你切屏的操作,只要發(fā)現(xiàn)作弊,有可能就會被拉黑了 。
那 AI 面試具體會問什么呢?
我看了一下大家總結(jié)美團(tuán)AI面試,找到了一些規(guī)律,更多的是考察基礎(chǔ)方面的內(nèi)容:
八股文:會問 5 個左右的八股文,其中Java/Go/C++語言基礎(chǔ)+計(jì)算機(jī)網(wǎng)絡(luò)+Linux 命令+數(shù)據(jù)庫這些八股出現(xiàn)的概率比較高。
系統(tǒng)設(shè)計(jì):每一場AI面試,必有一個系統(tǒng)設(shè)計(jì)(要把功能、數(shù)據(jù)庫表設(shè)計(jì)、實(shí)現(xiàn)的邏輯流程說出來)
場景題:會問 2 個非技術(shù)類的場景題,主要是關(guān)于你在項(xiàng)目/實(shí)習(xí)/實(shí)驗(yàn)室中遇到的最大困難是什么怎么解決的,你平時是怎么學(xué)習(xí)這類問題
沒有算法,不會問你項(xiàng)目和實(shí)習(xí)的問題
我也找了兩份美團(tuán) AI 面試的面經(jīng),分別是 ?C++ 和 Java 的,給大家感受一下。
美團(tuán)AI面試 C++
技術(shù)八股:SSL/TLS的工作原理Linux是怎么看內(nèi)存使用情況的GET和POST的區(qū)別C++的多態(tài)是什么?怎么通過虛函數(shù)實(shí)現(xiàn)?C++的函數(shù)對象是什么?跟普通函數(shù)的區(qū)別?NoSQL是什么?有哪些NoSQL數(shù)據(jù)庫?
系統(tǒng)設(shè)計(jì):設(shè)計(jì)一個用戶積分系統(tǒng),怎么維護(hù)積分有效性和實(shí)現(xiàn)提醒功能?追問:怎么進(jìn)行數(shù)據(jù)庫設(shè)計(jì)?怎么進(jìn)行積分過期提醒?
場景題 :在實(shí)驗(yàn)室 / 項(xiàng)目涉及新的技術(shù)領(lǐng)域?是怎么學(xué)習(xí)的?舉例說明在實(shí)驗(yàn)室 / 實(shí)習(xí)遇到什么難題?是怎么解決的?舉例說明
SSL/TLS的工作原理?
傳統(tǒng)的 TLS 握手基本都是使用 RSA 算法來實(shí)現(xiàn)密鑰交換的,在將 TLS 證書部署服務(wù)端時,證書文件其實(shí)就是服務(wù)端的公鑰,會在 TLS 握手階段傳遞給客戶端,而服務(wù)端的私鑰則一直留在服務(wù)端,一定要確保私鑰不能被竊取。
在 RSA 密鑰協(xié)商算法中,客戶端會生成隨機(jī)密鑰,并使用服務(wù)端的公鑰加密后再傳給服務(wù)端。根據(jù)非對稱加密算法,公鑰加密的消息僅能通過私鑰解密,這樣服務(wù)端解密后,雙方就得到了相同的密鑰,再用它加密應(yīng)用消息。
我用 Wireshark 工具抓了用 RSA 密鑰交換的 TLS 握手過程,你可以從下面看到,一共經(jīng)歷了四次握手:
TLS 第一次握手
首先,由客戶端向服務(wù)器發(fā)起加密通信請求,也就是 ClientHello 請求。在這一步,客戶端主要向服務(wù)器發(fā)送以下信息:
- (1)客戶端支持的 TLS 協(xié)議版本,如 TLS 1.2 版本。(2)客戶端生產(chǎn)的隨機(jī)數(shù)(Client Random),后面用于生成「會話秘鑰」條件之一。(3)客戶端支持的密碼套件列表,如 RSA 加密算法。
TLS 第二次握手
服務(wù)器收到客戶端請求后,向客戶端發(fā)出響應(yīng),也就是 SeverHello。服務(wù)器回應(yīng)的內(nèi)容有如下內(nèi)容:
- (1)確認(rèn) TLS 協(xié)議版本,如果瀏覽器不支持,則關(guān)閉加密通信。(2)服務(wù)器生產(chǎn)的隨機(jī)數(shù)(Server Random),也是后面用于生產(chǎn)「會話秘鑰」條件之一。(3)確認(rèn)的密碼套件列表,如 RSA 加密算法。(4)服務(wù)器的數(shù)字證書。
TLS 第三次握手
客戶端收到服務(wù)器的回應(yīng)之后,首先通過瀏覽器或者操作系統(tǒng)中的 CA 公鑰,確認(rèn)服務(wù)器的數(shù)字證書的真實(shí)性。如果證書沒有問題,客戶端會從數(shù)字證書中取出服務(wù)器的公鑰,然后使用它加密報(bào)文,向服務(wù)器發(fā)送如下信息:
- (1)一個隨機(jī)數(shù)(pre-master key)。該隨機(jī)數(shù)會被服務(wù)器公鑰加密。(2)加密通信算法改變通知,表示隨后的信息都將用「會話秘鑰」加密通信。(3)客戶端握手結(jié)束通知,表示客戶端的握手階段已經(jīng)結(jié)束。這一項(xiàng)同時把之前所有內(nèi)容的發(fā)生的數(shù)據(jù)做個摘要,用來供服務(wù)端校驗(yàn)。
上面第一項(xiàng)的隨機(jī)數(shù)是整個握手階段的第三個隨機(jī)數(shù),會發(fā)給服務(wù)端,所以這個隨機(jī)數(shù)客戶端和服務(wù)端都是一樣的。服務(wù)器和客戶端有了這三個隨機(jī)數(shù)(Client Random、Server Random、pre-master key),接著就用雙方協(xié)商的加密算法,各自生成本次通信的「會話秘鑰」。
TLS 第四次握手
服務(wù)器收到客戶端的第三個隨機(jī)數(shù)(pre-master key)之后,通過協(xié)商的加密算法,計(jì)算出本次通信的「會話秘鑰」。然后,向客戶端發(fā)送最后的信息:
- (1)加密通信算法改變通知,表示隨后的信息都將用「會話秘鑰」加密通信。(2)服務(wù)器握手結(jié)束通知,表示服務(wù)器的握手階段已經(jīng)結(jié)束。這一項(xiàng)同時把之前所有內(nèi)容的發(fā)生的數(shù)據(jù)做個摘要,用來供客戶端校驗(yàn)。
至此,整個 TLS 的握手階段全部結(jié)束。接下來,客戶端與服務(wù)器進(jìn)入加密通信,就完全是使用普通的 HTTP 協(xié)議,只不過用「會話秘鑰」加密內(nèi)容。
Linux是怎么看內(nèi)存使用情況的?
使用 free -m 命令可以查看內(nèi)存的總體使用情況,輸出結(jié)果會大致如下:
total????????used????????free??????shared??buff/cache???available
Mem:????????????7982????????1746????????2523?????????155????????3703????????5818
Swap:???????????2047???????????6????????2041
關(guān)注以下幾項(xiàng):
used:已經(jīng)使用的內(nèi)存。
free:可用的空閑內(nèi)存。
available:可用的內(nèi)存,這包括了操作系統(tǒng)緩存,這個值更能代表實(shí)際可用內(nèi)存。
如果 available 的值長期很低,可能表明內(nèi)存不足。
GET和POST的區(qū)別
根據(jù) RFC 規(guī)范,GET 的語義是從服務(wù)器獲取指定的資源,這個資源可以是靜態(tài)的文本、頁面、圖片視頻等。GET 請求的參數(shù)位置一般是寫在 URL 中,URL 規(guī)定只能支持 ASCII,所以 GET 請求的參數(shù)只允許 ASCII 字符 ,而且瀏覽器會對 URL 的長度有限制(HTTP協(xié)議本身對 URL長度并沒有做任何規(guī)定)。比如,你打開我的文章,瀏覽器就會發(fā)送 GET 請求給服務(wù)器,服務(wù)器就會返回文章的所有文字及資源。
根據(jù) RFC 規(guī)范,POST 的語義是根據(jù)請求負(fù)荷(報(bào)文body)對指定的資源做出處理,具體的處理方式視資源類型而不同。POST 請求攜帶數(shù)據(jù)的位置一般是寫在報(bào)文 body 中,body 中的數(shù)據(jù)可以是任意格式的數(shù)據(jù),只要客戶端與服務(wù)端協(xié)商好即可,而且瀏覽器不會對 body 大小做限制。
比如,你在我文章底部,敲入了留言后點(diǎn)擊「提交」(暗示你們留言),瀏覽器就會執(zhí)行一次 POST 請求,把你的留言文字放進(jìn)了報(bào)文 body 里,然后拼接好 POST 請求頭,通過 TCP 協(xié)議發(fā)送給服務(wù)器。
如果從 RFC 規(guī)范定義的語義來看:
GET 方法就是安全且冪等的,因?yàn)樗恰钢蛔x」操作,無論操作多少次,服務(wù)器上的數(shù)據(jù)都是安全的,且每次的結(jié)果都是相同的。所以,
可以對 GET 請求的數(shù)據(jù)做緩存,這個緩存可以做到瀏覽器本身上(徹底避免瀏覽器發(fā)請求),也可以做到代理上(如nginx),而且在瀏覽器中 GET 請求可以保存為書簽。
POST
因?yàn)槭恰感略龌蛱峤粩?shù)據(jù)」的操作,會修改服務(wù)器上的資源,所以是不安全的,且多次提交數(shù)據(jù)就會創(chuàng)建多個資源,所以不是冪等的。所以,瀏覽器一般不會緩存 POST 請求,也不能把 POST 請求保存為書簽。
但是實(shí)際過程中,開發(fā)者不一定會按照 RFC 規(guī)范定義的語義來實(shí)現(xiàn) GET 和 POST 方法。比如:
- 可以用 GET 方法實(shí)現(xiàn)新增或刪除數(shù)據(jù)的請求,這樣實(shí)現(xiàn)的 GET 方法自然就不是安全和冪等??梢杂?POST 方法實(shí)現(xiàn)查詢數(shù)據(jù)的請求,這樣實(shí)現(xiàn)的 POST 方法自然就是安全和冪等。
C++的多態(tài)是什么?怎么通過虛函數(shù)實(shí)現(xiàn)?
C++中的多態(tài)性是指的是同一個操作作用于不同的對象時,可以產(chǎn)生不同的行為。多態(tài)性主要通過虛函數(shù)實(shí)現(xiàn),能夠讓你以父類的指針或引用調(diào)用子類的實(shí)現(xiàn),從而在運(yùn)行時決定使用哪個函數(shù)。
C++中的多態(tài)通常分為兩種主要類型:
編譯時多態(tài)(靜態(tài)多態(tài)):通過函數(shù)重載和運(yùn)算符重載實(shí)現(xiàn),在編譯時確定調(diào)用哪個函數(shù)。
運(yùn)行時多態(tài)(動態(tài)多態(tài)):通過虛函數(shù)實(shí)現(xiàn),在運(yùn)行時根據(jù)對象的實(shí)際類型決定調(diào)用的函數(shù)。實(shí)現(xiàn)原理是,每個包含虛函數(shù)的類都有一個虛函數(shù)表,這個表記錄了該類對象可以調(diào)用的虛函數(shù)指針,每個對象也有一個隱式的虛函數(shù)指針,指向其類的虛函數(shù)表。在運(yùn)行時,調(diào)用虛函數(shù)時,程序通過虛函數(shù)指針查找正確的函數(shù)。
虛函數(shù)是通過在基類中聲明一個函數(shù)為virtual
來實(shí)現(xiàn)的。這標(biāo)志著這個函數(shù)可以被派生類重寫(override)。當(dāng)通過基類指針或引用調(diào)用虛函數(shù)時,C++會查找實(shí)際對象的類型,調(diào)用對應(yīng)的子類實(shí)現(xiàn),而不是基類的實(shí)現(xiàn)。
下面是一個簡單的示例,展示了如何使用虛函數(shù)實(shí)現(xiàn)多態(tài)。
1. 定義基類和派生類
#include?<iostream>
using?namespace?std;
//?基類
class?Shape?{
public:
????//?虛函數(shù)
????virtual?void?draw()?{
????????cout?<<?"Drawing?Shape"?<<?endl;
????}
};
//?派生類:Circle
class?Circle?:?public?Shape?{
public:
????void?draw()?override?{??//?重寫虛函數(shù)
????????cout?<<?"Drawing?Circle"?<<?endl;
????}
};
//?派生類:Square
class?Square?:?public?Shape?{
public:
????void?draw()?override?{??//?重寫虛函數(shù)
????????cout?<<?"Drawing?Square"?<<?endl;
????}
};
2. 使用虛函數(shù)
- 創(chuàng)建一個函數(shù),接受基類指針作為參數(shù),利用多態(tài)性調(diào)用不同的派生類方法。
void?renderShape(Shape*?shape)?{
????shape->draw();??//?調(diào)用虛函數(shù)
}
int?main()?{
????Shape*?shape1?=?new?Circle();??//?創(chuàng)建?Circle?對象
????Shape*?shape2?=?new?Square();??//?創(chuàng)建?Square?對象
????renderShape(shape1);??//?輸出:?Drawing?Circle
????renderShape(shape2);??//?輸出:?Drawing?Square
????delete?shape1;??//?釋放內(nèi)存
????delete?shape2;??//?釋放內(nèi)存
????return?0;
}
C++的函數(shù)對象是什么?跟普通函數(shù)的區(qū)別?
函數(shù)對象是指一個重載了 operator()
的類或結(jié)構(gòu)體實(shí)例。函數(shù)對象可以像普通函數(shù)一樣被調(diào)用,但它們實(shí)際上是對象,具有狀態(tài)和行為。
普通函數(shù)與函數(shù)對象的區(qū)別:
-
- 定時方式:普通函數(shù)是用
返回類型 函數(shù)名(參數(shù))
-
- 語法定義的,而函數(shù)對象是一個類或結(jié)構(gòu)體,并重載了
operator()
- 。狀態(tài):普通函數(shù)無狀態(tài),而函數(shù)對象可以有內(nèi)置的狀態(tài)(成員變量)。調(diào)用方式:普通函數(shù)被直接調(diào)用,函數(shù)對象需要先創(chuàng)建實(shí)例,然后用實(shí)例調(diào)用。靈活性:函數(shù)對象可以重載多個操作符或添加更多功能,普通函數(shù)則只能定義一個函數(shù)。
普通函數(shù):
int?add(int?a,?int?b)?{
????return?a?+?b;
}
函數(shù)對象:
class?Add?{
public:
????int?operator()(int?a,?int?b)?{
????????return?a?+?b;
????}
};
Add?add;
int?result?=?add(2,?3);?//?調(diào)用函數(shù)對象
NoSQL是什么?有哪些NoSQL數(shù)據(jù)庫?
NoSQL指非關(guān)系型數(shù)據(jù)庫 ,主要代表:MongoDB,Redis。NoSQL 數(shù)據(jù)庫邏輯上提供了不同于二維表的存儲方式,存儲方式可以是JSON文檔、哈希表或者其他方式。選擇 SQL vs NoSQL,考慮以下因素。
ACID vs BASE
關(guān)系型數(shù)據(jù)庫支持 ACID 即原子性,一致性,隔離性和持續(xù)性。相對而言,NoSQL 采用更寬松的模型 BASE , 即基本可用,軟狀態(tài)和最終一致性。從實(shí)用的角度出發(fā),我們需要考慮對于面對的應(yīng)用場景,ACID 是否是必須的。比如銀行應(yīng)用就必須保證 ACID,否則一筆錢可能被使用兩次;又比如社交軟件不必保證 ACID,因?yàn)橐粭l狀態(tài)的更新對于所有用戶讀取先后時間有數(shù)秒不同并不影響使用。對于需要保證 ACID 的應(yīng)用,我們可以優(yōu)先考慮 SQL。反之則可以優(yōu)先考慮 NoSQL。
擴(kuò)展性對比
NoSQL數(shù)據(jù)之間無關(guān)系,這樣就非常容易擴(kuò)展,也無形之間,在架構(gòu)的層面上帶來了可擴(kuò)展的能力。比如 redis 自帶主從復(fù)制模式、哨兵模式、切片集群模式。相反關(guān)系型數(shù)據(jù)庫的數(shù)據(jù)之間存在關(guān)聯(lián)性,水平擴(kuò)展較難 ,需要解決跨服務(wù)器 JOIN,分布式事務(wù)等問題。
美團(tuán)AI面試 Java
技術(shù)八股:簡述 CORS 的工作原理;什么是長連接和短連接?它們各有什么優(yōu)缺點(diǎn)?如何查看當(dāng)前系統(tǒng)的內(nèi)存使用情況?什么是 MySQL 數(shù)據(jù)庫命名規(guī)范?為什么遵守命名規(guī)范很重要?解釋Java中的靜態(tài)變量和靜態(tài)方法。什么是Java里的垃圾回收?如何觸發(fā)垃圾回收?
系統(tǒng)設(shè)計(jì):設(shè)計(jì)一個基本的用戶隱私設(shè)置功能
場景題:描述一次你通過重構(gòu)代碼或優(yōu)化性能而學(xué)到新知識的經(jīng)歷描述一次你需要在有限資源、時間、人力、技術(shù)等下解決問題的經(jīng)歷
簡述 CORS 的工作原理
CORS(Cross-Origin Resource Sharing,跨源資源共享)是一種機(jī)制,它使用 HTTP 頭允許或限制不同源之間的資源共享。CORS 解決了瀏覽器的同源策略限制,使得網(wǎng)頁能夠安全地請求來自不同域的資源。
所謂的同源策略,在瀏覽器中,同源策略限制了從不同源(協(xié)議、域名和端口均不同)加載的資源。例如,域名為 example.com
的頁面無法直接請求 another-domain.com
上的資源。這是為了防止惡意網(wǎng)站竊取用戶數(shù)據(jù)。
CORS 的工作原理
請求階段:當(dāng)網(wǎng)頁嘗試從不同源發(fā)出請求時,瀏覽器會首先檢查 CORS 策略。對于跨源請求,瀏覽器會自動添加 CORS 請求頭。
簡單請求和預(yù)檢請求:
簡單請求
-
-
- :針對 GET、POST(符合特定條件,如 Content-Type 為
-
application/x-www-form-urlencoded
-
-
- 、
-
multipart/form-data
-
-
- 或
-
text/plain
-
-
- )等安全請求,直接發(fā)送請求。
-
預(yù)檢請求:如果請求的 HTTP 方法為 PUT、DELETE 或使用了自定義的請求頭,瀏覽器會先發(fā)送一個 OPTIONS 請求到服務(wù)器,詢問目標(biāo)資源的 CORS 允許情況,這被稱為預(yù)檢請求。
服務(wù)器響應(yīng):
Access-Control-Allow-Origin
-
-
- :指定允許訪問的源,可以是特定源或
-
*
-
-
- (允許所有源)。
-
Access-Control-Allow-Methods
-
-
- :指定允許的 HTTP 方法(如 GET、POST、PUT 等)。
-
Access-Control-Allow-Headers
-
-
- :允許的請求頭,主要用于自定義請求頭的情況。
-
Access-Control-Max-Age
-
-
- :表示預(yù)檢請求的有效期。服務(wù)器需要在響應(yīng)中包含 CORS 相關(guān)的 HTTP 頭,指示是否允許該跨源請求。主要的 CORS 響應(yīng)頭包括:
-
瀏覽器處理響應(yīng):如果服務(wù)器響應(yīng)的 CORS 頭匹配請求的源和相關(guān)設(shè)置,瀏覽器允許請求的結(jié)果繼續(xù)處理。如果 CORS 配置不匹配,瀏覽器會阻止請求并發(fā)出錯誤。
工作流程示例
發(fā)起請求:
-
-
- 用戶在http://example.com
-
-
-
- 的頁面中發(fā)起向http://api.example.com/data
-
-
-
- 的 AJAX 請求。
-
瀏覽器發(fā)起預(yù)檢請求(如果是跨域 POST 等):
-
- 瀏覽器發(fā)送一個 OPTIONS 請求:
OPTIONS?/data?HTTP/1.1
Origin:?http://example.com
服務(wù)器響應(yīng):
-
- 服務(wù)器響應(yīng)包含 CORS 相關(guān)頭:
HTTP/1.1?204?No?Content
Access-Control-Allow-Origin:?http://example.com
Access-Control-Allow-Methods:?GET,?POST
發(fā)送實(shí)際請求:
-
- 如果預(yù)檢請求成功,瀏覽器將發(fā)送實(shí)際的請求(如 POST)。服務(wù)器再次返回?cái)?shù)據(jù),并包含 CORS 頭,允許瀏覽器處理響應(yīng)。
什么是長連接和短連接?它們各有什么優(yōu)缺點(diǎn)?
長連接:
- 定義:當(dāng)一個網(wǎng)頁打開完成后,客戶端和服務(wù)器之間用于傳輸 HTTP 數(shù)據(jù)的 TCP 連接不會關(guān)閉,客戶端再次訪問這個服務(wù)器時,會繼續(xù)使用這一條已經(jīng)建立的連接。
- 優(yōu)點(diǎn):可以省去較多的 TCP 建立和關(guān)閉的操作,減少浪費(fèi),節(jié)約時間。對于頻繁請求資源的客戶來說較適用。
- 缺點(diǎn):存在存活功能的探測周期長的問題,遇到惡意連接時?;罟δ懿粔?;隨著客戶端連接增多,服務(wù)器可能扛不住,需要采取一些策略來管理連接。
短連接:
- 定義:客戶端和服務(wù)器每進(jìn)行一次 HTTP 操作,就建立一次連接,任務(wù)結(jié)束就中斷連接。
- 優(yōu)點(diǎn):管理起來比較簡單,存在的連接都是有用的連接,不需要額外的控制手段。
- 缺點(diǎn):如果客戶請求頻繁,將在 TCP 的建立和關(guān)閉操作上浪費(fèi)時間和帶寬。
如何查看當(dāng)前系統(tǒng)的內(nèi)存使用情況?
可以通過 top 或者 freem 命令都可以查看內(nèi)存情況
top 命令的 mem 信息這一欄,就是系統(tǒng)內(nèi)存的使用:
free 命令就是專門看系統(tǒng)內(nèi)存的使用情況。
什么是 MySQL 數(shù)據(jù)庫命名規(guī)范?為什么遵守命名規(guī)范很重要?
MySQL 數(shù)據(jù)庫命名規(guī)范是指在創(chuàng)建和管理數(shù)據(jù)庫、表、列、索引及其他對象時,遵循的一些標(biāo)準(zhǔn)化的命名規(guī)則。這些規(guī)范能夠幫助開發(fā)者提高代碼的可讀性、可維護(hù)性及簡潔性。以下是一些常見的 MySQL 數(shù)據(jù)庫命名規(guī)范:
表名命名規(guī)范:使用小寫字母,單詞之間用下劃線分隔(snake_case)。表名應(yīng)簡潔且具有描述性,例如:user_profiles
-
- 。大多數(shù)情況下,表名使用復(fù)數(shù)形式來表示集合,例如:users
-
- 而不是user。
列名命名規(guī)范:同樣使用小寫字母,單詞之間用下劃線分隔(snake_case)。列名應(yīng)能清晰描述所存儲的數(shù)據(jù),例如:
created_at
-
- 、
email_address
- 。
索引命名規(guī)范:
-
- 索引名稱應(yīng)以
idx_
-
- 開頭,后接表名和列名,例如:
idx_users_email
-
- 。對于唯一索引,可以以
uniq_
-
- 開頭,例如:
uniq_users_email
- 。
解釋Java中的靜態(tài)變量和靜態(tài)方法。
在Java中,靜態(tài)變量和靜態(tài)方法是與類本身關(guān)聯(lián)的,而不是與類的實(shí)例(對象)關(guān)聯(lián)。它們在內(nèi)存中只存在一份,可以被類的所有實(shí)例共享。
靜態(tài)變量
靜態(tài)變量(也稱為類變量)是在類中使用static
關(guān)鍵字聲明的變量。它們屬于類而不是任何具體的對象。主要的特點(diǎn):
共享性
-
- :所有該類的實(shí)例共享同一個靜態(tài)變量。如果一個實(shí)例修改了靜態(tài)變量的值,其他實(shí)例也會看到這個更改。
初始化
-
- :靜態(tài)變量在類被加載時初始化,只會對其進(jìn)行一次分配內(nèi)存。
訪問方式
- :靜態(tài)變量可以直接通過類名訪問,也可以通過實(shí)例訪問,但推薦使用類名。
示例:
public?class?MyClass?{
????static?int?staticVar?=?0;?//?靜態(tài)變量
????public?MyClass()?{
????????staticVar++;?//?每創(chuàng)建一個對象,靜態(tài)變量自增
????}
????
????public?static?void?printStaticVar()?{
????????System.out.println("Static?Var:?"?+?staticVar);
????}
}
//?使用示例
MyClass?obj1?=?new?MyClass();
MyClass?obj2?=?new?MyClass();
MyClass.printStaticVar();?//?輸出?Static?Var:?2
靜態(tài)方法
靜態(tài)方法是在類中使用static
關(guān)鍵字聲明的方法。類似于靜態(tài)變量,靜態(tài)方法也屬于類,而不是任何具體的對象。主要的特點(diǎn):
無實(shí)例依賴:靜態(tài)方法可以在沒有創(chuàng)建類實(shí)例的情況下調(diào)用。對于靜態(tài)方法來說,不能直接訪問非靜態(tài)的成員變量或方法,因?yàn)殪o態(tài)方法沒有上下文的實(shí)例。
訪問靜態(tài)成員:靜態(tài)方法可以直接調(diào)用其他靜態(tài)變量和靜態(tài)方法,但不能直接訪問非靜態(tài)成員。
多態(tài)性:靜態(tài)方法不支持重寫(Override),但可以被隱藏(Hide)。
public?class?MyClass?{
????static?int?count?=?0;
????//?靜態(tài)方法
????public?static?void?incrementCount()?{
????????count++;
????}
????public?static?void?displayCount()?{
????????System.out.println("Count:?"?+?count);
????}
}
//?使用示例
MyClass.incrementCount();?//?調(diào)用靜態(tài)方法
MyClass.displayCount();???//?輸出?Count:?1
使用場景
靜態(tài)變量:常用于需要在所有對象間共享的數(shù)據(jù),如計(jì)數(shù)器、常量等。
靜態(tài)方法:常用于助手方法(utility methods)、獲取類級別的信息或者是沒有依賴于實(shí)例的數(shù)據(jù)處理。
什么是Java里的垃圾回收?如何觸發(fā)垃圾回收?
垃圾回收(Garbage Collection, GC)是自動管理內(nèi)存的一種機(jī)制,它負(fù)責(zé)自動釋放不再被程序引用的對象所占用的內(nèi)存,這種機(jī)制減少了內(nèi)存泄漏和內(nèi)存管理錯誤的可能性。垃圾回收可以通過多種方式觸發(fā),具體如下:
內(nèi)存不足時:當(dāng)JVM檢測到堆內(nèi)存不足,無法為新的對象分配內(nèi)存時,會自動觸發(fā)垃圾回收。
手動請求:雖然垃圾回收是自動的,開發(fā)者可以通過調(diào)用
System.gc()
-
- 或
Runtime.getRuntime().gc()
-
- 建議 JVM 進(jìn)行垃圾回收。不過這只是一個建議,并不能保證立即執(zhí)行。
JVM參數(shù):啟動 Java 應(yīng)用時可以通過 JVM 參數(shù)來調(diào)整垃圾回收的行為,比如:
-Xmx
(最大堆大小)、
-Xms
(初始堆大?。┑取?/p>
對象數(shù)量或內(nèi)存使用達(dá)到閾值:垃圾收集器內(nèi)部實(shí)現(xiàn)了一些策略,以監(jiān)控對象的創(chuàng)建和內(nèi)存使用,達(dá)到某個閾值時觸發(fā)垃圾回收。