Java面試知識點總結①——Java基礎

大綱

  • [x] 1、Java基礎(語言、集合框架、OOP、設計模式等)
  • [x] 2、Java高級(JavaEE、框架、服務器、工具等)
  • [x] 3、多線程和併發
  • [x] 4、Java虛擬機
  • [x] 5、數據庫(Sql、MySQL、Redis等)
  • [x] 6、算法與數據結構
  • [x] 7、計算機網絡
  • [x] 8、操做系統(OS基礎、Linux等)
  • [x] 9、其餘

1、Java基礎(語言、集合框架、OOP、設計模式等)

1. HashMap和Hashtable的區別java

  • [x] Hashtable是基於陳舊的Dictionary的Map接口的實現,而HashMap是基於哈希表的Map接口的實現
  • [x] 從方法上看,HashMap去掉了Hashtable的contains方法
  • [x] HashTable是同步的(線程安全),而HashMap線程不安全,效率上HashMap更快
  • [x] HashMap容許空鍵值,而Hashtable不容許
  • [x] HashMap的iterator迭代器執行快速失敗機制,也就是說在迭代過程當中修改集合結構,除非調用迭代器自身的remove方法,不然以其餘任何方式的修改都將拋出併發修改異常。而Hashtable返回的Enumeration不是快速失敗的。

注:Fast-fail機制:在使用迭代器的過程當中有其它線程修改了集合對象結構或元素數量,都將拋出ConcurrentModificationException,可是拋出這個異常是不保證的,咱們不能編寫依賴於此異常的程序。c++

2. java的線程安全git

Vector、Stack、HashTable、ConcurrentHashMap、Properties程序員

3. java集合框架(經常使用)github

Collection - List - ArrayList
Collection - List - LinkedList
Collection - List - Vector
Collection - Queue - PriorityQueue
Collection - List - Vector - Stack
Collection - Set - HashSet
Collection - Set - TreeSet
Collection - Set - LinkedHashSet
Map - HashMap
Map - TreeMap
Map - HashTable
Map - LinkedHashMap
Map - ConcurrentHashMap複製代碼

3.1 List集合和Set集合面試

List中元素存取是有序的、可重複的;Set集合中元素是無序的,不可重複的。正則表達式

CopyOnWriteArrayList:COW的策略,即寫時複製的策略。適用於讀多寫少的併發場景算法

Set集合元素存取無序,且元素不可重複。sql

HashSet不保證迭代順序,線程不安全;LinkedHashSet是Set接口的哈希表和連接列表的實現,保證迭代順序,線程不安全。數據庫

TreeSet:能夠對Set集合中的元素排序,元素以二叉樹形式存放,線程不安全。

3.2 ArrayList、LinkedList、Vector的區別

首先它們均是List接口的實現。

ArrayList、LinkedList的區別

1.隨機存取:ArrayList是基於可變大小的數組實現,LinkedList是連接列表的實現。這也就決定了對於隨機訪問的get和set的操做,ArrayList要優於LinkedList,由於LinkedList要移動指針。

2.插入和刪除:LinkedList要好一些,由於ArrayList要移動數據,更新索引。

3.內存消耗:LinkedList須要更多的內存,由於須要維護指向後繼結點的指針。

Vector從JDK 1.0起就存在,在1.2時改成實現List接口,功能與ArrayList相似,可是Vector具有線程安全。

3.3 Map集合

Hashtable:基於Dictionary類,線程安全,速度快。底層是哈希表數據結構。是同步的。不容許null做爲鍵,null做爲值。

Properties:Hashtable的子類。用於配置文件的定義和操做,使用頻率很是高,同時鍵和值都是字符串。

HashMap:線程不安全,底層是數組加鏈表實現的哈希表。容許null做爲鍵,null做爲值。HashMap去掉了contains方法。注意:HashMap不保證元素的迭代順序。若是須要元素存取有序,請使用LinkedHashMap

TreeMap:能夠用來對Map集合中的鍵進行排序。

ConcurrentHashMap:是JUC包下的一個併發集合。

3.4 爲何使用ConcurrentHashMap而不是HashMap或Hashtable?

HashMap的缺點:主要是多線程同時put時,若是同時觸發了rehash操做,會致使HashMap中的鏈表中出現循環節點,進而使得後面get的時候,會死循環,CPU達到100%,因此在併發狀況下不能使用HashMap。讓HashMap同步:Map m = Collections.synchronizeMap(hashMap);而Hashtable雖然是同步的,使用synchronized來保證線程安全,但在線程競爭激烈的狀況下HashTable的效率很是低下。由於當一個線程訪問HashTable的同步方法時,其餘線程訪問HashTable的同步方法時,可能會進入阻塞或輪詢狀態。如線程1使用put進行添加元素,線程2不但不能使用put方法添加元素,而且也不能使用get方法來獲取元素,因此競爭越激烈效率越低。

ConcurrentHashMap的原理:

Hashtable容器在競爭激烈的併發環境下表現出效率低下的緣由在於全部訪問Hashtable的線程都必須競爭同一把鎖,那假如容器裏有多把鎖,每一把鎖用於鎖容器其中一部分數據,那麼當多線程訪問容器裏不一樣數據段的數據時,線程間就不會存在鎖競爭,從而能夠有效的提升併發訪問效率,這就是ConcurrentHashMap所使用的鎖分段技術,首先將數據分紅一段一段的存儲,而後給每一段數據配一把鎖,當一個線程佔用鎖訪問其中一個段數據的時候,其餘段的數據也能被其餘線程訪問。

ConcurrentHashMap的結構:

ConcurrentHashMap是由Segment數組結構和HashEntry數組結構組成。Segment是一種可重入互斥鎖ReentrantLock,在ConcurrentHashMap裏扮演鎖的角色,HashEntry則用於存儲鍵值對數據。一個ConcurrentHashMap裏包含一個Segment數組,Segment的結構和HashMap相似,是一種數組和鏈表結構, 一個Segment裏包含一個HashEntry數組,每一個HashEntry是一個鏈表結構的元素,當對某個HashEntry數組的數據進行修改時,必須首先得到它對應的Segment鎖。

ConcurrentHashMap的構造、get、put操做:

構造函數:傳入參數分別爲 一、初始容量,默認16 二、裝載因子 裝載因子用於rehash的斷定,就是當ConcurrentHashMap中的元素大於裝載因子*最大容量時進行擴容,默認0.75 三、併發級別 這個值用來肯定Segment的個數,Segment的個數是大於等於concurrencyLevel的第一個2的n次方的數。好比,若是concurrencyLevel爲12,13,14,15,16這些數,則Segment的數目爲16(2的4次方)。默認值爲static final int DEFAULTCONCURRENCYLEVEL = 16;。理想狀況下ConcurrentHashMap的真正的併發訪問量可以達到concurrencyLevel,由於有concurrencyLevel個Segment,假若有concurrencyLevel個線程須要訪問Map,而且須要訪問的數據都剛好分別落在不一樣的Segment中,則這些線程可以無競爭地自由訪問(由於他們不須要競爭同一把鎖),達到同時訪問的效果。這也是爲何這個參數起名爲「併發級別」的緣由。默認16.

初始化的一些動做:

初始化segments數組(根據併發級別獲得數組大小ssize),默認16

初始化segmentShift和segmentMask(這兩個全局變量在定位segment時的哈希算法裏須要使用),默認狀況下segmentShift爲28,segmentMask爲15

初始化每一個Segment,這一步會肯定Segment裏HashEntry數組的長度.

put操做:

一、判斷value是否爲null,若是爲null,直接拋出異常。

二、key經過一次hash運算獲得一個hash值。將獲得hash值向右按位移動segmentShift位,而後再與segmentMask作&運算獲得segment的索引j。即segmentFor方法

三、使用Unsafe的方式從Segment數組中獲取該索引對應的Segment對象。向這個Segment對象中put值,這個put操做也基本是同樣的步驟(經過&運算獲取HashEntry的索引,而後set)。

get操做:

一、和put操做同樣,先經過key進行hash肯定應該去哪一個Segment中取數據。

二、使用Unsafe獲取對應的Segment,而後再進行一次&運算獲得HashEntry鏈表的位置,而後從鏈表頭開始遍歷整個鏈表(由於Hash可能會有碰撞,因此用一個鏈表保存),若是找到對應的key,則返回對應的value值,若是鏈表遍歷完都沒有找到對應的key,則說明Map中不包含該key,返回null。

定位Segment的hash算法:(hash >>> segmentShift) & segmentMask

定位HashEntry所使用的hash算法:int index = hash & (tab.length - 1);

注:

1.tab爲HashEntry數組

2.ConcurrentHashMap既不容許key爲null 也不容許value爲null

3.5 Collection 和 Collections的區別

Collection是集合類的上級接口,子接口主要有Set 和List、QueueCollections是針對集合類的一個輔助類,提供了操做集合的工具方法:一系列靜態方法實現對各類集合的搜索、排序、線程安全化等操做。

3.6 Map、Set、List、Queue、Stack的特色與用法

Set集合相似於一個罐子,"丟進"Set集合裏的多個對象之間沒有明顯的順序。 List集合表明元素有序、可重複的集合,集合中每一個元素都有其對應的順序索引。 Stack是Vector提供的一個子類,用於模擬"棧"這種數據結構(LIFO後進先出) Queue用於模擬"隊列"這種數據結構(先進先出 FIFO)。 Map用於保存具備"映射關係"的數據,所以Map集合裏保存着兩組值。

3.7 HashMap的工做原理

HashMap維護了一個Entry數組,Entry內部類有key,value,hash和next四個字段,其中next也是一個Entry類型。能夠將Entry數組理解爲一個個的散列桶。每個桶其實是一個單鏈表。當執行put操做時,會根據key的hashcode定位到相應的桶。遍歷單鏈表檢查該key是否已經存在,若是存在,覆蓋該value,反之,新建一個新的Entry,並放在單鏈表的頭部。當經過傳遞key調用get方法時,它再次使用key.hashCode()來找到相應的散列桶,而後使用key.equals()方法找出單鏈表中正確的Entry,而後返回它的值。

3.8 Map的實現類的介紹

HashMap基於散列表來的實現,即便用hashCode()進行快速查詢元素的位置,顯著提升性能。插入和查詢「鍵值對」的開銷是固定的。能夠經過設置容量和裝載因子,以調整容器的性能。

LinkedHashMap, 相似於HashMap,可是迭代遍歷它時,保證迭代的順序是其插入的次序,由於它使用鏈表維護內部次序。此外能夠在構造器中設定LinkedHashMap,使之採用LRU算法。使沒有被訪問過的元素或較少訪問的元素出如今前面,訪問過的或訪問多的出如今後面。這對於須要按期清理元素以節省空間的程序員來講,此功能使得程序員很容易得以實現。

TreeMap, 是基於紅黑樹的實現。同時TreeMap實現了SortedMap接口,該接口能夠確保鍵處於排序狀態。因此查看「鍵」和「鍵值對」時,全部獲得的結果都是通過排序的,次序由天然排序或提供的Comparator決定。SortedMap接口擁有其餘額外的功能,如:返回當前Map使用的Comparator比較器,firstKey(),lastKey(),headMap(toKey),tailMap(fromKey)以及能夠返回一個子樹的subMap()方法等。

WeakHashMap,表示弱鍵映射,WeakHashMap 的工做與正常的 HashMap 相似,可是使用弱引用做爲 key,意思就是當 key 對象沒有任何引用時,key/value 將會被回收。

ConcurrentHashMap, 在HashMap基礎上分段鎖機制實現的線程安全的HashMap。

IdentityHashMap 使用==代替equals() 對「鍵」進行比較的散列映射。專爲解決特殊問題而設計。

HashTable:基於Dictionary類的Map接口的實現,它是線程安全的。

3.9 LinkedList 和 PriorityQueue 的區別

它們均是Queue接口的實現。擁有FIFO的特色,它們的區別在於排序行爲。LinkedList 支持雙向列表操做,PriorityQueue 按優先級組織的隊列,元素的出隊次序由元素的天然排序或者由Comparator比較器指定。

3.10 線程安全的集合類。Vector、Hashtable、Properties和Stack、ConcurrentHashMap

3.11 BlockingQueue

java.util.concurrent.BlockingQueue是一個隊列,在進行獲取元素時,它會等待隊列變爲非空;當在添加一個元素時,它會等待隊列中的可用空間。BlockingQueue接口是Java集合框架的一部分,主要用於實現生產者-消費者模式。咱們不須要擔憂等待生產者有可用的空間,或消費者有可用的對象,由於它都在BlockingQueue的實現類中被處理了。Java提供了集中BlockingQueue的實現,好比ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue,、SynchronousQueue等。

3.12 如何對一組對象進行排序

若是須要對一個對象數組進行排序,咱們可使用Arrays.sort()方法。若是咱們須要排序一個對象列表,咱們可使用Collections.sort()方法。排序時是默認根據元素的天然排序(使用Comparable)或使用Comparator外部比較器。Collections內部使用數組排序方法,全部它們二者都有相同的性能,只是Collections須要花時間將列表轉換爲數組。

4. ArrayList

  • 無參構造 容量爲10
  • ArrayList(Collections c)構造包含指定collection的元素的列表
  • ArrayList(int initialCapacity) 指定初始容量

5. final關鍵字

final修飾的變量是常量,必須進行初始化,能夠顯示初始化,也能夠經過構造函數進行初始化,若是不初始化編譯會報錯。

6. 接口與抽象類

6.1 一個子類只能繼承一個抽象類,但能實現多個接口6.2 抽象類能夠有構造方法,接口沒有構造方法6.3 抽象類能夠有普通成員變量,接口沒有普通成員變量6.4 抽象類和接口均可有靜態成員變量,抽象類中靜態成員變量訪問類型任意,接口只能public static final(默認)6.5 抽象類能夠沒有抽象方法,抽象類能夠有普通方法,接口中都是抽象方法6.6 抽象類能夠有靜態方法,接口不能有靜態方法6.7 抽象類中的方法能夠是public、protected;接口方法只有public abstract

7. 抽象類和最終類

抽象類能夠沒有抽象方法, 最終類能夠沒有最終方法

最終類不能被繼承, 最終方法不能被重寫(能夠重載)

8.異常

相關的關鍵字 throw、throws、try...catch、finally

  • throws 用在方法簽名上, 以便拋出的異常能夠被調用者處理
  • throw 方法內部經過throw拋出異常
  • try 用於檢測包住的語句塊, 如有異常, catch子句捕獲並執行catch塊

9. 關於finally

  • finally無論有沒有異常都要處理
  • 當try和catch中有return時,finally仍然會執行,finally比return先執行
  • 無論有木有異常拋出, finally在return返回前執行
  • finally是在return後面的表達式運算後執行的(此時並無返回運算後的值,而是先把要返回的值保存起來,管finally中的代碼怎麼樣,返回的值都不會改變,仍然是以前保存的值),因此函數返回值是在finally執行前肯定的

注意:finally中最好不要包含return,不然程序會提早退出,返回值不是try或catch中保存的返回值

finally不執行的幾種狀況:程序提早終止如調用了System.exit, 病毒,斷電

10. 受檢查異常和運行時異常

10.1 粉紅色的是受檢查的異常(checked exceptions),其必須被try...catch語句塊所捕獲, 或者在方法簽名裏經過throws子句聲明。受檢查的異常必須在編譯時被捕捉處理,命名爲Checked Exception是由於Java編譯器要進行檢查, Java虛擬機也要進行檢查, 以確保這個規則獲得遵照。

常見的checked exception:ClassNotFoundException IOException FileNotFoundException EOFException

10.2 綠色的異常是運行時異常(runtime exceptions), 須要程序員本身分析代碼決定是否捕獲和處理,好比空指針,被0除...

常見的runtime exception:NullPointerException ArithmeticException ClassCastException IllegalArgumentException IllegalStateException IndexOutOfBoundsException NoSuchElementException

10.3 而聲明爲Error的,則屬於嚴重錯誤,如系統崩潰、虛擬機錯誤、動態連接失敗等,這些錯誤沒法恢復或者不可能捕捉,將致使應用程序中斷,Error不須要捕獲。

11. this & super

11.1 super出如今父類的子類中。有三種存在方式

  1. super.xxx(xxx爲變量名或對象名)意思是獲取父類中xxx的變量或引用
  2. super.xxx(); (xxx爲方法名)意思是直接訪問並調用父類中的方法
  3. super() 調用父類構造

注:super只能指代其直接父類

11.2 this() & super()在構造方法中的區別

  1. 調用super()必須寫在子類構造方法的第一行, 不然編譯不經過
  2. super從子類調用父類構造, this在同一類中調用其餘構造
  3. 均須要放在第一行
  4. 儘管能夠用this調用一個構造器, 卻不能調用2個
  5. this和super不能出如今同一個構造器中, 不然編譯不經過
  6. this()、super()都指的對象,不能夠在static環境中使用
  7. 本質this指向本對象的指針。super是一個關鍵字

12. 修飾符一覽

修飾符             類內部      同一個包        子類         任何地方
private         yes
default         yes            yes
protected        yes            yes                yes
public            yes            yes                yes            yes複製代碼

13. 內部類和靜態內部類

public class Enclosingone {
    public class Insideone {}
    public static class Insideone{}
}

public class Test {
    public static void main(String[] args) {
    // 構造內部類對象須要外部類的引用
    Enclosingone.Insideone obj1 = new Enclosingone().new Insideone();
    // 構造靜態內部類的對象
    Enclosingone.Insideone obj2 = new Enclosingone.Insideone();
    }
}複製代碼

靜態內部類不須要有指向外部類的引用。但非靜態內部類須要持有對外部類的引用。非靜態內部類可以訪問外部類的靜態和非靜態成員。靜態內部類不能訪問外部類的非靜態成員,只能訪問外部類的靜態成員。

14. 序列化

聲明爲static和transient類型的數據不能被序列化, 反序列化須要一個無參構造函數

序列化參見個人筆記Java-note-序列化.md

15.正則表達式

次數符號

* 0或屢次
+ 1或屢次
?0或1次
{n} 恰n次
{n,m} 從n到m次複製代碼

其餘符號

符號 等價形式

\d        [0-9]
\D      [^0-9]  
\w         [a-zA-Z_0-9]
\W         [^a-zA-Z_0-9]
\s         [\t\n\r\f]
\S         [^\t\n\r\f]
.         任何字符複製代碼

邊界匹配器

行開頭 ^行結尾 $單詞邊界 b

貪婪模式:最大長度匹配 非貪婪模式:匹配到結果就好,最短匹配

環視

字符                 描述                     匹配對象
.                    單個任意字符            
[...]                 字符組                     列出的任意字符
[^...]                                         未列出的任意字符
^                     caret                     行的起始位置
$                     dollar                     行的結束位置
\<                                           單詞的起始位置
\>                                             單詞的結束位置
\b                   單詞邊界
\B                     非單詞邊界
(?=Expression)        順序確定環視            成功,若是右邊可以匹配
(?!Expression)        順序否認環視            成功,若是右邊不可以匹配
(?<=Expression)        逆序確定環視            成功,若是左邊可以匹配
(?<!Expression)     逆序否認環視            成功,若是左邊不可以匹配複製代碼

舉例:北京市(海淀區)(朝陽區)(西城區)

Regex: .*(?=\()

模式和匹配器的典型調用次序

  1. 把正則表達式編譯到模式中
    Pattern p = Pattern.compile("a*b");
  2. 建立給定輸入與此模式的匹配器
    Matcher m = p.matcher("aaab");
  3. 嘗試將整個區域與此模式匹配
    boolean b = m.matches();

16. 面向對象的五大基本原則(solid)

  1. S單一職責SRP:Single-Responsibility Principle
    一個類,最好只作一件事,只有一個引發它的變化。單一職責原則能夠看作是低耦合,高內聚在面向對象原則的引伸,將職責定義爲引發變化的緣由,以提升內聚性減小引發變化的緣由。
  2. O開放封閉原則OCP:Open-Closed Principle
    軟件實體應該是可擴展的,而不是可修改的。對擴展開放,對修改封閉
  3. L里氏替換原則LSP:Liskov-Substitution Principle
    子類必須可以替換其基類。這一思想表現爲對繼承機制的約束規範,只有子類可以替換其基類時,纔可以保證系統在運行期內識別子類,這是保證繼承複用的基礎。
  4. I接口隔離原則ISP:Interface-Segregation Principle
    使用多個小的接口,而不是一個大的總接口
  5. D依賴倒置原則DIP:Dependency-Inversion Principle
    依賴於抽象。具體而言就是高層模塊不依賴於底層模塊,兩者共同依賴於抽象。抽象不依賴於具體,具體依賴於抽象。

17. 面向對象設計其餘原則

  1. 封裝變化
  2. 少用繼承 多用組合
  3. 針對接口編程 不針對實現編程
  4. 爲交互對象之間的鬆耦合設計而努力
  5. 類應該對擴展開發 對修改封閉(開閉OCP原則)
  6. 依賴抽象,不要依賴於具體類(依賴倒置DIP原則)
  7. 密友原則:只和朋友交談(最少知識原則,迪米特法則)

說明:一個對象應當對其餘對象有儘量少的瞭解,將方法調用保持在界限內,只調用屬於如下範圍的方法:該對象自己(本地方法)對象的組件 被看成方法參數傳進來的對象 此方法建立或實例化的任何對象

  1. 別找我(調用我) 我會找你(調用你)(好萊塢原則)
  2. 一個類只有一個引發它變化的緣由(單一職責SRP原則)

18. null能夠被強制轉型爲任意類型的對象

19.代碼執行次序

  1. 多個靜態成員變量, 靜態代碼塊按順序執行
  2. 單個類中: 靜態代碼 -> main方法 -> 構造塊 -> 構造方法
  3. 構造塊在每一次建立對象時執行
  4. 涉及父類和子類的初始化過程
    a.初始化父類中的靜態成員變量和靜態代碼塊
    b.初始化子類中的靜態成員變量和靜態代碼塊
    c.初始化父類的普通成員變量和構造代碼塊(按次序),再執行父類的構造方法(注意父類構造方法中的子類方法覆蓋)
    d.初始化子類的普通成員變量和構造代碼塊(按次序),再執行子類的構造方法

20. 數組複製方法

  1. for逐一複製
  2. System.arraycopy() -> 效率最高native方法
  3. Arrays.copyOf() -> 本質調用arraycopy
  4. clone方法 -> 返回Object[],須要強制類型轉換

21. 多態

  1. Java經過方法重寫和方法重載實現多態
  2. 方法重寫是指子類重寫了父類的同名方法
  3. 方法重載是指在同一個類中,方法的名字相同,可是參數列表不一樣

22. Java文件

java文件能夠包含多個類,惟一的限制就是:一個文件中只能有一個public類, 而且此public類必須與文件名相同。並且這些類和寫在多個文件中沒有區別。

23. Java移位運算符

java中有三種移位運算符

  1. << :左移運算符,x << 1,至關於x乘以2(不溢出的狀況下),低位補0
  2. >> :帶符號右移,x >> 1,至關於x除以2,正數高位補0,負數高位補1
  3. >>> :無符號右移,忽略符號位,空位都以0補齊

參見個人GitHub,Java移位符

24. 形參&實參

  1. 形式參數可被視爲local variable.形參和局部變量同樣都不能離開方法。只有在方法中使用,不會在方法外可見。
  2. 形式參數只能用final修飾符,其它任何修飾符都會引發編譯器錯誤。可是用這個修飾符也有必定的限制,就是在方法中不能對參數作任何修改。不過通常狀況下,一個方法的形參不用final修飾。只有在特殊狀況下,那就是:方法內部類。一個方法內的內部類若是使用了這個方法的參數或者局部變量的話,這個參數或局部變量應該是final。
  3. 形參的值在調用時根據調用者更改,實參則用自身的值更改形參的值(指針、引用皆在此列),也就是說真正被傳遞的是實參。

25. IO流一覽

26. 局部變量爲何要初始化

局部變量是指類方法中的變量,必須初始化。局部變量運行時被分配在棧中,量大,生命週期短,若是虛擬機給每一個局部變量都初始化一下,是一筆很大的開銷,但變量不初始化爲默認值就使用是不安全的。出於速度和安全性兩個方面的綜合考慮,解決方案就是虛擬機不初始化,但要求編寫者必定要在使用前給變量賦值。

27. Java語言的魯棒性

Java在編譯和運行程序時,都要對可能出現的問題進行檢查,以消除錯誤的產生。它提供自動垃圾收集來進行內存管理,防止程序員在管理內存時容易產生的錯誤。經過集成的面向對象的例外處理機制,在編譯時,Java揭示出可能出現但未被處理的異常,幫助程序員正確地進行選擇以防止系統的崩潰。另外,Java在編譯時還可捕獲類型聲明中的許多常見錯誤,防止動態運行時不匹配問題的出現。

28. Java語言特性

  1. Java致力於檢查程序在編譯和運行時的錯誤
  2. Java虛擬機實現了跨平臺接口
  3. 類型檢查幫助檢查出許多開發早期出現的錯誤
  4. Java本身操縱內存減小了內存出錯的可能性
  5. Java還實現了真數組,避免了覆蓋數據的可能

29. 包裝類的equals()方法不處理數據轉型,必須類型和值都同樣才相等。

30. 子類能夠繼承父類的靜態方法!可是不能覆蓋。由於靜態方法是在編譯時肯定了,不能多態,也就是不能運行時綁定。

31. Java語法糖

  1. Java7的switch用字符串 - hashcode方法 switch用於enum枚舉
  2. 僞泛型 - List 原始類型
  3. 自動裝箱拆箱 - Integer.valueOf和Integer.intValue
  4. foreach遍歷 - Iterator迭代器實現
  5. 條件編譯
  6. enum枚舉類、內部類
  7. 可變參數 - 數組
  8. 斷言語言
  9. try語句中定義和關閉資源

32. Java 中應該使用什麼數據類型來表明價格?

若是不是特別關心內存和性能的話,使用BigDecimal,不然使用預約義精度的 double 類型。

33. 怎麼將 byte 轉換爲 String?

可使用 String 接收 byte[] 參數的構造器來進行轉換,須要注意的點是要使用的正確的編碼,不然會使用平臺默認編碼,這個編碼可能跟原來的編碼相同,也可能不一樣。

34. Java 中怎樣將 bytes 轉換爲 long 類型?

String接收bytes的構造器轉成String,再Long.parseLong

35. 咱們能將 int 強制轉換爲 byte 類型的變量嗎?若是該值大於 byte 類型的範圍,將會出現什麼現象?

是的,咱們能夠作強制轉換,可是 Java 中 int 是 32 位的,而 byte 是 8 位的,因此,若是強制轉化是,int 類型的高 24 位將會被丟棄,byte 類型的範圍是從 -128 到 127。

36. 存在兩個類,B 繼承 A,C 繼承 B,咱們能將 B 轉換爲 C 麼?如 C = (C) B;

能夠,向下轉型。可是不建議使用,容易出現類型轉型異常.

37. 哪一個類包含 clone 方法?是 Cloneable 仍是 Object?

java.lang.Cloneable 是一個標示性接口,不包含任何方法,clone 方法在 Object 類中定義。而且須要知道 clone() 方法是一個本地方法,這意味着它是由 c 或 c++ 或 其餘本地語言實現的。

38. Java 中 ++ 操做符是線程安全的嗎?

不是線程安全的操做。它涉及到多個指令,如讀取變量值,增長,而後存儲回內存,這個過程可能會出現多個線程交差。還會存在競態條件(讀取-修改-寫入)。

39. a = a + b 與 a += b 的區別

+= 隱式的將加操做的結果類型強制轉換爲持有結果的類型。若是兩這個整型相加,如 byte、short 或者 int,首先會將它們提高到 int 類型,而後在執行加法操做。

byte a = 127;
byte b = 127;
b = a + b; // error : cannot convert from int to byte
b += a; // ok
複製代碼

(由於 a+b 操做會將 a、b 提高爲 int 類型,因此將 int 類型賦值給 byte 就會編譯出錯)

40. 我能在不進行強制轉換的狀況下將一個 double 值賦值給 long 類型的變量嗎?

不行,你不能在沒有強制類型轉換的前提下將一個 double 值賦值給 long 類型的變量,由於 double 類型的範圍比 long 類型更廣,因此必需要進行強制轉換。

41. 3*0.1 == 0.3 將會返回什麼?true 仍是 false?

false,由於有些浮點數不能徹底精確的表示出來。

42. int 和 Integer 哪一個會佔用更多的內存?

Integer 對象會佔用更多的內存。Integer 是一個對象,須要存儲對象的元數據。可是 int 是一個原始類型的數據,因此佔用的空間更少。

43. 爲何 Java 中的 String 是不可變的(Immutable)?

Java 中的 String 不可變是由於 Java 的設計者認爲字符串使用很是頻繁,將字符串設置爲不可變能夠容許多個客戶端之間共享相同的字符串。

44. 咱們能在 Switch 中使用 String 嗎?

從 Java 7 開始,咱們能夠在 switch case 中使用字符串,但這僅僅是一個語法糖。內部實如今 switch 中使用字符串的 hash code。

45. Java 中的構造器鏈是什麼?

當你從一個構造器中調用另外一個構造器,就是Java 中的構造器鏈。這種狀況只在重載了類的構造器的時候纔會出現。

46. 枚舉類

JDK1.5出現 每一個枚舉值都須要調用一次構造函數。

48. 什麼是不可變對象(immutable object)?Java 中怎麼建立一個不可變對象?

不可變對象指對象一旦被建立,狀態就不能再改變。任何修改都會建立一個新的對象,如 String、Integer及其它包裝類。

如何在Java中寫出Immutable的類?

要寫出這樣的類,須要遵循如下幾個原則:

1)immutable對象的狀態在建立以後就不能發生改變,任何對它的改變都應該產生一個新的對象。

2)Immutable類的全部的屬性都應該是final的。

3)對象必須被正確的建立,好比:對象引用在對象建立過程當中不能泄露(leak)。

4)對象應該是final的,以此來限制子類繼承父類,以免子類改變了父類的immutable特性。

5)若是類中包含mutable類對象,那麼返回給客戶端的時候,返回該對象的一個拷貝,而不是該對象自己(該條能夠歸爲第一條中的一個特例)

49. 咱們能建立一個包含可變對象的不可變對象嗎?

是的,咱們是能夠建立一個包含可變對象的不可變對象的,你只須要謹慎一點,不要共享可變對象的引用就能夠了,若是須要變化時,就返回原對象的一個拷貝。最多見的例子就是對象中包含一個日期對象的引用。

50. List和Set

List 是一個有序集合,容許元素重複。它的某些實現能夠提供基於下標值的常量訪問時間,可是這不是 List 接口保證的。Set 是一個無序集合。

51. poll() 方法和 remove() 方法的區別?

poll() 和 remove() 都是從隊列中取出一個元素,可是 poll() 在獲取元素失敗的時候會返回空,可是 remove() 失敗的時候會拋出異常。

52. Java 中 LinkedHashMap 和 PriorityQueue 的區別是什麼?

PriorityQueue 保證最高或者最低優先級的的元素老是在隊列頭部,可是 LinkedHashMap 維持的順序是元素插入的順序。當遍歷一個 PriorityQueue 時,沒有任何順序保證,可是 LinkedHashMap 課保證遍歷順序是元素插入的順序。

53. ArrayList 與 LinkedList 的區別?

最明顯的區別是 ArrrayList 底層的數據結構是數組,支持隨機訪問,而 LinkedList 的底層數據結構書鏈表,不支持隨機訪問。使用下標訪問一個元素,ArrayList 的時間複雜度是 O(1),而 LinkedList 是 O(n)。

54. 用哪兩種方式來實現集合的排序?

你可使用有序集合,如 TreeSet 或 TreeMap,你也可使用有順序的的集合,如 List,而後經過 Collections.sort() 來排序。

55. Java 中怎麼打印數組?

你可使用 Arrays.toString() 和 Arrays.deepToString() 方法來打印數組。因爲數組沒有實現 toString() 方法,因此若是將數組傳遞給 System.out.println() 方法,將沒法打印出數組的內容,可是 Arrays.toString() 能夠打印每一個元素。

56. Java 中的 LinkedList 是單向鏈表仍是雙向鏈表?

是雙向鏈表,你能夠檢查 JDK 的源碼。在 Eclipse,你可使用快捷鍵 Ctrl + T,直接在編輯器中打開該類。

57. Java 中的 TreeMap 是採用什麼樹實現的?

Java 中的 TreeMap 是使用紅黑樹實現的。

58. Java 中的 HashSet,內部是如何工做的?

HashSet 的內部採用 HashMap來實現。因爲 Map 須要 key 和 value,因此全部 key 的都有一個默認 value。相似於 HashMap,HashSet 不容許重複的 key,只容許有一個null key,意思就是 HashSet 中只容許存儲一個 null 對象。

59. 寫一段代碼在遍歷 ArrayList 時移除一個元素?

該問題的關鍵在於面試者使用的是 ArrayList 的 remove() 仍是 Iterator 的 remove()方法。後者是正確的方式不會出現 ConcurrentModificationException 異常。

60. 咱們能本身寫一個容器類,而後使用 for-each 循環嗎?

能夠,你能夠寫一個本身的容器類。若是你想使用 Java 中加強的循環來遍歷,你只須要實現 Iterable 接口。若是你實現 Collection 接口,默認就具備該屬性。

61. ArrayList 和 HashMap 的默認大小是多數?

在 Java 7 中,ArrayList 的默認大小是 10 個元素,HashMap 的默認大小是16個元素(必須是2的冪)。這就是 Java 7 中 ArrayList 和 HashMap 類的代碼片斷:

// from ArrayList.java JDK 1.7
private static final int DEFAULT_CAPACITY = 10;
 
//from HashMap.java JDK 7
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // 16複製代碼

62. 有沒有可能兩個不相等的對象有有相同的 hashcode?

有可能,兩個不相等的對象可能會有相同的 hashcode 值,這就是爲何在 hashmap 中會有衝突。相等 hashcode 值的規定只是說若是兩個對象相等,必須有相同的hashcode 值,可是沒有關於不相等對象的任何規定。

63. 兩個相同的對象會有不一樣的的 hash code 嗎?

不能,根據 hash code 的規定,這是不可能的。

64. 咱們能夠在 hashcode() 中使用隨機數字嗎?

不行,由於對象的 hashcode 值必須是相同的。

65. Java 中,Comparator 與 Comparable 有什麼不一樣?

Comparable 接口用於定義對象的天然順序,而 comparator 一般用於定義用戶定製的順序。Comparable 老是隻有一個,可是能夠有多個 comparator 來定義對象的順序。

66. 爲何在重寫 equals 方法的時候須要重寫 hashCode 方法?

由於有強制的規範指定須要同時重寫 hashcode 與 equal 方法,許多容器類,如 HashMap、HashSet 都依賴於 hashcode 與 equals 的規定。

67. 「a==b」和」a.equals(b)」有什麼區別?

若是 a 和 b 都是對象,則 a==b 是比較兩個對象的引用,只有當 a 和 b 指向的是堆中的同一個對象纔會返回 true,而 a.equals(b) 是進行邏輯比較,因此一般須要重寫該方法來提供邏輯一致性的比較。例如,String 類重寫 equals() 方法,因此能夠用於兩個不一樣對象,可是包含的字母相同的比較。

68. a.hashCode() 有什麼用?與 a.equals(b) 有什麼關係?

簡介:hashCode() 方法是相應對象整型的 hash 值。它經常使用於基於 hash 的集合類,如 Hashtable、HashMap、LinkedHashMap等等。它與 equals() 方法關係特別緊密。根據 Java 規範,兩個使用 equal() 方法來判斷相等的對象,必須具備相同的 hash code。

一、hashcode的做用

List和Set,如何保證Set不重複呢?經過迭代使用equals方法來判斷,數據量小還能夠接受,數據量大怎麼解決?引入hashcode,實際上hashcode扮演的角色就是尋址,大大減小查詢匹配次數。

二、hashcode重要嗎

對於數組、List集合就是一個累贅。而對於HashMap, HashSet, Hashtable就異常重要了。

三、equals方法遵循的原則

  • 對稱性 若x.equals(y)true,則y.equals(x)true
  • 自反性 x.equals(x)必須true
  • 傳遞性 若x.equals(y)true,y.equals(z)true,則x.equals(z)必爲true
  • 一致性 只要x,y內容不變,不管調用多少次結果不變
  • 其餘 x.equals(null) 永遠false,x.equals(和x數據類型不一樣)始終false

二者的關係

69. final、finalize 和 finally 的不一樣之處?

final 是一個修飾符,能夠修飾變量、方法和類。若是 final 修飾變量,意味着該變量的值在初始化後不能被改變。Java 技術容許使用 finalize() 方法在垃圾收集器將對象從內存中清除出去以前作必要的清理工做。這個方法是由垃圾收集器在肯定這個對象沒有被引用時對這個對象調用的,可是何時調用 finalize 沒有保證。finally 是一個關鍵字,與 try 和 catch 一塊兒用於異常的處理。finally 塊必定會被執行,不管在 try 塊中是否有發生異常。

70. Java 中的編譯期常量是什麼?使用它又什麼風險?

變量也就是咱們所說的編譯期常量,這裏的 public 可選的。實際上這些變量在編譯時會被替換掉,由於編譯器知道這些變量的值,而且知道這些變量在運行時不能改變。這種方式存在的一個問題是你使用了一個內部的或第三方庫中的公有編譯時常量,可是這個值後面被其餘人改變了,可是你的客戶端仍然在使用老的值,甚至你已經部署了一個新的jar。爲了不這種狀況,當你在更新依賴 JAR 文件時,確保從新編譯你的程序。

71. 說出幾點 Java 中使用 Collections 的最佳實踐

這是我在使用 Java 中 Collectionc 類的一些最佳實踐:

a)使用正確的集合類,例如,若是不須要同步列表,使用 ArrayList 而不是 Vector。

b)優先使用併發集合,而不是對集合進行同步。併發集合提供更好的可擴展性。

c)使用接口表明和訪問集合,如使用List存儲 ArrayList,使用 Map 存儲 HashMap 等等。

d)使用迭代器來循環集合。

e)使用集合的時候使用泛型。

72. 靜態內部類與頂級類有什麼區別?

一個公共的頂級類的源文件名稱與類名相同,而嵌套靜態類沒有這個要求。一個嵌套類位於頂級類內部,須要使用頂級類的名稱來引用嵌套靜態類,如 HashMap.Entry 是一個嵌套靜態類,HashMap 是一個頂級類,Entry是一個嵌套靜態類。

73. Java 中,Serializable 與 Externalizable 的區別?

Serializable 接口是一個序列化 Java 類的接口,以便於它們能夠在網絡上傳輸或者能夠將它們的狀態保存在磁盤上,是 JVM 內嵌的默認序列化方式,成本高、脆弱並且不安全。Externalizable 容許你控制整個序列化過程,指定特定的二進制格式,增長安全機制。

74. 說出 JDK 1.7 中的三個新特性?

雖然 JDK 1.7 不像 JDK 5 和 8 同樣的大版本,可是,仍是有不少新的特性,如 try-with-resource 語句,這樣你在使用流或者資源的時候,就不須要手動關閉,Java 會自動關閉。Fork-Join 池某種程度上實現 Java 版的 Map-reduce。容許 Switch 中有 String 變量和文本。菱形操做符(<>)用於泛型推斷,再也不須要在變量聲明的右邊申明泛型,所以能夠寫出可讀寫更強、更簡潔的代碼。另外一個值得一提的特性是改善異常處理,如容許在同一個 catch 塊中捕獲多個異常。

75. 說出 5 個 JDK 1.8 引入的新特性?

Java 8 在 Java 歷史上是一個開創新的版本,下面 JDK 8 中 5 個主要的特性:Lambda 表達式,容許像對象同樣傳遞匿名函數Stream API,充分利用現代多核 CPU,能夠寫出很簡潔的代碼Date 與 Time API,最終,有一個穩定、簡單的日期和時間庫可供你使用擴展方法,如今,接口中能夠有靜態、默認方法。重複註解,如今你能夠將相同的註解在同一類型上使用屢次。

下述包含 Java 面試過程當中關於 SOLID 的設計原則,OOP 基礎,如類,對象,接口,繼承,多態,封裝,抽象以及更高級的一些概念,如組合、聚合及關聯。也包含了 GOF 設計模式的問題。

76. 接口是什麼?爲何要使用接口而不是直接使用具體類?

接口用於定義 API。它定義了類必須得遵循的規則。同時,它提供了一種抽象,由於客戶端只使用接口,這樣能夠有多重實現,如 List 接口,你可使用可隨機訪問的 ArrayList,也可使用方便插入和刪除的 LinkedList。接口中不容許普通方法,以此來保證抽象,可是 Java 8 中你能夠在接口聲明靜態方法和默認普通方法。

77. Java 中,抽象類與接口之間有什麼不一樣?

Java 中,抽象類和接口有不少不一樣之處,可是最重要的一個是 Java 中限制一個類只能繼承一個類,可是能夠實現多個接口。抽象類能夠很好的定義一個家族類的默認行爲,而接口能更好的定義類型,有助於後面實現多態機制參見第六條。

78. 除了單例模式,你在生產環境中還用過什麼設計模式?

這須要根據你的經驗來回答。通常狀況下,你能夠說依賴注入,工廠模式,裝飾模式或者觀察者模式,隨意選擇你使用過的一種便可。不過你要準備回答接下的基於你選擇的模式的問題。

79. 你能解釋一下里氏替換原則嗎?

嚴格定義:若是對每個類型爲S的對象o1,都有類型爲T的對象o2,使得以T定義的全部程序P在全部的對象用o1替換o2時,程序P的行爲沒有變化,那麼類型S是類型T的子類型。

通俗表述:全部引用基類(父類)的地方必須能透明地使用其子類的對象。也就是說子類能夠擴展父類的功能,但不能改變父類原有的功能。它包含如下4層含義:

  1. 子類能夠實現父類的抽象方法,但不能覆蓋父類的非抽象方法。
  2. 子類中能夠增長本身特有的方法。
  3. 當子類的方法重載父類的方法時,方法的前置條件(即方法的形參)要比父類方法的輸入參數更寬鬆。
  4. 當子類的方法實現父類的抽象方法時,方法的後置條件(即方法的返回值)要比父類更嚴格。

80.什麼狀況下會違反迪米特法則?爲何會有這個問題?

迪米特法則建議「只和朋友說話,不要陌生人說話」,以此來減小類之間的耦合。

81. 適配器模式是什麼?何時使用?

適配器模式提供對接口的轉換。若是你的客戶端使用某些接口,可是你有另一些接口,你就能夠寫一個適配去來鏈接這些接口。

82. 構造器注入和 setter 依賴注入,那種方式更好?

每種方式都有它的缺點和優勢。構造器注入保證全部的注入都被初始化,可是 setter 注入提供更好的靈活性來設置可選依賴。若是使用 XML 來描述依賴,Setter 注入的可讀寫會更強。經驗法則是強制依賴使用構造器注入,可選依賴使用 setter 注入。

83. 依賴注入和工廠模式之間有什麼不一樣?

雖然兩種模式都是將對象的建立從應用的邏輯中分離,可是依賴注入比工程模式更清晰。經過依賴注入,你的類就是 POJO,它只知道依賴而不關心它們怎麼獲取。使用工廠模式,你的類須要經過工廠來獲取依賴。所以,使用 DI 會比使用工廠模式更容易測試。

84. 適配器模式和裝飾器模式有什麼區別?

雖然適配器模式和裝飾器模式的結構相似,可是每種模式的出現意圖不一樣。適配器模式被用於橋接兩個接口,而裝飾模式的目的是在不修改類的狀況下給類增長新的功能。

85. 適配器模式和代理模式以前有什麼不一樣?

這個問題與前面的相似,適配器模式和代理模式的區別在於他們的意圖不一樣。因爲適配器模式和代理模式都是封裝真正執行動做的類,所以結構是一致的,可是適配器模式用於接口之間的轉換,而代理模式則是增長一個額外的中間層,以便支持分配、控制或智能訪問。

86. 什麼是模板方法模式?

模板方法提供算法的框架,你能夠本身去配置或定義步驟。例如,你能夠將排序算法看作是一個模板。它定義了排序的步驟,可是具體的比較,可使用 Comparable 或者其語言中相似東西,具體策略由你去配置。列出算法概要的方法就是衆所周知的模板方法。

87. 何時使用訪問者模式?

訪問者模式用於解決在類的繼承層次上增長操做,可是不直接與之關聯。這種模式採用雙派發的形式來增長中間層。

88. 何時使用組合模式?

組合模式使用樹結構來展現部分與總體繼承關係。它容許客戶端採用統一的形式來對待單個對象和對象容器。當你想要展現對象這種部分與總體的繼承關係時採用組合模式。

89. 繼承和組合之間有什麼不一樣?

雖然兩種均可以實現代碼複用,可是組合比繼承共靈活,由於組合容許你在運行時選擇不一樣的實現。用組合實現的代碼也比繼承測試起來更加簡單。

90. 描述 Java 中的重載和重寫?

重載和重寫都容許你用相同的名稱來實現不一樣的功能,可是重載是編譯時活動,而重寫是運行時活動。你能夠在同一個類中重載方法,可是隻能在子類中重寫方法。重寫必需要有繼承。

91. OOP 中的 組合、聚合和關聯有什麼區別?

若是兩個對象彼此有關係,就說他們是彼此相關聯的。組合和聚合是面向對象中的兩種形式的關聯。組合是一種比聚合更強力的關聯。組合中,一個對象是另外一個的擁有者,而聚合則是指一個對象使用另外一個對象。若是對象 A 是由對象 B 組合的,則 A 不存在的話,B必定不存在,可是若是 A 對象聚合了一個對象 B,則即便 A 不存在了,B 也能夠單獨存在。

92. 給我一個符合開閉原則的設計模式的例子?

開閉原則要求你的代碼對擴展開放,對修改關閉。這個意思就是說,若是你想增長一個新的功能,你能夠很容易的在不改變已測試過的代碼的前提下增長新的代碼。有好幾個設計模式是基於開閉原則的,如策略模式,若是你須要一個新的策略,只須要實現接口,增長配置,不須要改變核心邏輯。一個正在工做的例子是 Collections.sort() 方法,這就是基於策略模式,遵循開閉原則的,你不需爲新的對象修改 sort() 方法,你須要作的僅僅是實現你本身的 Comparator 接口。

93. 何時使用享元模式(蠅量模式)?

享元模式經過共享對象來避免建立太多的對象。爲了使用享元模式,你須要確保你的對象是不可變的,這樣你才能安全的共享。JDK 中 String 池、Integer 池以及 Long 池都是很好的使用了享元模式的例子。

94. Java 中如何格式化一個日期?如格式化爲 ddMMyyyy 的形式?

Java 中,可使用 SimpleDateFormat 類或者 joda-time 庫來格式日期。DateFormat 類容許你使用多種流行的格式來格式化日期。

95. Java 中,怎麼在格式化的日期中顯示時區?

pattern中加z yyyy-MM-dd HH:mm:ss.SSS Z

96. Java 中 java.util.Date 與 java.sql.Date 有什麼區別?

java.sql.Date是針對SQL語句使用的,它只包含日期而沒有時間部分,它們都有getTime方法返回毫秒數,天然就能夠直接構建。java.util.Date 是 java.sql.Date 的父類,前者是經常使用的表示時間的類,咱們一般格式化或者獲得當前時間都是用他,後者以後在讀寫數據庫的時候用他,由於PreparedStament的setDate()的第2參數和ResultSet的getDate()方法的第2個參數都是java.sql.Date。

97. Java 中,如何計算兩個日期之間的差距?

public static int dateDiff(Date d1, Date d2) throws Exception {
long n1 = d1.getTime();
long n2 = d2.getTime();
long diff = Math.abs(n1 - n2);

diff /= 3600 * 1000 * 24;
return diff;
}複製代碼

98. Java 中,如何將字符串 YYYYMMDD 轉換爲日期?

SimpleDateFormat的parse方法

99. 說出幾條 Java 中方法重載的最佳實踐?

下面有幾條能夠遵循的方法重載的最佳實踐來避免形成自動裝箱的混亂。

a)不要重載這樣的方法:一個方法接收 int 參數,而另個方法接收 Integer 參數。

b)不要重載參數數量一致,而只是參數順序不一樣的方法。

c)若是重載的方法參數個數多於 5 個,採用可變參數。

100. 說出 5 條 IO 的最佳實踐

IO 對 Java 應用的性能很是重要。理想狀況下,你應該在你應用的關鍵路徑上避免 IO 操做。下面是一些你應該遵循的 Java IO 最佳實踐:

a)使用有緩衝區的 IO 類,而不要單獨讀取字節或字符

b)使用 NIO 和 NIO2

c)在 finally 塊中關閉流,或者使用 try-with-resource(Java7) 語句

d)使用內存映射文件獲取更快的 IO

101. Object有哪些公用方法?

clone equals hashcode wait notify notifyall finalize toString getClass除了clone和finalize其餘均爲public方法。

11個方法,wait被重載了兩次

102. equals與==的區別

區別1. ==是一個運算符 equals是Object類的方法

區別2. 比較時的區別

a. 用於基本類型的變量比較時:==用於比較值是否相等,equals不能直接用於基本數據類型的比較,須要轉換爲其對應的包裝類型。b. 用於引用類型的比較時。==和equals都是比較棧內存中的地址是否相等 。相等爲true 不然爲false。可是一般會重寫equals方法去實現對象內容的比較。

103. String、StringBuffer與StringBuilder的區別

第一點:可變和適用範圍。String對象是不可變的,而StringBuffer和StringBuilder是可變字符序列。每次對String的操做至關於生成一個新的String對象,而對StringBuffer和StringBuilder的操做是對對象自己的操做,而不會生成新的對象,因此對於頻繁改變內容的字符串避免使用String,由於頻繁的生成對象將會對系統性能產生影響。

第二點:線程安全。String因爲有final修飾,是immutable的,安全性是簡單而純粹的。StringBuilder和StringBuffer的區別在於StringBuilder不保證同步,也就是說若是須要線程安全須要使用StringBuffer,不須要同步的StringBuilder效率更高。

104. switch可否用String作參數

Java1.7開始支持,但實際這是一顆Java語法糖。除此以外,byte,short,long,枚舉,boolean都可用於switch,只有浮點型不能夠。

105. 封裝、繼承、多態

封裝

1.概念:就是把對象的屬性和操做(或服務)結合爲一個獨立的總體,並儘量隱藏對象的內部實現細節。

2.好處:

(1)隱藏內部實現細節。

繼承

1.概念:繼承是從已有的類中派生出新的類,新的類能吸取已有類的數據屬性和行爲,並能擴展新的能力

2.好處:提升代碼的複用,縮短開發週期。

多態

1.概念:多態(Polymorphism)按字面的意思就是「多種狀態,即同一個實體同時具備多種形式。通常表現形式是程序在運行的過程當中,同一種類型在不一樣的條件下表現不一樣的結果。多態也稱爲動態綁定,通常是在運行時刻才能肯定方法的具體執行對象。

2.好處:

1)將接口和實現分開,改善代碼的組織結構和可讀性,還能建立可拓展的程序。

2)消除類型之間的耦合關係。容許將多個類型視爲同一個類型。

3)一個多態方法的調用容許有多種表現形式

106. Comparable和Comparator接口區別

Comparator位於包java.util下,而Comparable位於包java.lang下

若是咱們須要使用Arrays或Collections的排序方法對對象進行排序時,咱們須要在自定義類中實現Comparable接口並重寫compareTo方法,compareTo方法接收一個參數,若是this對象比傳遞的參數小,相等或大時分別返回負整數、0、正整數。Comparable被用來提供對象的天然排序。String、Integer實現了該接口。

Comparator比較器的compare方法接收2個參數,根據參數的比較大小分別返回負整數、0和正整數。Comparator 是一個外部的比較器,當這個對象天然排序不能知足你的要求時,你能夠寫一個比較器來完成兩個對象之間大小的比較。用 Comparator 是策略模式(strategy design pattern),就是不改變對象自身,而用一個策略對象(strategy object)來改變它的行爲。

107. 與Java集合框架相關的有哪些最好的實踐

(1)根據須要選擇正確的集合類型。好比,若是指定了大小,咱們會選用Array而非ArrayList。若是咱們想根據插入順序遍歷一個Map,咱們須要使用TreeMap。若是咱們不想重複,咱們應該使用Set。

(2)一些集合類容許指定初始容量,因此若是咱們可以估計到存儲元素的數量,咱們可使用它,就避免了從新哈希或大小調整。

(3)基於接口編程,而非基於實現編程,它容許咱們後來輕易地改變實現。

(4)老是使用類型安全的泛型,避免在運行時出現ClassCastException。

(5)使用JDK提供的不可變類做爲Map的key,能夠避免本身實現hashCode()和equals()。

108. IO和NIO簡述

一、簡述

在之前的Java IO中,都是阻塞式IO,NIO引入了非阻塞式IO。第一種方式:我從硬盤讀取數據,而後程序一直等,數據讀完後,繼續操做。這種方式是最簡單的,叫阻塞IO。第二種方式:我從硬盤讀取數據,而後程序繼續向下執行,等數據讀取完後,通知當前程序(對硬件來講叫中斷,對程序來講叫回調),而後此程序能夠當即處理數據,也能夠執行完當前操做在讀取數據。

2.流與塊的比較

原來的 I/O 以流的方式處理數據,而 NIO 以塊的方式處理數據。面向流 的 I/O 系統一次一個字節地處理數據。一個輸入流產生一個字節的數據,一個輸出流消費一個字節的數據。這樣作是相對簡單的。不利的一面是,面向流的 I/O 一般至關慢。一個 面向塊 的 I/O 系統以塊的形式處理數據。每個操做都在一步中產生或者消費一個數據塊。按塊處理數據比按(流式的)字節處理數據要快得多。可是面向塊的 I/O 缺乏一些面向流的 I/O 所具備的優雅性和簡單性。

3.通道與流

Channel是一個對象,能夠經過它讀取和寫入數據。通道與流功能相似,不一樣之處在於通道是雙向的。而流只是在一個方向上移動(一個流必須是 InputStream 或者 OutputStream 的子類), 而通道能夠用於讀、寫或者同時用於讀寫。

4.緩衝區Buffer

在 NIO 庫中,全部數據都是用緩衝區處理的。

Position: 表示下一次訪問的緩衝區位置
Limit: 表示當前緩衝區存放的數據容量。
Capacity:表示緩衝區最大容量
flip()方法:讀寫模式切換
clear方法:它將 limit 設置爲與 capacity 相同。它設置 position 爲 0。複製代碼

【感謝您能看完,若是可以幫到您,麻煩點個贊~】

更多經驗技術歡迎前來共同窗習交流:一點課堂-爲夢想而奮鬥的在線學習平臺 http://www.yidiankt.com/

![關注公衆號,回覆「1」免費領取-【java核心知識點】]file

QQ討論羣:616683098

QQ:3184402434

想要深刻學習的同窗們能夠加我QQ一塊兒學習討論~還有全套資源分享,經驗探討,等你哦!在這裏插入圖片描述

相關文章
相關標籤/搜索