「每日分享」挑戰四道Java試題

點擊上方"java全棧技術"關注,每天學習一個java知識點

四道Java基礎題,你能對幾道?

一、==符的使用

首先看一段比較有意思的代碼

「每日分享」挑戰四道Java試題

如果這道題你能得出正確答案,並能瞭解其中的原理的話。說明你基礎還可以。

如果你的答案 是 true 和true的話,你的基礎可能有所欠缺。

首先公佈下答案, 運行代碼,我們會得到 false true。

我們知道==比較的是兩個對象的引用,這裡的abcd都是新建出來的對象,按理說都應該輸入false才對。這就是這道題的有趣之處,無論是面試題還是論壇討論區,這道題的出場率都很高。原理其實很簡單,我們去看下Integer.java這個類就瞭然了。

「每日分享」挑戰四道Java試題

二、String

接著看代碼

「每日分享」挑戰四道Java試題

那麼這道題的答案是什麼

按照==的語法來看, 首先s1、s2、s3是三個不同的對象,常理來說,輸出都會是false。然而程序的運行結果確實true、false。第二個輸出false可以理解,第一個輸出true就又讓人費解了。

我們知道一些基本類型的變量和對象的引用變量都是在函數的棧內存中分配,而堆內存中則存放new 出來的對象和數組。然而除此之外還有一塊區域叫做常量池。像我們通常想String s1 = "abc"; 這樣申明的字符串對象,其值就是存儲在常量池中。當我們創建String s1 = "abc"這樣一個對象之後,"abc"就存儲到了常量池(也可叫做字符串池)中,當我們創建引用String s2 = "abc" 的時候,Java底層會優先在常量池中查找是否存在"abc",如果存在則讓s2指向這個值,不會重新創建,如果常量池中沒有則創建並添加的池中。這就是為什麼答案是true 和false的原因。

三、final關鍵字

還是來看一段代碼

「每日分享」挑戰四道Java試題

這種代碼相信大家寫過很多,當內部類訪問局部變量的時候,需要在局部變量前加final修飾符,不然編譯器就會報錯。通常我們也是這麼幹的。好的,第二個問題來了,為什麼要加final修飾符?相信大多數小夥伴都沒有思考過這個問題,但凡使用的時候,直接加上就得了,從來沒去深究過其中的原理。這對於一個優秀的程序員來說是不可取,我們不僅要知其然還要知其所以然。

現在我們來分析一下,為什麼要加final關鍵字。首先內部類的生命週期是成員級別的,而局部變量的生命週期實在方法體之內。也就是說會出現這樣一種情況,當mRun方法執行,new 的線程運行,新線程裡面會睡一秒。主線程會繼續執行,mRun執行完畢,name屬性生命週期結束。1秒之後,Syetem.out.printh(name)執行。然而此時name已經壽終正寢,不在內存中了。Java就是為了杜絕這種錯誤,嚴格要求內部類中訪問局部變量,必須使用final關鍵字修飾。局部變量被final修飾之後,此時會在內存中保有一份局部變量的複製品,當內部類訪問的時候其實訪問的是這個複製品。其實就是匿名內部類會將final的變量當成自己的一個成員變量保存。這就好像是把局部變量的生命週期變長了。說到底還是Java工程師提前把這個坑給我們填了,不然不知道又會有多少小夥伴會為了內部類局部變量而發愁了。

四、Integer與int那些事

看下面代碼

「每日分享」挑戰四道Java試題

這道題是繼第一題的後續,如果這道題你能很快速的得出答案,那麼恭喜你,==比較符你就算掌握的比較透徹了。

揭曉正確答案: true 、false

看到這個答案很多小夥伴又會不解,先來說下第二個,按第一題來說Integer不是把-128-127緩存起來了嗎?這不是應該是true嘛,但是你仔細看,這裡的Integer是我們自己new出來的,並不是用的緩存,所以結果是false。 現在來看第一個為啥又是true了?

首先這裡的值為1000,肯定和我們所知的Integer緩存沒有關係。既然和緩存沒有關係,a是新new出來的對象,按理說輸入應該是false才對。但是注意b這裡是int類型。當int和Integer進行==比較的時候,Java會把Integer進行自動拆箱,也就是把Integer轉成int類型,所以這裡進行比較的是int類型的值,所以結果即為true。


分享到:


相關文章: