java基礎知識點的查漏補缺
1. 靜態屬性和靜態方法是否可以被繼承?是否可以被重寫?以及原因?
2.什麼是內部類 內部類、靜態內部類、局部內部類和匿名內部類的區別及作用
- 內部類的作用
⑴ 內部類作爲外部類的成員,可以訪問外部類的私有成員或屬性。(即使將外部類聲明爲PRIVATE,但是對於處於其內部的內部類還是可見的。)
⑵ 用內部類定義在外部類中不可訪問的屬性。這樣就在外部類中實現了比外部類的private還要小的訪問權限。
- 局部內部類的作用 ----沒理解。
在類外不可直接生成局部內部類(保證局部內部類對外是不可見的)。
要想使用局部內部類時需要生成對象,對象調用方法,在方法中才能調用其局部內部類。
通過內部類和接口達到一個強制的弱耦合,用局部內部類來實現接口,並在方法中返回接口類型,使局部內部類不可見,
屏蔽實現類的可見性。
- 靜態內部類
生成(new)一個靜態內部類不需要外部類成員:這是靜態內部類和成員內部類的區別。靜態內部類的對象可以直接生成:
Outer.Inner in=new Outer.Inner();
而不需要通過生成外部類對象來生成。這樣實際上使靜態內部類成爲了一個頂級類。靜態內部類不可用private來進行定義。
- 匿名內部類
實現接口
3. == 和 equals() 和 hashcode()的區別?
== 基本類型比較值 複合類型比較的是堆內存的地址 (String != Stringbuffer) //這裏String a = String b 這部分看下
equals 默認實現是 == 一些類都會覆寫
hashCode : Object 的 native方法 , 獲取對象的哈希值,用於確定該對象在哈希表中的索引位置,它實際上是一個int型整數
!! 這邊最好能引申到棧內存和堆內存 //看下jvm
4.java的集合以及集合之間的繼承關係
-----Collection
- List 有序可重複 (ArrayList 可以用來查改 LinkedList 可以用來增刪) ArrayList是實現了基於動態數組的數據結構,而LinkedList是基於鏈表的數據結構
- Set 無序不重複 (HashSet:無序 TreeSet:需要排序)
-----Map
- Map 映射關係 (HashMap:無序 TreeMap:排序)
Collection和Map最大的區別就是Collection存儲的是一組對象;Map是以“鍵值對”的形式對對象進行的管理
--List
- ArrayList
1.可變大小
2.非線程安全
3.動態增長
- LinkedList
1.是一個雙鏈表
2.非線程安全
5.HashMap HashTable ConcurrentHashMap區別
- HashMap
HashMap由數組+鏈表組成的,數組是HashMap的主體,鏈表則是主要爲了解決哈希衝突而存在的,線程不安全
1.本質數組+鏈表
2.hash值put 、 擴容
3.Fail-Fast機制 防止其他線程操作
- Hashtable
是jdk1的一個遺棄的類,它把所有方法都加上synchronized關鍵字來實現線程安全。所有的方法都同步這樣造成多個線程訪問效率特別低
1.將hashMap鎖住
- ConcurrentHashMap
Segment數組的意義就是將一個大的table分割成多個小的table來進行加鎖,也就是上面的提到的鎖分離技術,而每一個Segment元素存儲的是HashEntry數組+鏈表,這個和HashMap的數據存儲結構一樣
2.分塊加鎖
理解HashMap 的put get源碼
一、 put
- 判斷 value 是否爲空,爲空則拋出異常;
- 計算 key 的 hash 值,並根據 hash 值獲得 key 在 table 數組中的位置 index,如果 table[index] 元素不爲空,則進行迭代,如果遇到相同的 key,則直接替換,並返回舊 value;
* 否則,我們可以將其插入到 table[index] 位置。
二、 get
- 首先通過 hash()方法求得 key 的哈希值,
- 然後根據 hash 值得到 index 索引(上述兩步所用的算法與 put 方法都相同)。
- 然後迭代鏈表,返回匹配的 key 的對應的 value;找不到則返回 null。
6.對反射的瞭解
Java 強類型語言,但是我們在運行時有了解、修改信息的需求,包括類信息、成員信息以及數組信息。
!!! 反射的原理
!!! 爲什麼反射消耗性能: 創建好多臨時變量,造成gc回收,內存抖動 遞歸的查找方法也是消耗性能
得到一個 Class 對象
以下是幾種獲取Class對象的方法
- 1.Object.getClass 方法
Class c = "com.hugh".getClass();
- 2.在要獲得的類名後加上 .class ,比如這樣:
Integer.class.newInstance();
int.class.newInstance()
//可以看到,這種方式不僅能用於引用類型,基本類型也可以。
// 當然數組也可以:x`
Class b = int[][].class;
- 3.Class.forName()
如果我們有一個類的完整路徑,就可以使用 Class.forName(“類完整的路徑”) 來得到相應的 Class,這個方法只能用於引用類型,比如:
Class<?> c = Class.forName("java.lang.String");
Class<?> aClass = Class.forName("com.hugh.demo1.beans.BookBean"); //包名加路徑
// 具體參考這個類MethodTypeSpy
!!! 有時間瞭解下反射的原理 運行時
7.對註解的瞭解?
爲程序的元素(類、方法、成員變量)加上更直觀的說明,`這些說明信息是與程序的業務邏輯無關,並且供指定的工具或框架使用。`Annontation像一種修飾符一樣,應用於包、類型、構造方法、方法、成員變量、參數及本地變量的聲明語句中。
Java 註解是附加在代碼中的一些元信息,用於一些工具在編譯、運行時進行解析和使用,起到說明、配置的功能。`註解不會也不能影響代碼的實際邏輯,僅僅起到輔助性的作用。`
- 1.能夠讀懂別人寫的代碼(尤其是框架相關的代碼);
- 2.實現替代配置文件的功能。比如可能原本需要很多配置文件以及很多邏輯才能實現的內容,如果使用合理的註解,就可以使用一個或多個註解來實現相同的功能。這樣就使得代碼更加清晰和整潔;
- 3.編譯時進行格式檢查。 如 @Override 註解放在方法前,如果該方法不是覆蓋了某個超類方法,編譯的時候編譯器就能檢查出來。
元註解
元註解是可以註解到註解上的註解,或者說元註解是一種基本註解,但是它能夠應用到其它的註解上面。或者可以理解爲:元註解也是一張標籤,但是它是一張特殊的標籤,它的作用和目的就是給其他普通的標籤進行解釋說明的。
基本的元標籤有 @Retention, @Documented, @Target, @Inherited 四種(後來到了 Java 8 又加入了 @Repeatable)。
---------------------
@Retention
@Retention 定義了該註解的生命週期。當 @Retention 應用到一個註解上的時候,作用就是說明這個註解的存活時間。
RetentionPolicy.SOURCE: 註解只在源碼階段保留,在編譯器完整編譯之後,它將被丟棄忽視;
例:@Override, @SuppressWarnings
RetentionPolicy.CLASS: 註解只被保留到編譯進行的時候,它並不會被加載到 JVM 中;
RetentionPolicy.RUNTIME: 註解可以保留到程序運行的時候,它會被加載進入到 JVM 中,所以在程序運行時可以獲取到它們;筆者接觸到大部分的註解都是 RUNTIME 的生命週期。
---------------------
@Target 表示該註解用於什麼地方,可以理解爲:當一個註解被 @Target 註解時,這個註解就被限定了運用的場景。可以使用的 ElementType 參數:
ElementType.CONSTRUCTOR: 對構造方法進行註解;
ElementType.ANNOTATION_TYPE: 對註解進行註解;
ElementType.FIELD: 對屬性、成員變量、成員對象(包括 enum 實例)進行註解;
ElementType.LOCAL_VARIABLE: 對局部變量進行註解;
ElementType.METHOD: 對方法進行註解;
ElementType.PACKAGE: 對包進行註解;
ElementType.PARAMETER: 對描述參數進行註解;
ElementType.TYPE: 對類、接口、枚舉進行註解;
---------------------
@Documented 是一個簡單的標記註解,表示是否將註解信息添加在 Java 文檔,即 Javadoc 中。
---------------------
Inherited 是指繼承,@Inherited 定義了一個註釋與子類的關係。如果一個超類帶有 @Inherited 註解,那麼對於該超類,它的子類如果沒有被任何註解應用的話,那麼這個子類就繼承了超類的註解。
8.對依賴注入的瞭解?
DL框架
之前:
//編寫代碼時我們常常會發現有一些類是依賴於其它類的。所以類A可能需要一個類B的引用或對象。 ---這就是依賴 一個類 要去使用其他類相應的一些方法或屬性
public class Car{
private Engine engine;
public Car(){
engine=new PetrolEngine();
}
}
依賴注入
public class Car{
private Engine engine;
public Car(Engine engine){
this.engine=engine;
}
}
我們通過Car 的構造函數,向Car 傳遞了一個Engine 對象。
這意味着兩個對象之間的耦合變低了。
Car類不需要知道 Engine 的具體實現,只要繼承了原始 Engine 類,任何類型 Engine 都符合要求。
它最基本的用法就是向類中傳遞一個依賴,而不是直接在類中實例化。
9.對泛型的瞭解?
“泛型” 意味着編寫的代碼可以被不同類型的對象所重用。
10.靜態代理和動態代理的區別?有什麼場景使用?
這裏看下設計模式在總結吧!!