1. 程式人生 > >Java程式設計常見"坑"彙總(上)

Java程式設計常見"坑"彙總(上)

每天在寫Java程式,其實裡面有一些細節大家可能沒怎麼注意,這不,有人總結了一個我們程式設計中常見的問題。雖然一般沒有什麼大問題,但是最好別這樣做。另外這裡提到的很多問題其實可以通過Findbugs( http://findbugs.sourceforge.net/ )來幫我們進行檢查出來。

注意:Java程式設計常見坑彙總將分為上下兩期來給大家推送!!!

1.字串連線誤用

錯誤的寫法:

Strings ="";  
for(Person p : persons) {  
   s +=", "+ p.getName();  
}  
s = s.substring(2);//remove first comma

正確的寫法:

StringBuilder sb =newStringBuilder(persons.size() *16);// well estimated buffer
for(Person p : persons) {
   if(sb.length() >0) sb.append(", ");
   sb.append(p.getName);
}

2.錯誤的使用StringBuffer

錯誤的寫法:

StringBuffer sb =newStringBuffer();  
sb.append("Name: ");  
sb.append(name +'\n');  
sb.append
("!");  
...  
String s = sb.toString();

問題在第三行,append char比String效能要好,另外就是初始化StringBuffer沒有指定size,導致中間append時可能重新調整內部陣列大小。如果是JDK1.5最好用StringBuilder取代StringBuffer,除非有執行緒安全的要求。還有一種方式就是可以直接連線字串。缺點就是無法初始化時指定長度。

正確的寫法:

StringBuilder sb =newStringBuilder(100);  
sb.append("Name: ");  
sb.append(name);  
sb.append
("\n!");  
String s = sb.toString();

或者這樣寫:

Strings ="Name: "+ name +"\n!";

3.測試字串相等性

錯誤的寫法:

if(name.compareTo("John") ==0) ...  
if(name =="John") ...  
if(name.equals("John")) ...  
if("".equals(name)) ...

上面的程式碼沒有錯,但是不夠好。compareTo不夠簡潔,==原義是比較兩個物件是否一樣。另外比較字元是否為空,最好判斷它的長度。

正確的寫法:

if("John".equals(name)) ...  
if(name.length() ==0) ...  
if(name.isEmpty()) ...

4.數字轉換成字串

錯誤的寫法:

""+set.size()  
newInteger(set.size()).toString()

正確的寫法:

String.valueOf(set.size())

5.利用不可變物件(Immutable)

錯誤的寫法:

zero =newInteger(0);  
returnBoolean.valueOf("true");

正確的寫法:

zero = Integer.valueOf(0);  
returnBoolean.TRUE;

6.請使用XML解析器

錯誤的寫法:

intstart= xml.indexOf("<name>") +"<name>".length();  
intend= xml.indexOf("</name>");  
String name = xml.substring(start,end);

正確的寫法:

SAXBuilder builder =newSAXBuilder(false);  
Document doc = doc = builder.build(newStringReader(xml));  
Stringname = doc.getRootElement().getChild("name").getText();

7.請使用JDom組裝XML

錯誤的寫法:

Stringname = ...  
Stringattribute = ...  
Stringxml ="<root>"
           +"<name att=\""+ attribute +"\">"+ name +"</name>"
           +"</root>";

正確的寫法:

Element root =newElement("root");  
root.setAttribute("att", attribute);  
root.setText(name);  
Document doc =newDocumet();  
doc.setRootElement(root);  
XmlOutputterout=newXmlOutputter(Format.getPrettyFormat());  
String xml =out.outputString(root);

8.XML編碼陷阱

錯誤的寫法:

Stringxml = FileUtils.readTextFile("my.xml");

因為xml的編碼在檔案中指定的,而在讀檔案的時候必須指定編碼。另外一個問題不能一次就將一個xml檔案用String儲存,這樣對記憶體會造成不必要的浪費,正確的做法用InputStream來邊讀取邊處理。為了解決編碼的問題, 最好使用XML解析器來處理。

9.未指定字元編碼

錯誤的寫法:

Reader r =newFileReader(file);  
Writer w =newFileWriter(file);  
Reader r =newInputStreamReader(inputStream);  
Writer w =newOutputStreamWriter(outputStream);  
Strings =newString(byteArray);// byteArray is a byte[]  
byte[] a =string.getBytes();

這樣的程式碼主要不具有跨平臺可移植性。因為不同的平臺可能使用的是不同的預設字元編碼。

正確的寫法:

Reader r =newInputStreamReader(newFileInputStream(file),"ISO-8859-1");  
Writer w =newOutputStreamWriter(newFileOutputStream(file),"ISO-8859-1");  
Reader r =newInputStreamReader(inputStream,"UTF-8");  
Writer w =newOutputStreamWriter(outputStream,"UTF-8");  
Strings =newString(byteArray,"ASCII");  
byte[] a =string.getBytes("ASCII");

10.未對資料流進行快取

錯誤的寫法:

InputStreamin=newFileInputStream(file);  
intb;  
while((b =in.read()) !=-1) {  
...  
}

上面的程式碼是一個byte一個byte的讀取,導致頻繁的本地JNI檔案系統訪問,非常低效,因為呼叫本地方法是非常耗時的。最好用BufferedInputStream包裝一下。曾經做過一個測試,從/dev/zero下讀取1MB,大概花了1s,而用BufferedInputStream包裝之後只需要60ms,效能提高了94%! 這個也適用於output stream操作以及socket操作。

正確的寫法:

InputStreamin=newBufferedInputStream(newFileInputStream(file));

11.無限使用heap記憶體

錯誤的寫法:

byte[] pdf = toPdf(file);

這裡有一個前提,就是檔案大小不能講JVM的heap撐爆。否則就等著OOM吧,尤其是在高併發的伺服器端程式碼。最好的做法是採用Stream的方式邊讀取邊儲存(本地檔案或database)。

正確的寫法:

Filepdf = toPdf(file);

另外,對於伺服器端程式碼來說,為了系統的安全,至少需要對檔案的大小進行限制。

12.不指定超時時間

錯誤的程式碼:

Socket socket = ...  
socket.connect(remote);  
InputStreamin= socket.getInputStream();  
inti =in.read();

這種情況在工作中已經碰到不止一次了。個人經驗一般超時不要超過20s。這裡有一個問題,connect可以指定超時時間,但是read無法指定超時時間。但是可以設定阻塞(block)時間。

正確的寫法:

Socket socket = ...  
socket.connect(remote,20000);// fail after 20s  
InputStreamin= socket.getInputStream();  
socket.setSoTimeout(15000);  
inti =in.read();

另外,檔案的讀取(FileInputStream, FileChannel, FileDescriptor, File)沒法指定超時時間, 而且IO操作均涉及到本地方法呼叫, 這個更操作了JVM的控制範圍,在分散式檔案系統中,對IO的操作內部實際上是網路呼叫。一般情況下操作60s的操作都可以認為已經超時了。為了解決這些問題,一般採用快取和非同步/訊息佇列處理。

13.頻繁使用計時器

錯誤程式碼:

for(...) {  
longt = System.currentTimeMillis();  
longt = System.nanoTime();  
Date d =newDate();  
Calendar c =newGregorianCalendar();  
}

每次new一個Date或Calendar都會涉及一次本地呼叫來獲取當前時間(儘管這個本地呼叫相對其他本地方法呼叫要快)。
如果對時間不是特別敏感,這裡使用了clone方法來新建一個Date例項。這樣相對直接new要高效一些。

正確的寫法:

Dated =newDate();  
for(E entity : entities) {  
entity.doSomething();  
entity.setUpdated((Date) d.clone());  
}

如果迴圈操作耗時較長(超過幾ms),那麼可以採用下面的方法,立即建立一個Timer,然後定期根據當前時間更新時間戳,在我的系統上比直接new一個時間物件快200倍:

privatevolatilelongtime;  
Timer timer =newTimer(true);  
try{  
time = System.currentTimeMillis();  
timer.scheduleAtFixedRate(

相關推薦

Java程式設計常見""彙總

每天在寫Java程式,其實裡面有一些細節大家可能沒怎麼注意,這不,有人總結了一個我們程式設計中常見的問題。雖然一般沒有什麼大問題,但是最好別這樣做。另外這裡提到的很多問題其實可以通過Findbugs( http://findbugs.sourceforge.net/ )來幫我們進行檢查出來。

Java程式設計常見低階錯誤整理

前言 本文件根據java開發人員在編碼過程中容易忽視或經常出錯的地方進行了整理,總結了十個比較常見的低階錯誤點,方便大家學習。 一:使用“ == ”比較兩個String物件是否相等         兩個字串在比較內容是否相等的時候,如果使用“==”,當兩個字串不是指向記憶體

JAVA程式設計常見錯誤集錦2

32, car is not mapped  可能1: 在cfg.xml中沒有增加對映的hbm.xml檔案在<mapping.../>中 33, 屬性沒有找到  可能1: hbm.xml檔案中的 <property name =""> 有問題, 也許是name的值與對應類中的成員名

Java高併發程式設計 JDK併發包

1. 重入鎖  重入鎖可以完全替代synchronized關鍵字。使用java.util.concurrent.locks.ReentrantLock類實現,下面是一個重入鎖的簡單例子: package cn.net.bysoft.java.concurrency.desi

Java 分頁與原理

現在 分享圖片 inf bubuko 9.png 原理 src 查詢 mage Java web 實習需要用到分頁技術 所以現在學習一下 做個記錄 方便以後查閱 分類:傳統分頁技術 下拉式分頁技術 起始位置(0)開始 查詢(10條記錄)

最全java架構師技能圖譜

線程數 分支 選擇排序 linu 系統 窮舉 熱部署 batis err java架構師最全技能圖譜上篇,包含:數結構算法、java進階、web開發、框架與工具四大技能圖譜。下篇將包含大數據以及性能、設計模式、UML、中間件、分布式集群、負載均衡、通訊協議、架構設計等技術圖

Java中JNI的使用

android immediate 返回值 str byte 文件 field 方式 touch JNI 全稱是 Java Native Interface。是在 Java 和 Native 層(包括但不限於C/C++)相互調用的接口規範。 JNI 在 Java 1.1中正

c語言程式設計常見問題總結1

總結1: 將全域性變數放在會被多次呼叫的標頭檔案中,編譯會報錯:該變數被多次定義,所以是最好把全域性變數放在.c檔案中。 總結2:  Getche()函式,輸入後立即從控制檯取字元,不以回車為結束(帶回顯); Getch()是一個不回顯函式,當用戶按下某個字元時,函式自動讀

JAVA程式設計思想學習筆記

物件導論 1.1 抽象過程 Smalltalk的五個基本特性: 萬物皆為物件。 程式是物件的集合,它通過傳送訊息來告知彼此所要做的。 每個物件都有自己的由其他物件所構成的儲存。 每個物件都有其型別。 某一特定型別的所有物件都可以接受同樣的訊息。

java學習day21~23--MySQL

關於SQL  結構化查詢語言  structured query language sql語句對於不同的資料庫有微小差異 資料語言     1.DDL  資料定義語言       

前端常用外掛、工具類庫彙總

前言 在開發中,我們經常會將一些常用的程式碼塊、功能塊進行封裝,為的是更好的複用。那麼,被抽離出來獨立完成功能,通過API或配置項和其他部分互動,便形成了外掛。 下面這些是我在工作中積累的一些常用的前端開源外掛,這裡只是羅列出來,詳細的用法各個外掛官網或者Gayhub都有介紹。注意:往往一個解決方案會

JavaSE之面向物件程式設計—類與物件

1.面向物件程式設計簡介: [點一下就可以看到這個內容喲] (https://blog.csdn.net/ZhuiZhuDream5/article/details/83831961) 2.類與物件的定義與使用: [帶你進一步走進java] (https://blog.csdn.net/Zh

JavaSE之面向物件程式設計—類與物件—— 5

首先我們來認識一下static關鍵字表示什麼:static關鍵字表示靜態的意思,更加通俗的解釋就是static修飾屬性或者方法它表示類的屬性或者方法,而前面所學的都表示物件的熟悉感或者方法。下面我們將從兩個方面來介紹static關鍵字。 一、static屬性 static屬性也叫類屬性,對於

JavaSE之面向物件程式設計—類與物件—— 4

一、首先介紹一下this關鍵字的用法: 總的來說this共有三類用法: 1.this呼叫本類屬性 2.this呼叫本類方法 3.this表示當前物件 下面通過栗子來具體的解釋每種用法: 1.this呼叫本類屬性 注意:一個檔案只能有一個公有的類,並且檔名應該和公有的類名一致;如果定義一個類沒

JavaSE之面向物件程式設計—類與物件—— 3

一、private實現封裝處理和構造方法(匿名物件) 1.private實現封裝處理 封裝是java的一大特性,private只是為實現封裝處理做了一個鋪墊。我們之所以存在封裝是因為封裝可以是我們的程式更加的有序,更加的安全private它表示私有化,它可以幫助我們實現面向物件的這一特性。

Java面試之基礎篇

題目來源於網路 後面是筆者自己提供的答案,僅供參考,如有錯誤,歡迎指正   一、基礎篇 1.1、Java基礎  面向物件的特徵:繼承、封裝和多型 final, finally, finalize 的區別 Exception、Er

java常見面試題彙總

本期的java面試題是偏向資料庫方面的,對相關技術知識匱乏的,或者對這方面不大自信的同學,面試之前可以參考一下這套題,這只是節選,試運營一下,如果不能滿足你們的需求,可以直接評論留言!  1、檢視的優缺點 答:優點: 1)對資料庫的訪問,因為檢視可以有選擇性的選取資料庫裡的一部分。 2 )使用者

Java常見面試題彙總:spring框架

今天分享的java實習生常見面試題,是spring專場,主要是針對spring總結的面試題,有需要的小夥伴可以收入囊中了!   1、 Spring Framework 中有多少個模組,它們分別是什麼? Spring 核心容器 – 該層基本上是 Spring Framework 的核心。它包含以

最新支援java8的Java反編譯工具彙總大全!!

大多商業軟體,會對程式進行加密、加殼等安全措施以防範軟體被破解,從而使得反編譯越來越難。反編譯是一個對目標可執行程式進行逆向分析,從而得到原始碼的過程。尤其是像Java這樣的執行在虛擬機器上的程式語言,更容易進行反編譯得到原始碼。       我

Java常見面試題彙總

今天總結的是java框架相關的面試題,有需要的可以繼續拿去了。  1、J2EE 是什麼? 答:J2EE 是Sun 公司提出的多層(multi-diered),分散式(distributed),基於元件(component-base)的企業級應用模型(enterpriese application