中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

看看這5個最容易犯的Java錯誤,你犯了沒?

發布時間:2020-08-03 11:26:05 來源:網絡 閱讀:146 作者:qq593e097eaab3c 欄目:編程語言

人非圣賢,孰能無過。都說Java語言是一門簡單的編程語言,基于C++演化而來,剔除了很多C++中的復雜特性,但這并不能保證Java程序員不會犯錯。那么對于廣大的Java程序員來說,它們最容易犯的幾個錯誤是什么呢?
接下來就一起來看看這些錯誤是否也是你經常犯的!

1、重復造輪子
一個明顯的錯誤就是Java程序員習慣性的忽略已經存在的大量的庫。在你決定造一個輪子之間,我建議你試著先搜一下是否有已經存在庫。例如日志方面,有logback,新log4j,網絡方面,有Netty或者Akka。有一些庫,已經逐步變成了標準,比如Java8中加入的Joda-Time。
下面講述的是我上一個項目中的個人經歷。有一部分用于HTML轉義的代碼是一個開發自己完成的。這個代碼正常工作了多年,但是又一次遇到了一個用戶輸入,代碼陷入了死循環。這個用戶發現應用沒有反應,又重新輸入了一遍,服務器因為這個死循環掛了。如果這個開發使用已有的HTML轉義工具,比如Google Guava項目提供的HtmlEscaper,這個嚴重的問題可能就不會出現。并且現在市面上流行的大部分的開源庫,背后都有團隊和社區在支持,類似這樣的錯誤,都能夠及時的被修復。
2、在Switch-Case中錯誤的使用break
這是一個很尷尬的問題,但是仍然在實際開發中經常出現。瀑布特性在switch語句中有時會非常有用,但是必要的break關鍵字的缺失,有時會帶來災難性的后果。比如在下面的代碼中,如果在case 0中忘記放一個break關鍵字,代碼會繼續向下執行,就會在Zero之后再輸出一個One:
public static void switchCasePrimer() {
int caseIndex = 0;
switch (caseIndex) {
case 0:
System.out.println("Zero");
case 1:
System.out.println("One");
break;
case 2:
System.out.println("Two");
break;
default:
System.out.println("Default");
}
}

最好的解決辦法是使用多態,并把不同的處理代碼放到子類中。當然,類似這樣的錯誤,也可以通過類似FindBugs或者PMD這樣的工具檢查出來。
3、忘記釋放資源
一旦打開一個文件,或者建立一個網絡連接,一個非常重要的習慣是記得關閉資源。并且一定記得,如果在使用類似這樣的資源過程中出現了錯誤,在異常處理中,也需要做對應的關閉操作。可能有人會說,FileInputStream對象在GC的時候,Java終結器(finalizer)會自動調用其close()方法,但是我們知道,我們無法預知GC在什么時候開始,所以我們無法預知在執行GC之前,會有多少資源無法及時關閉。為了避免這種情況,Java7推出的try-with-resources語法,是值得每個開發使用的。
private static void printFileJava7() throws IOException {
try(FileInputStream input = new FileInputStream("file.txt")) {
int data = input.read();
while(data != -1){
System.out.print((char) data);
data = input.read();
}
}
}

try-with-resources語法適用于所有實現了AutoClosable接口的類。它能保證每一個資源及時的關閉。
4、內存泄露
Java使用自動內存管理,所以大部分時間,我們都不會去關心內存的分配和釋放,但是,這并不意味著Java開發人員需要忽略內存。在Java應用中,內存的問題也經常出現。我們知道,對象如果沒有被引用了,這個對象就會被釋放,但是并不意味著,就不會出現內存泄露的問題。在Java中,造成內存泄露的原因有很多,但最容易出現的情況就是對象引用無法釋放,因為GC在回收堆內存的時候,如果一個對象仍然被其他對象引用,這個對象空間是不會被回收的,舉個例子,如果在類中,有一個靜態字段引用到一個集合,假如我們沒有手動的在使用完成這個集合之后,將他設置為null,那么這個集合及這個集合中的對象,是永遠不會被回收的,因為類靜態字段是不會被GC的。
比如還有一種造成內存泄露的原因,就是一組對象互相引用對方,就是我們經常說的循環引用,因為循環引用,所以GC不能確定這些互相引用的對象是否還有繼續存活的必要。還有一種情況,就是使用JNI時的非堆內存泄露。
一個典型的內存泄露例子:
final ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);final Deque numbers = new LinkedBlockingDeque<>();final BigDecimal divisor = new BigDecimal(51);

scheduledExecutorService.scheduleAtFixedRate(() -> {
BigDecimal number = numbers.peekLast();
if (number != null && number.remainder(divisor).byteValue() == 0) {
System.out.println("Number: " + number);
System.out.println("Deque size: " + numbers.size());
}
}, 10, 10, TimeUnit.MILLISECONDS);

scheduledExecutorService.scheduleAtFixedRate(() -> {
    numbers.add(new BigDecimal(System.currentTimeMillis()));
}, 10, 10, TimeUnit.MILLISECONDS);

try {
scheduledExecutorService.awaitTermination(1, TimeUnit.DAYS);
} catch (InterruptedException e) {
e.printStackTrace();
}

在上面的例子中,我們創建了兩個定時任務。第一個定時任務,從deque中獲取了最后的一個數字”numbers”并判斷,如果這個數字能被51整除,則打印該數字和deque的大小。第二個定時任務,不斷的向deque中添加數據。兩個任務都間隔10ms執行。如果這個代碼執行,你會發現,deque的大小會持續的增加,直到deque中的數據占滿整個堆空間。為了阻止這種情況的發生,我們可以使用pollLast方法來代替peekLast方法,因為pollLast方法會在拿到最后一個元素之后,把這個元素從deque中移除。
5、過度產生垃圾數據
過度產生垃圾數據的意思,是程序運行中大量產生短聲明周期的對象。這回導致GC頻繁的執行,從內存中回收空間,GC的執行是需要完成堆掃描的,這對系統的性能影響是非常大的。下面是一個小例子:
String oneMillionHello = "";for (int i = 0; i < 1000000; i++) {
oneMillionHello = oneMillionHello + "Hello!";
}
System.out.println(oneMillionHello.substring(0, 6));

在Java中,字符串是不可變的,所以每一次循環都會創建一個新的字符串對象。為了改進這種代碼,我們可以使用StringBuilder來代替:
StringBuilder oneMillionHelloSB = new StringBuilder();
for (int i = 0; i < 1000000; i++) {
oneMillionHelloSB.append("Hello!");
}
System.out.println(oneMillionHelloSB.toString().substring(0, 6));

第二個版本的代碼,在執行的時候會提高不少的性能。
本次干貨分享到這里就結束啦!想要獲取更多干貨及免費資源,請持續關注每周的更新!跟我一起進階打怪!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

盐亭县| 阿克苏市| 崇明县| 临海市| 纳雍县| 望奎县| 黄平县| 安国市| 翼城县| 通榆县| 樟树市| 闵行区| 麦盖提县| 尚义县| 剑川县| 衡东县| 汝阳县| 丰县| 门源| 贵德县| 平舆县| 阳泉市| 黄梅县| 深州市| 尉氏县| 贡嘎县| 迁西县| 抚州市| 舞阳县| 乐昌市| 轮台县| 乌拉特后旗| 三门峡市| 德庆县| 大竹县| 贵定县| 昌都县| 靖西县| 开封县| 扎赉特旗| 满城县|