1. 程式人生 > >#Java乾貨分享:兩分鐘瞭解日常程式設計中的小技巧,提高你的能力

#Java乾貨分享:兩分鐘瞭解日常程式設計中的小技巧,提高你的能力

1.return 一個空的集合,而不是 null

如果一個程式返回一個沒有任何值的集合,請確保一個空集合返回,而不是空元素。這樣你就不用去寫一大堆 ”if else” 判斷null元素。

如果有想學習java的程式設計師,可來我們的java學習扣qun:94311,1692免費送java的視訊教程噢!我整理了一份適合18年學習的java乾貨,送給每一位想學的小夥伴,並且每天晚上8點還會在群內直播講解Java知識,歡迎大家前來學習哦。

大狗乾貨鋪:13個java程式設計中的小技巧

Java 的標準庫設計者已經在 Collections 類中放了一個空的 List 常量 EMPTY_LIST,除此之外,還有 EMPTY_MAP, EMPTY_SET,真是貼心。

2. 小心使用 String

因為字串相加或者拼接的方式都會在物件池中查詢字串是否存在,如果不存在則建立,這樣在拼接的過程中會產生大量中間過程的字串,佔用記憶體資源。StringBuilder效率優於StringBuffer,但是StringBuffer執行緒安全。

大狗乾貨鋪:13個java程式設計中的小技巧

大狗乾貨鋪:13個java程式設計中的小技巧

另外,在例項化一個字串物件,建構函式應該避免發生直接例項化,例如:

大狗乾貨鋪:13個java程式設計中的小技巧

3. 避免不必要的物件

一個最昂貴的操作(在記憶體利用率)是java物件的建立。因此,建議只在必要時建立或初始化物件。下面的程式碼給出了一個例子:

大狗乾貨鋪:13個java程式設計中的小技巧

4.Array 和ArrayList 選擇

ArrayList和Array是我們在實際程式設計中經常使用的容器,而且因為ArrayList相當於動態化的陣列,所以它們之間有太多的相似,以至於我們在選擇哪種來儲存元素的時候,會有小小的迷惑,他們都有註解的優缺點,選擇真的取決於你的真實場景。

大狗乾貨鋪:13個java程式設計中的小技巧

4.1.Array 有固定大小但 ArrayList 的大小不同。由於Array 的大小是固定的,在Array 型別變數宣告的時候,記憶體被分配。因此,Array 是非常快的。另一方面, 使用ArrayList的最大缺點就是當我們新增新的元素的時候,它是先檢查內部陣列的容量是否足夠,如果不夠,它會建立一個容量為原來陣列兩倍的新陣列,���後將所有元素複製到新數組裡,接著拋掉舊陣列。這點真的很麻煩,因為每次都要這麼搞,尤其是元素足夠多的時候,這就真的是既影響記憶體又影響效率的問題,但通過單獨測試它們的執行時間,發現其實差不多,最大的影響就是如果是有其他程式碼也需要使用到記憶體,那麼Array依然不變,但是ArrayList就會變得慢多,相同情況下所花的時間是Array的四倍多(實際情況是遠遠不止)。

4.2.這是新增或刪除元素從ArrayList 比Array更容易。

4.3.陣列可以多維但ArrayList只有一個維度。

4.4.ArrayList因為內部是一個數組,所以它是可以轉化為陣列的。

4.5 兩者的適用場合:

List list = new ArrayList();

雖然我們想要的確實是ArrayList而不是list,但是我們知道,父類是可以獲得子類的引用並且使用子類的方法,所以這樣我們就能同時使用List和ArrayList的方法而不用害怕出錯了。

首先,一個重要的約束就是,List的宣告區域一般是在main方法裡(當然靜態list也可以,但是我們一般使用的時候都只是當做儲存元素的臨時容器),而Array是可以在外部進行宣告的,這時它就是全域性陣列。所以,單看這點,它們的使用已經有區別,如果想要儲存一些在整個程式執行期間都會存在而且不變的資料,我們可以將它們放進一個全域性數組裡,但是如果我們單純只是想要以陣列的形式儲存資料,方便我們進行查詢,那麼,我們就選擇ArrayList。而且還有一個地方是必須知道的,就是如果我們需要對元素進行頻繁的移動或刪除,或者是處理的是超大量的資料,那麼,使用ArrayList就真的不是一個好的選擇,因為它的效率很低,使用陣列進行這樣的動作就很麻煩,那麼,我們可以考慮選擇LinkedList。

大狗乾貨鋪:13個java程式設計中的小技巧

5.用try catch的時候,要加finally嗎?

考慮下面的程式碼片斷

大狗乾貨鋪:13個java程式設計中的小技巧

執行結果:

在Finally程式碼塊中

在Finally程式碼塊中

在Finally程式碼塊中

在Finally程式碼塊中

在Try內部程式碼塊,退出不執行Finally程式碼塊

在執行程式碼前,它看起來像要列印 ”在Finally程式碼塊中“ 5次。但是執行的結果只有4次。第五次列印的結果是 ”在Try內部程式碼塊,退出不執行Finally程式碼塊“。

關於 Java 虛擬機器是如何編譯 finally 語句塊的問題,有興趣的讀者可以參考《 The JavaTM Virtual Machine Specification, Second Edition 》中 7.13 節 Compiling finally。那裡詳細介紹了 Java 虛擬機器是如何編譯 finally 語句塊。實際上,Java 虛擬機器會把 finally 語句塊作為 subroutine(對於這個 subroutine 不知該如何翻譯為好,乾脆就不翻譯了,免得產生歧義和誤解。)直接插入到 try 語句塊或者 catch 語句塊的控制轉移語句之前。但是,還有另外一個不可忽視的因素,那就是在執行 subroutine(也就是 finally 語句塊)之前,try 或者 catch 語句塊會保留其返回值到本地變量表(Local Variable Table)中。待 subroutine 執行完畢之後,再恢復保留的返回值到運算元棧中,然後通過 return 或者 throw 語句將其返回給該方法的呼叫者(invoker)。

將上面程式碼修改如下:

大狗乾貨鋪:13個java程式設計中的小技巧

執行結果:

在Try內部程式碼塊,退出不執行Finally程式碼塊

在Try內部程式碼塊,退出不執行Finally程式碼塊

在Try內部程式碼塊,退出不執行Finally程式碼塊

在Try內部程式碼塊,退出不執行Finally程式碼塊

在Try內部程式碼塊,退出不執行Finally程式碼塊

總結:

這裡就不過多的去具體分析整個過程有興趣的朋友可找資料瞭解整個過程,一個小小的、看似簡單的 finally 語句塊背後居然隱藏了這麼多玄機。看來,我們平時還是應該認真的閱讀 Java 相關的基礎文件,比如:Java 語言規範、Java 虛擬機器規範等,很多棘手的問題都可以從中得到答案。只有真正的吃透了基礎知識,才能達到運用自如的境界!

1> try、catch、finally語句中,在如果try語句有return語句,則返回的之後當前try中變數此時對應的值,此後對變數做任何的修改,都不影響try中return的返回值

2> 如果finally塊中有return 語句,則返回try或catch中的返回語句忽略。

3 >如果finally塊中丟擲異常,則整個try、catch、finally塊中丟擲異常

所以使用try、catch、finally語句塊中需要注意的是

1> 儘量在try或者catch中使用return語句。通過finally塊中達到對try或者catch返回值修改是不可行的。

2 >finally塊中避免使用return語句,因為finally塊中如果使用return語句,會顯示的消化掉try、catch塊中的異常資訊,遮蔽了錯誤的發生

3 >finally塊中避免再次丟擲異常,否則整個包含try語句塊的方法回丟擲異常,並且會消化掉try、catch塊中的異常

6.奇數判斷

看看下面的程式碼行,並確定如果他們可以用來精確地識別一個給定的數字是否是奇數?

大狗乾貨鋪:13個java程式設計中的小技巧

奇數可以被定義為被2整除餘數為1的整數。表示式 num% 2 計算的是 num整除 2 時所產生的餘數,因此看起來這個程式應該能夠正確運轉。遺憾的是,它不能;它在四分之一的時間裡返回的都是錯誤的答案。

為什麼是四分之一?因為在所有的 int 數值中,有一半都是負數,而 isOdd 方法對於對所有負奇數的判斷都會失敗。在任何負整數上呼叫該方法都回返回 false ,不管該整數是偶數還是奇數。

這是 Java 對取餘操作符(%)的定義所產生的後果。該操作符被定義為對於所有的 int 數值 a 和所有的非零 int 數值b,都滿足下面的恆等式:

(a / b) * b + (a % b) == a

現在進行修改如下:

大狗乾貨鋪:13個java程式設計中的小技巧

使用此程式碼,不僅是解決了奇數的負的問題,而且這個程式碼也高度優化。因為,算術和邏輯運算的速度更快,比除法和乘法,結果取得了更快。

7. 單引號和雙引號之間的區別

大狗乾貨鋪:13個java程式設計中的小技巧

嘗試執行上面的程式。這個程式演示了一個死鎖。這種死鎖的產生是因為兩個執行緒都在等待其他執行緒所抓取的資源。他們都不在任何一個版本。從程式碼,似乎還“HaHa”是回來了,但它實際上返回ha169。原因是,如果使用雙引號,字串對待,但在單引號的情況下,字元自動轉換為int型,進行計算。

8. 通過簡單的技巧避免記憶體洩漏

記憶體洩漏經常會導致軟體的效能退化。因為,java自動管理記憶體,開發商沒有太多的控制。但仍有一些標準的做法,可以用來防止記憶體洩漏。

當查詢完成時,總是釋放資料庫連線。

儘量使用 Finally 塊。

釋放儲存在靜態表中的例項。

9. 避免死鎖

死鎖出現的原因有很多。避免死鎖不是一句話就能解決的。通常來說,當某個同步物件在等待另一個同步物件所擁有的資源上的鎖時,便會產生死鎖。

試著執行下下面的程式。它會告訴你什麼是死鎖。這個死鎖是由於兩個執行緒都在等待對方所擁有的資源,因此會產生死鎖。它們會一直等待,沒有誰會先放手。

大狗乾貨鋪:13個java程式設計中的小技巧

大狗乾貨鋪:13個java程式設計中的小技巧

大狗乾貨鋪:13個java程式設計中的小技巧

執行結果:

Addition Thread: 13

Subtraction Thread: 7

Holding First Lock…

Holding Second Lock…

Addition Thread: Waiting for AddLock…

Subtraction Thread: Waiting for SubLock…

但如果呼叫的順序變一下的話,死鎖的問題就解決了。

將 MySubtractionThread中的執行緒加鎖順序調換再看看

大狗乾貨鋪:13個java程式設計中的小技巧

執行結果:

Addition Thread: 13

Holding First Lock…

Addition Thread: Waiting for AddLock…

Threads: Holding Add and Sub Locks…

Subtraction Thread: 7

Holding Second Lock…

Subtraction Thread: Waiting for SubLock…

Threads: Holding Add and Sub Locks…

三種用於避免死鎖的技術:

1>加鎖順序

2>加鎖時限

3>死鎖檢測

一個更好的方案是給這些執行緒設定優先順序,讓一個(或幾個)執行緒回退,剩下的執行緒就像沒發生死鎖一樣繼續保持著它們需要的鎖。如果賦予這些執行緒的優先順序是固定不變的,同一批執行緒總是會擁有更高的優先順序。為避免這個問題,可以在死鎖發生的時候設定隨機的優先順序。

10.JAVA執行記憶體的設定

一些java應用程式可以被高度的CPU密集型以及他們需要很多記憶體。這樣的應用程式通常執行速度慢,因為記憶體高的要求。所以,我們可以在相關的配置檔案中進行修改調整記憶體大小。

Xms = 設定記憶體初始化的大小

Xmx = 設定最大能夠使用記憶體的大小

XX:PermSize =初始大小,將分配給JVM的啟動過程

XX:MaxPermSize = 最大尺寸可以分配JVM的啟動過程

11. 如何在java時間操作

有java時間兩種標準方法:

System.currentTimeMillis()、System.nanoTime()

平時產生隨機數時我們經常拿時間做種子,比如用System.currentTimeMillis的結果,但是在執行一些迴圈中使用了System.currentTimeMillis,那麼每次的結果將會差別很小,甚至一樣,因為現代的計算機執行速度很快。後來看到java中產生隨機數函式以及執行緒池中的一些函式使用的都是System.nanoTime。

>System.currentTimeMillis返回的是從1970.1.1 UTC 零點開始到現在的時間,精確到毫秒,平時我們可以根據System.currentTimeMillis來計算當前日期,星期幾等,可以方便的與Date進行轉換,

> System.nanoTime提供相對精確的計時,但是不能用他來計算當前日期,

所以在使用中,我們可以根據我們具體的目的去正確的選擇他們。

12. Float 和Double的選擇

Data type Bytes used Significant figures (decimal)
Float 4 7
Double 8 15

double應該比float更好用,原因:

大多數處理器需要幾乎相同數量的處理時間來執行浮點和雙運算的操作。在相同數量的計算時間雙提供了更高的精度。

13. Java的乘方運算

java提供了兩個方法:

Multiplication:乘法

大狗乾貨鋪:13個java程式設計中的小技巧

pow(double base, double exponent):(base的exponent次方)

大狗乾貨鋪:13個java程式設計中的小技巧

math.pow只應在必要時使用,像指數是一個分數。Math.pow()方法通常慢300-600倍的速度比乘法。