成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

Java編程中最容易忽略的10個(gè)常見(jiàn)問(wèn)題分別有哪些

本篇文章給大家分享的是有關(guān)Java編程中最容易忽略的10個(gè)常見(jiàn)問(wèn)題分別有哪些,小編覺(jué)得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說(shuō),跟著小編一起來(lái)看看吧。

創(chuàng)新互聯(lián)建站2013年開(kāi)創(chuàng)至今,先為薩迦等服務(wù)建站,薩迦等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢服務(wù)。為薩迦企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問(wèn)題。

在Java編碼中,我們?nèi)菀追敢恍╁e(cuò)誤,也容易疏忽一些問(wèn)題,因此筆者對(duì)日常編碼中曾遇到的一些經(jīng)典情形歸納整理成文,以共同探討。

Java編程中最容易忽略的10個(gè)常見(jiàn)問(wèn)題分別有哪些

1. 糾結(jié)的同名

現(xiàn)象

很多類(lèi)的命名相同(例如:常見(jiàn)于異常、常量、日志等類(lèi)),導(dǎo)致在import時(shí),有時(shí)候張冠李戴,這種錯(cuò)誤有時(shí)候很隱蔽。因?yàn)橥念?lèi)功能也類(lèi)似,所以IDE不會(huì)提示warn。

解決

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

啟示

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

2. 想當(dāng)然的API

現(xiàn)象

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

示例一: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);

解決辦法

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

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

啟示

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

3. 有時(shí)候溢出并不難

現(xiàn)象

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

示例一:

long x=Integer.MAX_VALUE+1;
System.out.println(x);

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

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

示例二:

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

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

解決

  1. 讓***個(gè)操作數(shù)是long型,例如加上L或者l(不建議小寫(xiě)字母l,因?yàn)楹蛿?shù)字1太相似了);

  2. 不確定時(shí),還是使用重載吧,即使用doubleValue(),當(dāng)參數(shù)是BigDecimal參數(shù)時(shí),也不能解決問(wèn)題。

啟示

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

4. 日志跑哪了?

現(xiàn)象

有時(shí)候覺(jué)得log都打了,怎么找不到?

示例一:沒(méi)有stack trace!

} catch (Exception ex) {
    log.error(ex);
}

示例二:找不到log!

} catch (ConfigurationException e) {
    e.printStackTrace();
}

解決

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

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

啟示

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

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

5. 遺忘的Volatile

現(xiàn)象

在DCL模式中,總是忘記加一個(gè)Volatile。

private static CacheImpl instance;  //lose volatile
public static CacheImpl getInstance() {
    if (instance == null) {
        synchronized (CacheImpl.class) {
            if (instance == null) {
                instance = new CacheImpl ();
            }
        }
    }
    return instance;
}

解決

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

啟示

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

6. 不要影響彼此

現(xiàn)象

在釋放多個(gè)IO資源時(shí),都會(huì)拋出IOException ,于是可能為了省事如此寫(xiě):

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)閉嗎?當(dāng)然不能!

解決辦法

雖然拋出的是同一個(gè)異常,但是還是各自捕獲各的為好。否則***個(gè)失敗,后一個(gè)面就沒(méi)有機(jī)會(huì)去釋放資源了。

啟示

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

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

現(xiàn)象

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

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

解決

換成正常的統(tǒng)一的參數(shù)校驗(yàn)方法。因?yàn)閿嘌阅J(rèn)是關(guān)閉的,所以起不起作用完全在于配置,如果采用默認(rèn)配置,經(jīng)歷了eventList != null結(jié)果還沒(méi)有起到作用,徒勞無(wú)功。

啟示

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

8. 用戶認(rèn)知負(fù)擔(dān)有時(shí)候很重

現(xiàn)象

先來(lái)比較三組例子,看看那些看著更順暢?

示例一:

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.delete(key);
public boolean delete(String key, long timeout) {
             Future< Boolean> future = memcachedClient.delete(key);

示例三:

public static String getDigest(String filePath, DigestAlgorithm algorithm)
public static String getDigest(String filePath, DigestAlgorithm digestAlgorithm)

解決

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

  2. remove變成了delete,顯得突兀了點(diǎn), 統(tǒng)一表達(dá)更好;

  3. 保持表達(dá),少縮寫(xiě)也會(huì)看起來(lái)流暢點(diǎn)。

啟示

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

9. 忽視日志記錄時(shí)機(jī)、級(jí)別

現(xiàn)象

存在下面兩則示例:

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

catch (SocketException e)
{
    LOG.error("server error", e);
    throw new ConnectionException(e.getMessage(), e);
}

示例二:記什么級(jí)別日志?

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

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

解決

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

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

啟示

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

  1. 是用戶行為錯(cuò)誤還是代碼錯(cuò)誤?

  2. 記錄下來(lái)的日志,能否能給別人在不造成過(guò)多的干擾前提下提供有用的信息以快速定位問(wèn)題。

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

現(xiàn)象

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

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

解決

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

  • memory for reference fields (4 bytes each);

  • memory for primitive fields

Java type

Bytes required

boolean

1

byte


char

2

short


int

4

float


long

8

double


啟示

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

在Java編程中,除了上面枚舉的一些容易忽視的問(wèn)題,日常實(shí)踐中還存在很多。

以上就是Java編程中最容易忽略的10個(gè)常見(jiàn)問(wèn)題分別有哪些,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見(jiàn)到或用到的。希望你能通過(guò)這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

當(dāng)前名稱(chēng):Java編程中最容易忽略的10個(gè)常見(jiàn)問(wèn)題分別有哪些
網(wǎng)站網(wǎng)址:http://jinyejixie.com/article32/gggcsc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供Google、微信小程序、用戶體驗(yàn)云服務(wù)器、做網(wǎng)站網(wǎng)頁(yè)設(shè)計(jì)公司

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

綿陽(yáng)服務(wù)器托管
黄石市| 开封县| 敖汉旗| 宣威市| 随州市| 常山县| 乐都县| 神池县| 花莲县| 毕节市| 贵港市| 巴林右旗| 鹰潭市| 长汀县| 嘉义县| 阳东县| 苏尼特左旗| 清流县| 桓仁| 鸡东县| 纳雍县| 怀安县| 江陵县| 遵义市| 武威市| 延边| 佛学| 和平区| 阿鲁科尔沁旗| 曲周县| 迁西县| 望都县| 梁河县| 黔西县| 沂水县| 禹州市| 松原市| 临西县| 旬邑县| 灵璧县| 长白|