參加java培訓的心得總結zz

 

JAVA基礎培訓總結 by 光遠

                                                                         

通過參加本次JAVA基礎培訓,自己對之前所瞭解的一些知識有了一次比較系統的學習。回想整個學習過程,對以下印象比較深刻的知識點在課後做了個簡單整理和總結。如有不對,請指正。

1 JAVA語言基礎

1.1 傳值與傳引用

提到Java語言,在網上討論較多的是:Java到底是傳值還是傳引用?

誤區:JAVA對於原始類型(primitive type)傳值,對於引用類型(reference type)傳引用;

正解:JAVA參數傳遞都是傳值的,傳入參數都是“源”的一個複製品。

對於簡單數據類型理解上基本沒問題,對於對象傳參的典型示例:


                 

運行結果:


                

具體過程:

對象在傳遞給具體的方法時,會複製一個對象的引用給參數,也就是說,這個Object對象當前至少存在2個引用,引用指向的對象是相同的。

 

                      

 

調用tricky方法前後的變化過程如下:




                  
 
 

       即只有方法的引用發生了改變,源的引用將不會變化。

 

1.2 對象的比較

“==”比較對象是否引用了同一個對象,或者比較簡單類型變量值是否相等。

Object類的equals()方法用來比較是否一個對象(內存地址比較),在用equals比較具體對象時可以重寫。

重寫equals需要嚴格遵循java.lang.Object的規範:自反性、對稱性、傳遞性、 一致性、非空性。改寫的一般規則是:

l使用==操作符檢查實參是否爲指向對象的一個引用

l使用instanceof操作符檢查“實參是否爲正確的類型”。

l把實參轉換到正確的類型 。

l對於類中的每一個“關鍵域”檢查實參中的域與當前對象中對應的域值。

 

改寫一個類的equals方法後,兩個截然不同的實例有可能在邏輯上是相等的,但是,根據Object.hashCode方法,它們僅僅是兩個對象。因此,違反了“相等的對象必須具有相等的散列碼”。因此,當改寫equals()的時候,必須要改寫hashCode()

1.3 集合類


          

Collection是最基本的集合接口,一個Collection代表一組ObjectCollection中除Set不允許包含重複的元素外,其他的都可添加重複元素。

Collection的通用訪問方式:

 

 

Iterator it = collection.iterator(); // 獲得一個迭代子
while(it.hasNext()) {
   Object obj = it.next(); // 得到下一個元素
}
 

 

List是有序的Collection,使用此接口能夠精確的控制每個元素插入的位置。實現List接口的常用類有LinkedListArrayListVectorStackLinkedList可被用作堆棧(stack),隊列(queue)或雙向隊列(deque);LinkedList沒有同步方法,可在創建List時構造一個同步的List

 

List list = Collections.synchronizedList(new LinkedList(...));

 

ArrayList實現了可變大小的數組,也是非同步的。Vector非常類似ArrayList,但是Vector是同步的。如果涉及到堆棧,隊列等操作,應該考慮用List,對於需要快速插入,刪除元素,應該使用LinkedList,如果需要快速隨機訪問元素,應該使用ArrayListArrayList是實現了基於動態數組的數據結構,LinkedList基於鏈表的數據結構。對於隨機訪問getsetArrayList覺得優於LinkedList,因爲LinkedList要移動指針。對於新增和刪除操作addremoveLinedList比較佔優勢,因爲ArrayList要移動數據。

還有一點需要注意,在迭代CollectionMap的時候,迭代器在調用next方法時,會檢查列表是否被修改過,如果被修改 (addremove) 過將會拋出ConcurrentModificationException

1.4 泛型

泛型除了基本的用法外,有幾個誤區:

誤區1

 

List<String> ls = new ArrayList<String>(); //1
List<Object> lo = ls; //2

 

假設這兩行代碼是正確的,那麼下面的操作:

 

lo.add(new Object());
String str = ls.get(0);

 將導致運行時錯誤,通過別名lo存取ls時,可以插入任意類型的對象,ls就不再僅僅支持String了。Java編譯器消除了這種錯誤發生的可能性。

 

2行將導致編譯時刻錯誤。一般地說,如果SubPar的子類,G定義爲某種泛型,那麼G<Sub>不是G<Par>的子類。

誤區2

 

void method(List<String> ls) {…}
void method(List<Long> ls) {…}
void method (List<Object> lo){…}
void method (List<?> l) {…}
  

以上三個方法放在一起並不能構成重載,相反還會出現編譯錯誤。按照錯誤提示,可以瞭解到Java針對泛型採取的是erasure拭去法,拭去了參數,不論是List<String>List<Object>還是List<?>,編譯生成的都是同一段代碼,只是在適當的地方加上了類型轉換。

 

2 多線程

2.1 多線程與多進程

Java只有一個JVM進程。

進程相比線程而言比較獨立,不共享資源和地址空間的;而線程是共享着相同的地址空間和資源,所以多線程之間的數據不安全。

 

  

 

 

 

2.2 對象鎖與同步

Synchronized:這個關鍵字用於保護共享數據,每個對象都有一個鎖標誌,當一個線程訪問該對象時,被Synchronized修飾的數據將被“上鎖”,阻止其他線程訪問。當前線程訪問完這部分數據後釋放鎖標誌,其他線程就可以訪問了。

volatile :  volatile 變量可以被看作是一種程度較輕的 synchronized” 但是不具備原子特性。由於線程變量緩存一致性,允許線程保存共享成員變量的私有拷貝,而且只有當線程進入或者離開同步代碼塊時,才能與共享變量的原始值對比,但是線程能夠自動發現 volatile 變量保存的最新值(子線程始終能拿到主線程的最新值)。要使 volatile 變量提供理想的線程安全,必須同時滿足下面兩個條件:

<!--[if !supportLists]-->ü  <!--[endif]-->對變量的寫操作不依賴於當前值。

<!--[if !supportLists]-->ü  <!--[endif]-->該變量沒有包含在具有其他變量的不變式中。

因此,這個變量可以用在一個控制開關的標誌上,可以修飾一個變量始終保存多個線程讀寫後的最新值。

wait():此方法使當前線程暫停執行並釋放對象鎖標誌,讓其他線程可以進入Synchronized數據塊,當前線程被放入對象等待池中。此方法放棄當前對資源的佔有權,等啊等啊,一直等到有人通知,纔會運行後面的代碼。

notify():此方法被調用後,將喚醒在等待該對象鎖的線程;如果沒有等待中的線程,則notify()不起作用。但是隻有一個線程從wait狀態中恢復,然後繼續運行wait()後面的語句。

notifyAll()則喚醒所有在等待改對象鎖的線程,通知所有的等待中的線程從wait()方法後的語句開始運行。

wait()notify()notifyAll()三個方法用於協調多個線程對共享數據的存取,所以必須在Synchronized語句塊內使用這三個方法,否則拋出IllegalMonitorStateException。當某個線程試圖等待一個自己並不擁有的對象的監控器或者在自己擁有的同時去通知其他線程等待該對象的監控器時便會拋出該異常。

死鎖:多個線程同時被阻塞,它們中的一個或者全部都在等待某個資源被釋放,線程被無限期地阻塞,程序不可能正常終止。常見於線程加鎖次序、佔有並等待的情況。

java.util.concurrent包:

Atomic原子性:volatile僅僅只是解決了讀最新的問題,如volatile int i i++操作涉及到獲取i值、修改i值、存儲i(i=i+1),這裏的volatile只是解決了保存i值的問題,至於獲取和修改i值,沒有做到同步(2個線程讀到的i都是1,執行i++後結果僅僅是2,而不是3)Atomic*中的變量是申明爲volatile變量的,這樣就保證的變量的寫和讀是一致的,然後Atomic提供了getAndIncrement方法,該方法對變量的++操作進行了封裝,並提供了compareAndSet方法,來完成對單個變量的加鎖和解鎖操作。

ExecutorService :繼承於Executor接口的接口,調用execute()方法執行線程任務。ExecutorService 提供了多個完整的異步任務執行框架,管理任務的排隊和安排,提供了管理終止的方法,可以爲一個或多個異步任務執行狀況而生成 Future,獲取線程返回值。其中,shutdown() 方法在終止前允許繼續執行之前提交的任務,而 shutdownNow()方法阻止等待任務啓動並試圖停止當前正在執行的任務。

Executors:提供大多數 Executor 的常見類型和配置的工廠方法,以及使用它們的幾種實用工具方法。如:newCachedThreadPool()--創建一個可根據需要創建新線程的無界線程池,可以進行自動線程回收,但是在以前構造的線程可用時將重用它們;newScheduledThreadPool()--創建一個線程池,它可安排在給定延遲後運行命令或者定期地執行;newFixedThreadPool()創建固定大小線程池。關於線程池,比較常用的還有ThreadPoolExecutor,可靈活配置線程池的大小、調度策略以及拒絕策略。

concurrent包下還有較多線程安全的隊列、併發Collection,都是比較實用的,。

3 開源工具包

Apache組織涉及到 Http服務器,編譯工具,類庫,開發架構,服務器端Java技術,J2EE容器,數據庫工具,日誌工具,XML解析等諸多領域。其下的Commons項目下包含了很多開源的工具,主要用於解決平時編程經常會遇到的問題,可有效減少重複勞動。

commons-io:主要在IO操作上提供了一系列的工具,包含了日常工作的靜態工具類、輸入流、輸出流、文件過濾器、文件比較器、文件系統監控器。常見的工具類有FileUtils,對文件的讀寫、拷貝、刪除等提供了很便利的方法。如:List<String>    readLines(File file)void copyFile(File srcFile, File destFile)void       writeStringToFile(File file, String data)

commons-beanutils:常用的BeanUtils類提供beanclonebean之間屬性拷貝、獲取bean指定屬性值等。如:void copyProperties(Object dest, Object orig)String getSimpleProperty(Object bean, String name)。在bean的拷貝使用中,需要注意:如果bean的屬性中包含引用類型成員,拷貝之後的bean含有此成員的相同引用,即:拷貝後的bean可以修改拷貝前的bean的引用類型成員。

commons-configuration:用來幫助處理配置文件的,支持很多種存儲方式,常見的有:Properties files XML documentsJNDIJDBC DatasourceSystem properties等。

commons-dbcp:這個是用來配置數據庫連接池,實際使用的較多。其BasicDataSource類中提供了連接池這個參數的設置、連接的建立和關閉等。

commons-net:此包封裝了很多網絡協議,可以各種協議進行編程通信。

其他子項目就不在此列舉了,具體的使用可參閱apache官網指導信息。

4 感想

源碼之下,了無祕密。多看開源框架,多看高手寫的代碼,多看優秀的代碼,本身也是一種很好的學習方式。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章