java隨筆

static變量和static方法

static變量

1.static修飾的變量:靜態變量,靜態變量在內存中只有一個拷貝,jvm只為靜態變量分配一次內存,在加載類的過程中完成靜態變量的內存分配。可以類名直接訪問。一般在對象之間共享值時和方便訪問變量時使用靜態變量。

2.實例變量,每創建一個實例就會為實例變量分配一次內存,實例變量可以有多個拷貝,互不影響。

靜態方法

靜態方法可以直接通過類名調用,實例也可調用。靜態方法中不能使用this和super關鍵字,不能直接訪問所屬類的實例變量和實例方法,只能訪問所屬類的靜態成員變量和成員方法。

static代碼塊

    public class Test5 {    
    private static int a;    
    private int b;    
     
    static{    
    Test5.a=3;    
    System.out.println(a);    
    Test5 t=new Test5();    
    t.f();    
    t.b=1000;    
    System.out.println(t.b);    
    }

在類中獨立于類成員的static語句塊,可以有多個,jvm加載類時會按順序執行靜態代碼塊

static final

static final修飾的變量,表示一旦賦值就不可修改,并且可以通過類名訪問
static final修飾的方法,不可覆蓋,可通過類名直接訪問

java支持的數據類型有?何為自動拆裝箱?

1.byte

2.short

3.int

4.long

5.float

6.double

7.boolean

8.char
自動裝箱時java編譯器在基本數據類型和對應的對象包裝類型之間做的一個轉化,比如int轉成Integer,double轉double等,反之就是自動拆箱

java不支持多繼承。每個類只能繼承一個類,但可以實現多個接口

抽象類和抽象接口

java提供和創建抽象類和接口,不同點
1.接口中所有的方法隱含的都是抽象的。而抽象類則可以同時包含抽象和非抽象的方法。

2.類可以實現很多個接口,但是只能繼承一個抽象類

3.類如果要實現一個接口,它必須要實現接口聲明的所有方法。但是,類可以不實現抽象類聲明的所有方法,當然,在這種情況下,類也必須得聲明成是抽象的。

4.抽象類可以在不提供接口方法實現的情況下實現接口。

5.Java接口中聲明的變量默認都是final的。抽象類可以包含非final的變量。

6.Java接口中的成員函數默認是public的。抽象類的成員函數可以是private,protected或者是public。

7。接口是絕對抽象的,不可以被實例化。抽象類也不可以被實例化,但是,如果它包含main方法的話是可以被調用的。

創建線程的幾種方式*

  1. 繼承thread類
  2. 實現Runnable接口
  3. 使用Executor框架來創建線程池
    java不支持多繼承,實現接口的方式更受歡迎

synchronized獲取鎖,同步*

在監視器內部,如何做線程同步?程序應做何種級別的同步

監視器和鎖在Java虛擬機中是一塊使用的。監視器監視一塊同步代碼塊,確保一次只有一個線程執行同步代碼塊。每一個監視器

hashMap的原理

hashMap以key-value的形式進行數據存儲,本質上是數組和鏈表的結合。

initialCapacity(初始容量)和loadFactor(加載因子)是影響hashMap性能的重要參數。默認初始容量16,加載因子是0.75。為了保證HashMap的效率,系統必須要在某個臨界點進行擴容處理,臨界點:當HashMap中元素的數量=數據長度length*加載因子(loadFactor).擴容是一個非常耗時的過程,需要重新計算數據在數組中的位置并進行復制。

實驗表明length=2的n次方時,數組中元素分布較均勻
過程:

  1. 利用key的hashCode重新hash計算出當前對象的元素在數組中的下標,然后找到在數組中的位置。
  2. 如果hash值相同且key值也相同,則覆蓋原始值;如果hash相同key不同(出現沖突),則將當前的key-value放入鏈表中

hashMap和hashTable、ConcurrentHashMap和synchronized Map的原理和區別(出處:http://www.importnew.com/21396.html

HashMap中key可以為null,HashTable中key不可以為null,ConcurrentHashMap中key和value都不能為null
HashMap是非線程安全的
如何線程安全的使用hashMap
Map<String,String> hashTable = new HashTable<String,String>()
Map<String,String> synchronizedMap = Collections.synchronizedMap(new HashMap<String,String>)
Map<String,String> concurrentHashMap = new ConcurrentHashMap<String,String>();
HashMap何時會產生死循環?

HashTable

HashTable源碼中使用synchronized來保證線程安全,如get方法和put方法
public synchronized V get(Object key){
//省略
}
public synchronized V put(Object key){
//省略
}
當一個線程使用put方法時別的線程不但不可以使用put,連get方法都不可以使用,效率低!現已基本不使用

ConcurrentHashMap

ConcurrentHashMap線程安全的,適用于讀者數量大于寫者數量的場景

  1. 允許并發讀和線程安全的更新操作
  2. 在執行寫操作時,只鎖住部分map
  3. 高的并發級別會造成時間和空間的浪費,低的并發級別在寫線程多時會引起線程間的競爭
  4. 返回的迭代器是弱一致性,fail-safe并且不會拋出ConcurrentModificationException異常
  5. 不允許null的鍵值
  6. 可代替HashTable,但CHM不會鎖住整個map
java7

采用鎖分離技術,使用多個鎖來控制hash表的不同部分,每一部分相當于一個hashTable,有自己的鎖。只要多個修改操作發生在不同的segment上,就可以并發執行。
有些方法需要跨段,如size()和containsValue(),他們可能需要鎖定整個表而不僅僅是段,這需要按順序鎖定所有段,操作完畢后,按順序釋放所有段的鎖

java8
synchronizedHashMap

源碼
//synchronizedMap方法
public static <K,V> Map<K,V>synchronizedMap(Map<K,V> m){
return new SynchronizedMap<>(m);
}
//SynchronizedMap類
private static class SynchronizedMap<K,V> implements Map<K,V> Serializable{
private static final long serialVersionUID = 1978198479659022715L;
private final Map<K,V> m; // Backing Map
final Object mutex; // Object on which to synchronize
SynchronizedMap(Map<K,V> m) {
this.m = Objects.requireNonNull(m);
mutex = this;
}
SynchronizedMap(Map<K,V> m, Object mutex) {
this.m = m;
this.mutex = mutex;
}
public int size() {
synchronized (mutex) {return m.size();}
}
public boolean isEmpty() {
synchronized (mutex) {return m.isEmpty();}
}
public boolean containsKey(Object key) {
synchronized (mutex) {return m.containsKey(key);}
}
public boolean containsValue(Object value) {
synchronized (mutex) {return m.containsValue(value);}
}
public V get(Object key) {
synchronized (mutex) {return m.get(key);}
}
public V put(K key, V value) {
synchronized (mutex) {return m.put(key, value);}
}
public V remove(Object key) {
synchronized (mutex) {return m.remove(key);}
}
// 省略其他方法
}
從源碼中可以看出,synchronizedMap()方法返回一個SynchronizedMap類的對象,而在SynchronizedMap類中使用了synchronized同步關鍵字來保證對Map的操作是線程安全的

HashMap為什么是非線程安全?

void addEntry(int hash,K key,V value,int bucketIndex){
  Entry<K,V> e = table[bucketIndex];
  table[bucketIndex] = new Entry<K,V>(hash,key,value,e);
  if(size++ >= threshold){
    resize(2*table.length);
  }

}

原因一:hashMap做put操作的時候調用addEntry方法,現在假如A線程和B線程同時對同一個數據位置調用該方法,兩個線程會同時得到頭節點,A寫入頭節點以后B也寫入新的頭節點,那B的寫入操作造成A的寫入操作丟失。

addEntry中當加入新的鍵值對后鍵值對總數超過門限值的時候會調用一個resize操作,代碼如下:
void resize(int newCapacity){
Entry[] oldTable = table;
int oldCapacity = oldTable.length;
if(oldCapacity == MAXIMUM_CAPACITY){
threshold = Integer.MAX_VALUE;
return;
}
Entry[] newTable = new Entry[newCapacity];
transfer(newTable);
table = newTable;
threshold = (int)(newCapacity * loadFactor);
這個操作會生成一個新的容量的數組,會對原數組的所有鍵值對重新進行計算和寫入新的數組,之后指向新的數組。
原因二:當多個線程同時檢測需要進行resize()操作,各自生成新的數組并rehash后賦給該map底層的數組table,結果最后只有一個線程生成的新數組被賦給table變量,其他線程的均丟失。
Map testmap = Collection.synchronizedMap(new HashMap())

equals()方法和hashCode()方法

java.lang.Object類中有兩個非常重要的方法
public boolean equals(Object obj)
public int hashCode()
Object是類繼承結構的基礎,是所有類的父類

equals()

public boolean equals(Object obj){
    return (this == obj)
}

是對兩個對象的地址值進行比較。但String、Math、Integer、Double等這些封裝類在使用equals()方法時,已經覆蓋了object類的equals()方法
如在String類中如下:
public boolean equals(Object anObject){
if(this == anObject){
return true;
}
if(anObject instanceof String){
String anotherString = (String)anObject;
int n = count;
if(n == anotherString.count){
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while(n-- != 0)//對每一位置逐一比較
{
if(v1[i++] != v2[j++]
return false;
}
}
return true;
}
}
return false;
}
類推Math、Integer、Double等類都重寫了equals()方法,還有基本類型也是進行內容的比較

注意:當equals方法被override時,hashCode()也要被override。按照一般hashCode()方法的實現來說,相等的對象,它們的hash code一定相等

hashCode

  1. 在一個java應用的執行期間,如果一個對象提供給equals做比較的信息沒有被修改的話,該對象多次調用hashCode方法,始終返回同一個integer。
  2. 如果兩個對象根據equals(Object)方法是相等的,那調用二者各自的hashCode()方法必須產生同一個integer結果。
    在Object類中,hashCode定義如下:
    public native int hashCode();
    說明是本地方法,實現跟本地機器有關,如String、Integer、Double等這些類都覆蓋了hashCode方法,String中定義的hashCode()方法如下:
    public int hashCode(){
    int h = hash;
    if(h == 0){
    int off = offset;
    char val[] = value;
    int len = count;
    for(int i=0;i<len;i++){
    h = 31*h+val[off++];
    }
    hash = h;
    }
    return h;
    }

ArrayList 和 linkedList

  1. ArrayList實現了基于動態數組的數據結構,LinkedList基于鏈表的數據結構。
  2. 對于隨機訪問,ArrayList優于LinkedList
  3. 對于新增和刪除操作,LinkedList優于ArrayList

ArrayList

ArrayList,在聲明對象時并不需要指定它的長度,對象的大小是按照其中存儲的數據來動態擴充和收縮的。

數組擴容是對ArrayList效率影響較大的一個元素。
每當執行Add、AddRange、insert、insertRange等添加元素的方法,都會檢查內部數組的容量是否夠用。若不夠,以當前容量的兩倍來重新構建數組,將舊元素COPY到數組中,然后丟棄舊數組

特定類型(Object除外)的數組的性能優于ArrayList的性能,因為ArrayList的元素屬于Object類型,所以在存儲或檢索值類型時通常發生裝箱和取消裝箱的操作。

map、list、set

list 有序可重復
set 無序不可重復
map 按鍵值對存儲,無放入順序

List接口有三個實現類:LinkedList、ArrayList、Vector
Set接口有兩個實現類:HashSet(底層由HashMap實現),LinkedHashSet
Map接口有三個實現類:HashMap、HashTable、LinkedHashMap
HashMap allows one null key and any number of null values.,而Hashtable則不行
HashTable是synchronized的,是線程安全的,而HashMap不是

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,646評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,595評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,560評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,035評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,814評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,224評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,301評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,444評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,988評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,804評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,998評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,544評論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,237評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,665評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,927評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,706評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,993評論 2 374

推薦閱讀更多精彩內容

  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,721評論 18 399
  • (一)Java部分 1、列舉出JAVA中6個比較常用的包【天威誠信面試題】 【參考答案】 java.lang;ja...
    獨云閱讀 7,129評論 0 62
  • 一、基本數據類型 注釋 單行注釋:// 區域注釋:/* */ 文檔注釋:/** */ 數值 對于byte類型而言...
    龍貓小爺閱讀 4,283評論 0 16
  • 面向對象主要針對面向過程。 面向過程的基本單元是函數。 什么是對象:EVERYTHING IS OBJECT(萬物...
    sinpi閱讀 1,072評論 0 4
  • 晚上接娃,通常是娃爹的活。我偶爾打個替班。 前幾天,清明過后的那晚,雷電交加。我帶著兩把傘去接他。兩把傘都蠻大的,...
    息語閱讀 352評論 0 3