首頁  >  文章  >  Java  >  java常見面試題目(含答案)

java常見面試題目(含答案)

(*-*)浩
(*-*)浩原創
2019-11-26 15:02:512504瀏覽

java常見面試題目(含答案)

如何用陣列實作佇列?

用陣列實作佇列時要注意 溢出 現象,這時我們可以採用循環數組的方式來解決,即將數組收尾相接。使用front指標指向隊列首位,tail指標指向隊列末位。 (建議學習:java常見面試題

內部類別存取局部變數的時候,為什麼變數必須加上final修飾?

因為生命週期不同。局部變數在方法結束後就會被銷毀,但內部類別物件並不一定,這樣就會導致內部類別引用了一個不存在的變數。

所以編譯器會在內部類別中產生局部變數的拷貝,這個拷貝的生命週期和內部類別物件相同,就不會出現上述問題。

但這樣就導致了其中一個變數被修改,兩個變數值可能不同的問題。為了解決這個問題,編譯器就要求局部變數需要被final修飾,以確保兩個變數值相同。

在JDK8之後,編譯器不要求內部類別存取的局部變數必須被final修飾,但局部變數值不能被修改(無論是方法或內部類別中),否則會報編譯錯誤。利用javap查看編譯後的字節碼可以發現,編譯器已經加上了final。

long s = 499999999 * 499999999 在上面的程式碼中,s的值是多少?

根據程式碼的計算結果,s的值應該是-1371654655,這是由於Java中右側值的計算預設是int型別。

非靜態內部類別能定義靜態方法嗎?

public class OuterClass{
    private static float f = 1.0f;

    class InnerClass{
        public static float func(){return f;}
    }
}

以上程式碼會出現編譯錯誤,因為只有靜態內部類別才能定義靜態方法。

Lock 和 Synchronized 有什麼不同?

1. 使用方法的区别
- **Synchronized**:在需要同步的对象中加入此控制,`synchronized`可以加在方法上,也可以加在特定代码块中,括号中表示需要锁的对象。
- **Lock**:需要显示指定起始位置和终止位置。一般使用`ReentrantLock`类做为锁,多个线程中必须要使用一个`ReentrantLock`类做为对象才能保证锁的生效。且在加锁和解锁处需要通过`lock()`和`unlock()`显示指出。所以一般会在`finally`块中写`unlock()`以防死锁。
2. 性能的区别
`synchronized`是托管给JVM执行的,而`lock`是java写的控制锁的代码。在Java1.5中,`synchronize`是性能低效的。因为这是一个重量级操作,需要调用操作接口,导致有可能加锁消耗的系统时间比加锁以外的操作还多。相比之下使用Java提供的Lock对象,性能更高一些。但是到了Java1.6,发生了变化。`synchronize`在语义上很清晰,可以进行很多优化,有适应自旋,锁消除,锁粗化,轻量级锁,偏向锁等等。导致在Java1.6上`synchronize`的性能并不比Lock差。
  - **Synchronized**:采用的是CPU悲观锁机制,即线程获得的是独占锁。独占锁意味着 **其他线程只能依靠阻塞来等待线程释放锁**。而在CPU转换线程阻塞时会引起线程上下文切换,当有很多线程竞争锁的时候,会引起CPU频繁的上下文切换导致效率很低。
  - **Lock**:用的是乐观锁方式。所谓乐观锁就是,**每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止**。乐观锁实现的机制就是`CAS`操作。我们可以进一步研究`ReentrantLock`的源代码,会发现其中比较重要的获得锁的一个方法是`compareAndSetState`。这里其实就是调用的CPU提供的特殊指令。
3. `ReentrantLock`:具有更好的可伸缩性:比如时间锁等候、可中断锁等候、无块结构锁、多个条件变量或者锁投票。

float 變數如何與 0 比較?

folat類型的還有double類型的,這些小數類型在趨近於0的時候直接等於0的可能性很小,一般都是無限趨近於0,因此不能用= =來判斷。應該用|x-0|

//用程序表示就是

fabs(x) < 0.00001f

如何新建非靜態內部類別?

內部類別在宣告的時候必須是Outer.Inner a,就像int a 一樣,至於靜態內部類別和非靜態內部類別new的時候有點差別:

Outer.Inner a = new Outer().new Inner()(非靜態,先有Outer物件才能new 內部類別)

Outer.Inner a = new Outer.Inner()(靜態內部類別)

Java標識符命名規則

可以包含:字母、數字、$、_(底線),不可用數字開頭,不能是Java 的關鍵字和保留字。

你知道哪些JDK中用到的設計模式?

裝飾模式:java.io

單一範例模式:Runtime類別

簡單工廠模式:Integer.valueOf方法

享元模式:String常數池、Integer.valueOf(int i)、Character.valueOf(char c)

迭代器模式:Iterator

職責鏈模式:ClassLoader的雙親委派模型

解釋器模式:正規表示式java.util.regex.Pattern

ConcurrentHashMap如何確保執行緒安全性

##JDK 1.7及以前:

ConcurrentHashMap允許多個修改操作並發進行,其關鍵在於使用了鎖定分離技術。它使用了多個鎖來控制對hash表的不同部分的修改。 ConcurrentHashMap內部使用段(Segment)來表示這些不同的部分,每個段其實就是一個小的hash table,它們有自己的鎖。只要多個修改操作發生在不同的段落上,它們就可以並發進行。

JDK 1.8:

Segment雖保留,但已經簡化屬性,只是為了相容舊版本。

插入時使用CAS演算法:unsafe.compareAndSwapInt(this, valueOffset, expect, update)。 CAS(Compare And Swap)意思是如果valueOffset位置包含的值與expect值相同,則更新valueOffset位置的值為update,並傳回true,否則不更新,傳回false。插入時不允許key或value為null

與Java8的HashMap有相通之處,底層仍由「陣列」 鍊錶紅黑樹;

底層結構存放的是TreeBin對象,而不是TreeNode物件;

CAS作為知名無鎖定演算法,那ConcurrentHashMap就沒用了麼?當然不是,當hash值與鍊錶的頭結點相同還是會synchronized上鎖,鎖鍊錶。

Thread.sleep() & Thread.yield()&Thread.wait()的差異

sleep()和yield()都會釋放CPU。

sleep()可讓優先權低的執行緒得到執行的機會,當然也可以讓同優先權和高優先權的執行緒有執行的機會;yield()只能使同優先權的執行緒有執行的機會。

Thread.sleep和Thread.yield()不會導致鎖定行為的改變,如果目前執行緒是擁有鎖定的,那麼Thread.sleep不會讓執行緒釋放鎖定。如果能夠幫助你記憶的話,可以簡單認為和鎖定相關的方法都定義在Object類別中,因此呼叫Thread.sleep是不會影響鎖定的相關行為。

Thread.sleep和Object.wait都會暫停目前的線程,而對於CPU資源來說,不管是哪種方式暫停的線程,都表示它暫時不再需要CPU的執行時間。 OS會將執行時間分配給其它執行緒。差別是,呼叫wait後,需要別的執行緒執行notify/notifyAll才能夠重新獲得CPU執行時間。

arraylist 和 linkedlist 的差別?

ArrayList和LinkedList兩者都實作了List接口,但它們之間有些不同。

(1)ArrayList是由Array所支援的基於一個索引的資料結構,所以它提供對元素的隨機存取

(2)與ArrayList相比,在LinkedList中插入、新增和刪除一個元素會更快

(3)LinkedList比ArrayList消耗更多的內存,因為LinkedList中的每個節點儲存了前後節點的引

以上是java常見面試題目(含答案)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn