亚欧洲精品在线观看,窝窝影院午夜看片,久久国产成人午夜av影院宅,午夜91,免费国产人成网站,ts在线视频,欧美激情在线一区

java語言

Java編程中最容易忽略的問題

時間:2025-03-31 21:03:46 java語言 我要投稿
  • 相關(guān)推薦

Java編程中最容易忽略的問題

  在Java編碼中,我們?nèi)菀追敢恍╁e誤,也容易疏忽一些問題,下面內(nèi)容由小編為大家介紹Java編程中最容易忽略的問題,供大家參考!

  1. 糾結(jié)的同名

  現(xiàn)象

  很多類的命名相同(例如:常見于異常、常量、日志等類),導(dǎo)致在import時,有時候張冠李戴,這種錯誤有時候很隱蔽。因為往往同名的類功能也類似,所以IDE不會提示warn。

  解決

  寫完代碼時,掃視下import部分,看看有沒有不熟悉的。替換成正確導(dǎo)入后,要注意下注釋是否也作相應(yīng)修改。

  啟示

  命名盡量避開重復(fù)名,特別要避開與JDK中的類重名,否則容易導(dǎo)入錯,同時存在大量重名類,在查找時,也需要更多的辨別時間。

  2. 想當然的API

  現(xiàn)象

  有時候調(diào)用API時,會想當然的通過名字直接自信滿滿地調(diào)用,導(dǎo)致很驚訝的一些錯誤:

  示例一:flag是true?

  boolean flag = Boolean.getBoolean("true");

  可能老是false。

  示例二:這是去年的今天嗎(今年是2012年,不考慮閏年)?結(jié)果還是2012年:

  Calendar calendar = GregorianCalendar.getInstance();

  calendar.roll(Calendar.DAY_OF_YEAR, -365);

  下面的才是去年:

  calendar.add(Calendar.DAY_OF_YEAR, -365);

  解決辦法

  問自己幾個問題,這個方法我很熟悉嗎?有沒有類似的API? 區(qū)別是什么?就示例一而言,需要區(qū)別的如下:

  Boolean.valueOf(b) VS Boolean.parseBoolean(b) VS Boolean.getBoolean(b);

  啟示

  名字起的更詳細點,注釋更清楚點,不要不經(jīng)了解、測試就想當然的用一些API,如果時間有限,用自己最為熟悉的API。

  3. 有時候溢出并不難

  現(xiàn)象

  有時候溢出并不難,雖然不常復(fù)現(xiàn):

  示例一:

  long x=Integer.MAX_VALUE+1;

  System.out.println(x);

  x是多少?竟然是-2147483648,明明加上1之后還是long的范圍。類似的經(jīng)常出現(xiàn)在時間計算:

  數(shù)字1×數(shù)字2×數(shù)字3…

  示例二:

  在檢查是否為正數(shù)的參數(shù)校驗中,為了避免重載,選用參數(shù)number, 于是下面代碼結(jié)果小于0,也是因為溢出導(dǎo)致:

  Number i=Long.MAX_VALUE;System.out.println(i.intValue()>0);

  解決

  讓第一個操作數(shù)是long型,例如加上L或者l(不建議小寫字母l,因為和數(shù)字1太相似了);

  不確定時,還是使用重載吧,即使用doubleValue(),當參數(shù)是BigDecimal參數(shù)時,也不能解決問題。

  啟示

  對數(shù)字運用要保持敏感:涉及數(shù)字計算就要考慮溢出;涉及除法就要考慮被除數(shù)是0;實在容納不下了可以考慮BigDecimal之類。

  4. 日志跑哪了?

  現(xiàn)象

  有時候覺得log都打了,怎么找不到?

  示例一:沒有stack trace!

  } catch (Exception ex) {

  log.error(ex);

  }

  示例二:找不到log!

  } catch (ConfigurationException e) {

  e.printStackTrace();

  }

  解決

  替換成log.error(ex.getMessage(),ex);

  換成普通的log4j吧,而不是System.out。

  啟示

  API定義應(yīng)該避免讓人犯錯,如果多加個重載的log.error(Exception)自然沒有錯誤發(fā)生

  在產(chǎn)品代碼中,使用的一些方法要考慮是否有效,使用e.printStackTrace()要想下終端(Console)在哪。

  5. 遺忘的Volatile

  現(xiàn)象

  在DCL模式中,總是忘記加一個Volatile。

  private static CacheImpl instance; //lose volatilepublic static CacheImpl getInstance() { if (instance == null) { synchronized (CacheImpl.class) { if (instance == null) {

  instance = new CacheImpl ();

  }

  }

  } return instance;

  }

  解決

  毋庸置疑,加上一個吧,synchronized 鎖的是一塊代碼(整個方法或某個代碼塊),保證的是這”塊“代碼的可見性及原子性,但是instance == null第一次判斷時不再范圍內(nèi)的。所以可能讀出的是過期的null。

  啟示

  我們總是覺得某些低概率的事件很難發(fā)生,例如某個時間并發(fā)的可能性、某個異常拋出的可能性,所以不加控制,但是如果可以,還是按照前人的“最佳實踐”來寫代碼吧。至少不用過多解釋為啥另辟蹊徑。

  6. 不要影響彼此

  現(xiàn)象

  在釋放多個IO資源時,都會拋出IOException ,于是可能為了省事如此寫:

  public static void inputToOutput(InputStream is, OutputStream os, boolean isClose) throws IOException {

  BufferedInputStream bis = new BufferedInputStream(is, 1024);

  BufferedOutputStream bos = new BufferedOutputStream(os, 1024);

  …. if (isClose) {

  bos.close();

  bis.close();

  }

  }

  假設(shè)bos關(guān)閉失敗,bis還能關(guān)閉嗎?當然不能!

  解決辦法

  雖然拋出的是同一個異常,但是還是各自捕獲各的為好。否則第一個失敗,后一個面就沒有機會去釋放資源了。

  啟示

  代碼/模塊之間可能存在依賴,要充分識別對相互的依賴。

  7. 用斷言取代參數(shù)校驗

  現(xiàn)象

  如題所提,作為防御式編程常用的方式:斷言,寫在產(chǎn)品代碼中做參數(shù)校驗等。例如:

  private void send(List< Event> eventList) { assert eventList != null;

  }

  解決

  換成正常的統(tǒng)一的參數(shù)校驗方法。因為斷言默認是關(guān)閉的,所以起不起作用完全在于配置,如果采用默認配置,經(jīng)歷了eventList != null結(jié)果還沒有起到作用,徒勞無功。

  啟示

  有的時候,代碼起不起作用,不僅在于用例,還在于配置,例如斷言是否啟用、log級別等,要結(jié)合真實環(huán)境做有用編碼。

  8. 用戶認知負擔有時候很重

  現(xiàn)象

  先來比較三組例子,看看那些看著更順暢?

  示例一:

  public void caller(int a, String b, float c, String d) {

  methodOne(d, z, b);

  methodTwo(b, c, d);

  }public void methodOne(String d, float z, String b) public void methodTwo(String b, float c, String d)

  示例二:

  public boolean remove(String key, long timeout) {

  Future< Boolean> future = memcachedClient.(key);public boolean (String key, long timeout) {

  Future< Boolean> future = memcachedClient.(key);

  示例三:

  public static String getDigest(String filePath, DigestAlgorithm algorithm)

  public static String getDigest(String filePath, DigestAlgorithm digestAlgorithm)

  解決

  保持參數(shù)傳遞順序;

  remove變成了,顯得突兀了點, 統(tǒng)一表達更好;

  保持表達,少縮寫也會看起來流暢點。

  啟示

  在編碼過程中,不管是參數(shù)的順序還是命名都盡量統(tǒng)一,這樣用戶的認知負擔會很少,不要要用戶容易犯錯或迷惑。例如用枚舉代替string從而不讓用戶迷惑到底傳什么string, 諸如此類。

  9. 忽視日志記錄時機、級別

  現(xiàn)象

  存在下面兩則示例:

  示例一:該不該記錄日志?

  catch (SocketException e)

  {

  LOG.error("server error", e); throw new ConnectionException(e.getMessage(), e);

  }

  示例二:記什么級別日志?

  在用戶登錄系統(tǒng)中,每次失敗登錄:

  LOG.warn("Failed to login by "+username+");

  解決

  移除日志記錄:在遇到需要re-throw的異常時,如果每個人都按照先記錄后throw的方式去處理,那么對一個錯誤會記錄太多的日志,所以不推薦如此做;但是如果re-throw出去的exception沒有帶完整的trace( 即cause),那么最好還是記錄下。

  如果惡意登錄,那系統(tǒng)內(nèi)部會出現(xiàn)太多WARN,從而讓管理員誤以為是代碼錯誤?梢苑答佊脩粢藻e誤,但是不要記錄用戶錯誤的行為,除非想達到控制的目的。

  啟示

  日志改不改記?記成什么級別?如何記?這些都是問題,一定要根據(jù)具體情況,需要考慮:

  是用戶行為錯誤還是代碼錯誤?

  記錄下來的日志,能否能給別人在不造成過多的干擾前提下提供有用的信息以快速定位問題。

  10. 忘設(shè)初始容量

  現(xiàn)象

  在JAVA中,我們常用Collection中的Map做Cache,但是我們經(jīng)常會遺忘設(shè)置初始容量。

  cache = new LRULinkedHashMap< K, V>(maxCapacity);

  解決

  初始容量的影響有多大?拿LinkedHashMap來說,初始容量如果不設(shè)置默認是16,超過16×LOAD_FACTOR,會resize(2 * table.length),擴大2倍:采用 Entry[] newTable = new Entry[newCapacity]; transfer(newTable),即整個數(shù)組Copy, 那么對于一個需要做大容量CACHE來說,從16變成一個很大的數(shù)量,需要做多少次數(shù)組復(fù)制可想而知。如果初始容量就設(shè)置很大,自然會減少resize, 不過可能會擔心,初始容量設(shè)置很大時,沒有Cache內(nèi)容仍然會占用過大體積。其實可以參考以下表格簡單計算下, 初始時還沒有cache內(nèi)容, 每個對象僅僅是4字節(jié)引用而已。

  memory for reference fields (4 bytes each);

  memory for primitive fields

  Java typeBytes required

  boolean1

  byte

  char2

  short

  int4

  float

  long8

  double

  啟示

  不僅是map, 還有stringBuffer等,都有容量resize的過程,如果數(shù)據(jù)量很大,就不能忽視初始容量可以考慮設(shè)置下,否則不僅有頻繁的 resize還容易浪費容量。

  在Java編程中,除了上面枚舉的一些容易忽視的問題,日常實踐中還存在很多。相信通過不斷的總結(jié)和努力,可以將我們的程序完美呈現(xiàn)給讀者。


【Java編程中最容易忽略的問題】相關(guān)文章:

雅思考試中最容易忽略的3大問題08-14

Java編程常見問題07-19

Java編程的常見問題05-15

Java編程常見問題匯總06-12

Java編程語言在什么行業(yè)應(yīng)用中最搶手01-10

java編程中的一些共同的問題03-04

科目二最容易忽略的問題有哪些08-09

java編程基礎(chǔ)07-26

java編程術(shù)語03-09