- java基礎知識
- java的四個基本特性(封裝,繼承,多態,抽象)
- 封裝:數據和基於數據的操作封裝在一起,對外提供接口。
- 繼承:is-a 關係,子類繼承唯一父類,符合里氏替換原則
- 多態:子類對父類的方法做多種不同形式的響應,子類繼承父類,重寫父類的方法,父類引用子類對象
- 抽象:一類對象的共同特徵總結出來構造類的過程,比如動物類是貓和狗的抽象。
- 面向對象的6個原則
- 單一原則:一個類只負責一個責任
- 開放封閉:對擴展開放,對修改封閉
- 里氏替換:任何使用基類的地方都可以使用子類替換
- 接口隔離:接口力度最小化,對每個功能特別專一
- 依賴倒置:依賴於抽象不依賴於具體。面向接口編程
- 合成複用:優先使用合成或者複用的代碼
- (覆蓋,重寫)和重載
覆蓋,重寫:是java多態性的不同表現方式,子類對父類的方法進行重寫和覆蓋。
重載:函數方法名相同,返回值相同,參數的個數,類型,順序不同
重點!返回值類型可以相同也可以不相同,因爲java中調用函數並不需要強制賦值。
- Java泛型,及其意義
參數化類型,明確指定集合元素的數據類型,該集合只能保存指定類型的元素。意義:避免的數據類型的強制轉換導致的錯誤。
類型擦除:將泛型java代碼轉換爲普通java代碼,用頂級父類替換,移除類型參數
- Java訪問權限修飾符和訪問權限
Public:整個項目
Protected: 同一個類,同一個包,子類
default:同一個類,同一個包
Private: 同一個類
- Final與static
Final:聲明數據爲常量,不能被繼承,不能被子類修改(覆蓋)
Static:聲明變量爲靜態變量,在類第一次實例化時運行一次
初始化順序:父類(靜態變量、靜態初始化塊)→子類(靜態變量、靜態初始化塊)→父類(變量、初始化塊)→父類(構造器)→子類(變量、初始化塊)→子類(構造器)
- 抽象類和接口類的區別
方法:接口類中的必須是抽象的(不能寫具體方法過程),抽象類中可以沒有抽象方法
變量:接口類中的參數必須用final static修飾,必須被初始化,沒有常量與變量。抽象類中可以有普通成員。
子類:接口可以繼承多個父接口,抽象只能單繼承
- 8種基本數據類型
1字節(byte,boolean),2字節(char,Short),4直接(int,float),8字節(long,double)
強制類型裝換規則:①byte,short,char變量計算都會提升到int型,要強制轉換。②基本數據類型不能和boolean類型進行裝換③char類型裝換成高級類型會變成對應的ASCII④高級類型裝換成低級類型數據會丟失。
- String、StringBuffer和StringBuilder
可變不可變:string類型是不可變的(都會生成一個新的string對象,用+號鏈接字符串創建新對象),stringBuffer和StringBuilder是可變的。
線程安全:string和stringBuffer是線程安全的(同步鎖),stringBuilder是不安全
Final:都是final類型不能被繼承
初始化:stringBuffer和stringbuild都是用構造函數初始化,string可以用構造函數初始化也可以用賦值。
- Java和C++的區別
都是面嚮對象語言,支持封裝,繼承,多態
指針:java不提供指針來訪問內存,更安全,C++提供指針
繼承:java是單繼承,c++是多重繼承,java一個類實現多個接口
內存:java垃圾回收機制,不用管理內存的是用情況
- Object的通用方法
toString(),
finalize(),
clone(),
Equals(),hashCode()
Wait(),notify(),notifyAll()
getClass()
- JDK,JRE,JVM區別
JDK是java運行工具,包含JRE,
JRE:是java運行環境,提供了java程序的運行平臺,包含JVM
JVM:java虛擬機,提供內存管理和垃圾回收機制等
- JDK中常用的包
Java.net java.util java.io java.sql java.lang
- Equals與==的區別
“==”:比較基本數據類型的值,比較對象存放的內存地址
Equals:可以用來對複合數據類型的值做比較,也能比較對象存放的內存地址
- Super與this的區別
Super:訪問父類構造函數的父類方法,爲保證在子類可以訪問父類對象之前要完成對父類對象的初始化,必須要放在第一行
This:調用本類的構造函數,必須寫在第一行
- 異常
- Throwable是java語言中所有錯誤和異常的超類(萬物即可拋)。它有兩個子類:Error、Exception
- Error:Error爲錯誤,是程序無法處理的,如OutOfMemoryError、ThreadDeath等,出現這種情況你唯一能做的就是聽之任之,交由JVM來處理,不過JVM在大多數情況下會選擇終止線程。
- Exception:Exception是程序可以處理的異常
- 非檢查異常(unckecked exception):Error和RuntimeException以及他們的子類。javac在編譯時,不會提示和發現這樣的異常。這樣的異常發生的原因多半是代碼有問題。如:除0錯誤ArithmeticException,錯誤的強制類型轉換錯誤ClassCastException,數組索引越界ArrayIndexOutOfBoundsException,使用了空對象NullPointerException等等。
- 檢查異常(checked exception):SQLException異常,IOException異常,ClassNotFoundException異常。 javac強制要求程序員爲這樣的異常做預備處理工作(使用try…catch…finally或者throws),否則編譯不會通過。這樣的異常一般是由程序的運行環境導致的。
- 如果try語句裏面有return,返回的是try語句塊的變量值(返回值保存到局部變量->執行jsr指令跳到finally語句執行->執行完畢finally後,返回局部變量保存值);
- Finally塊中的return將覆蓋其他所有的return。
- Java的動態代理和反射機制
只要給定類的名字,就可以通過反射機制來獲得該類的所有信息。
-
- 在運行時判斷任意一個對象所屬的類;
- 在運行時構造任意一個類的對象;
- 在運行時判斷任意一個類所具有的成員變量和方法;
- 在運行時調用任意一個對象的方法;
- 生成動態代理:
代理的好處:①隱藏委託類的實現 ②在不修改委託類代碼的前提下對做一些額外的修改,實現解耦。
動態代理:代理類在程序運行時創建的代理方式被稱爲動態代理。 也就是說,這種情況下,代理類並不是在Java代碼中定義的,而是在運行時根據我們在Java代碼中的“指示”動態生成的。相比於靜態代理, 動態代理的優勢在於可以很方便的對代理類的函數進行統一的處理,而不用修改每個代理類的函數
Java動態代理是寫一個類實現InvocationHandler接口,重寫Invoke方法,在Invoke方法可以進行增強處理的邏輯的編寫,這個公共代理類在運行的時候才能明確自己要代理的對象,同時可以實現該被代理類的方法的實現,然後在實現類方法的時候可以進行增強處理。
- hashcode與equal區別
Equal:逐個比較,特別是像set這樣不能重複,用equal比較效率低下
Hashcode:實際上是返回對象的存儲地址,如果這個位置上沒有元素,就把元素直接存儲在上面,如果這個位置上已經存在元素,這個時候纔去調用equal方法與新元素進行比較,相同的話就不存了,散列到其他地址上。
- 集合專題
- 常見的集合有哪些
總的分爲Map接口與Collection接口
Map:HashMap,HashTable,concurrentHashMap,treeMap以及properties
Collection:分爲List 與 Set接口
Set接口:HashSet,TreeSet,LinkedHashSet
List接口:ArrayList,LinkedList,vector,stack
擴展:List是元素有序的,可以重複;Set是元素無序的,不可以重複
- HashMap底層實現?
數組+鏈表
計算key的hashCode值,然後對哈希碼再哈希(減少哈希衝突),然後把哈希碼和(數組長度-1)進行按位與操作,得到存儲的數組下標,如果該位置沒有鏈表節點,那麼直接把<key,value>的節點放入該位置。如果該位置又節點,就對鏈表進行遍歷,如果有相同的key則進行替換,否則插入鏈表表頭。
- HashMap的數組長度爲什麼是2的冪次方?
- 通過將key的hash值與length-1進行& 運算,實現了當前 Key 的定位,2 的冪次方可以減少衝突(碰撞)的次數,提高 HashMap 查詢效率(length=2n);
- 如果 length 爲 2 的次冪 則 length-1 轉化爲二進制必定是 11111……的形式,在於 h 的二進制與操作效率會非常的快,而且空間不浪費;
- HashMap和Hashtable的區別有哪些?
線程安全:HashMap沒有考慮同步是線程不安全的,HashTable是線程安全的
關鍵字:HashMap允許null作爲鍵(一個)值(多個),HashTable不允許null作爲鍵值。Get()方法返回null值,既可以表示hashmap中沒有該鍵,也可以表示該鍵對應的值爲null。所以hashmap用containsKey()判斷是否存儲某個鍵。
大小:hashmap中數組的默認大小是16,擴容後是之前數組的2倍。Hashtable默認大小11,擴容後是之前數組的2倍+1.
- ConcurrentHashMap和Hashtable的區別?
concurrentHashMap結合了hashMap和 hashTable的優勢,是線程安全的且不允許null作爲鍵和值。
concurrentHashMap應用了分段鎖機制,分成16段,每次get,put,remove只鎖當前用到的段。
hashTable是鎖住整個結構
ConcurrentHashMap 的具體實現知道嗎
該類包含兩個靜態內部類 HashEntry 和 Segment;前者用來封裝映射表的鍵值對,後者用來充當鎖的角色;
Segment 是一種可重入的鎖 ReentrantLock,每個 Segment 守護一個 HashEntry 數組裏得元素,當對 HashEntry 數組的數據進行修改時,必須首先獲得對應的 Segment 鎖。
- HashMap和HashSet的區別?
HashMap |
HashSet |
實現了Map接口 |
實現Set接口 |
存儲鍵值對 |
僅存儲對象
|
調用put()向map中添加元素 |
調用add()方法向Set中添加元素
|
HashMap使用鍵(Key)計算Hashcode
|
HashSet使用成員對象來計算hashcode值, 對於兩個對象來說hashcode可能相同, 所以equals()方法用來判斷對象的相等性, 如果兩個對象不同的話,那麼返回false |
HashMap相對於HashSet較快,因爲它是使用唯一的鍵獲取對象 |
HashSet較HashMap來說比較慢 |
不允許key重複 |
不允許元素重複 |
- HashMap和TreeMap的區別?
①實現方法:HashMap基於哈希表實現。TreeMap基於紅黑樹實現
②TreeMap能夠把他保存的記錄根據鍵排序
③HashMap:適用於在Map中插入,刪除和查找元素
TreeMap:按自然順序或自定義順序遍歷鍵
HashMap比TreeMap快一點
- List,set和map的初始容量和加載因子?
- List
ArrayList 的初始容量是 10;加載因子爲 0.5; 擴容增量:原容量的 0.5 倍 +1;一次擴容後長度爲 16。
Vector 初始容量爲 10,加載因子是 1。擴容增量:原容量的 1 倍,如 Vector 的容量爲 10,一次擴容後是容量爲 20。
- Set
HashSet,初始容量爲 16,加載因子爲 0.75; 擴容增量:原容量的 1 倍; 如 HashSet 的容量爲 16,一次擴容後容量爲 32
- Map
HashMap,初始容量 16,加載因子爲 0.75; 擴容增量:原容量的 1 倍; 如 HashMap 的容量爲 16,一次擴容後容量爲 32
- Comparable接口和comparator接口有什麼區別?
前者簡單,但是如果需要重新定義比較類型時,需要修改源代碼。
後者不需要修改源代碼,自定義一個比較器,實現自定義的比較方法。
- Java集合的快速失敗機制“fail-fast”?
它是 java 集合的一種錯誤檢測機制,當多個線程對集合進行結構上的改變的操作時,有可能會產生 fail-fast 機制。
原因: 迭代器在遍歷時直接訪問集合中的內容,並且在遍歷過程中使用一個 modCount 變量。集合在被遍歷期間如果內容發生變化,就會改變 modCount 的值。
每當迭代器使用 hashNext()/next() 遍歷下一個元素之前,都會檢測 modCount 變量是否爲 expectedmodCount 值,是的話就返回遍歷;否則拋出異常,終止遍歷。
解決辦法:①在遍歷過程中,所有涉及到改變 modCount 值得地方全部加上 synchronized;②使用 CopyOnWriteArrayList 來替換 ArrayList。
- ArrayList,LinkedList,Vector的區別和實現原理?
基於類型:ArrayList 和 Vector是基於數組的(方便查詢,增加時尾部O(1),增加和刪除操作是O(n)),LinkedList是基於鏈表的(方便刪除,修改,增加,不方便查詢)
線程安全:vector使用同步機制是線程安全的,ArrayList和LinkedList是線程不安全的
擴容機制:ArrayList初始容量10,一次擴容後是16。Vector初始初始10,一次擴容後是20