10個(gè)實(shí)用的但偏執(zhí)的Java編程技術(shù)_3

背景:


閱讀新聞

10個(gè)實(shí)用的但偏執(zhí)的Java編程技術(shù)

[日期:2015-08-31]

來源:碼農(nóng)網(wǎng)

作者:小峰

[字體:大 中 小]

在沉浸于編碼一段時(shí)間以后(比如說我已經(jīng)投入近20年左右的時(shí)間在程序上了),你會(huì)漸漸對(duì)這些東西習(xí)以為常。因?yàn)?你知道的……

任何事情有可能出錯(cuò),沒錯(cuò),的確如此。

這就是為什么我們要采用“防御性編程”,即一些偏執(zhí)習(xí)慣的原因。下面是我個(gè)人認(rèn)為的10個(gè)最有用但偏執(zhí)的Java編程技術(shù)。一起來看一看吧:

1.將String字符串放在最前面

為了防止偶發(fā)性的 異常,我們通常將String放置在equals()函數(shù)的左邊來實(shí)現(xiàn)字符串比較,如下代碼:

// Bad

if (variable.equals("literal")) { ... }

// Good

if ("literal".equals(variable)) { ... }

這是隨便用腦子想想就可以做的事,從Bad版本的代碼改寫表達(dá)式到Good版本的代碼,這中間并不會(huì)丟失任何東西。歡迎不同的觀點(diǎn)…

2.不要相信早期的JDK API

在Java早期,編程是一件非常痛苦的事情。那些API仍然很不成熟,也許你已經(jīng)碰到過下面的代碼塊:

String[] files=file.list();

// Watch out

if (files !=null) {

for (int i=0; i < files.length; i++) {

...

}

}

看上去很偏執(zhí)?也許吧,但請(qǐng)看Javadoc:

如果這個(gè)虛擬路徑不表示一個(gè)文件夾目錄,則此方法返回null。否則將會(huì)返回一個(gè)字符串?dāng)?shù)組,每一個(gè)字符串表示目錄中的文件或文件夾。

對(duì),沒錯(cuò)。我們可以添加一些校驗(yàn):

if (file.isDirectory()) {

String[] files=file.list();

// Watch out

if (files !=null) {

for (int i=0; i < files.length; i++) {

...

}

}

}

3.不要相信“-1”

我知道這是偏執(zhí)的,但Javadoc中對(duì) String.indexOf()方法明確指出:對(duì)象內(nèi)第一次出現(xiàn)指定字符的位置索引,如果為-1則表示該字符不在字符序列中。

所以使用-1是理所當(dāng)然的,對(duì)嗎?我說不對(duì),請(qǐng)看以下代碼:

// Bad

if (string.indexOf(character) !=-1) { ... }

// Good

if (string.indexOf(character) >=0) { ... }

誰知道呢。也許到時(shí)候他們改變了編碼方式,對(duì)字符串并不區(qū)分大小寫,也許更好的方式是返回-2?誰知道呢。

4.避免意外賦值

是的。這種事情也許經(jīng)常會(huì)發(fā)生。

// Ooops

if (variable=5) { ... }

// Better (because causes an error)

if (5=variable) { ... }

// Intent (remember. Paranoid JavaScript:===)

if (5===variable) { ... }

所以你可以將比較常量放置在左側(cè),這樣就不會(huì)發(fā)生意外賦值的錯(cuò)誤了。

5.檢查Null和Length

無論如何,只要你有一個(gè)集合、數(shù)組等,請(qǐng)確保它存在,并且不為空。

// Bad

if (array.length > 0) { ... }

// Good

if (array !=null && array.length > 0) { ... }

你并不知道這些數(shù)組從哪里來,也許是來自早期版本的JDK API,誰知道呢。

6.所有的方法都是final的

你也許會(huì)告訴我你的開/閉原則,但這都是胡說八道。我不相信你(正確繼承我這個(gè)父類的所有子類),我也不相信我自己(不小心繼承我這個(gè)父類的所有子類)。所以對(duì)于那些意義明確的方法要嚴(yán)格用final標(biāo)識(shí)。

// Bad

public void boom() { ... }

// Good. Do九度快排系統(tǒng) https://www.190seo.comn't touch.

public final void dontTouch() { ... }

7.所有變量和參數(shù)都是final

就像我說的。我不相信我自己(不要意外覆蓋我的值)。話雖如此,我不相信我自己的是因?yàn)椤?/p>

…這就是為什么所有的變量和參數(shù)都是final的原因。

// Bad

void input(String importantMessage) {

String answer="...";

answer=importantMessage="LOL accident";

}

// Good

final void input(final String importantMessage) {

final String answer="...";

}

8.重載時(shí)不要相信泛型

是,它可以發(fā)生。你相信你寫的超級(jí)好看的API,它很直觀,隨之而來的,一些用戶誰只是將原始類型轉(zhuǎn)換成Object類型,直到那該死的編譯器停止發(fā)牢騷,并且突然他們會(huì)鏈接錯(cuò)誤的方法,以為這是你的錯(cuò)誤。

看下面的代碼:

// Bad

void bad(T value) {

bad(Collections.singletonList(value));

}

void bad(List values) {

...

}

// Good

final void good(final T value) {

if (value instanceof List)

good((List>) value);

else

good(Collections.singletonList(value));

}

final void good(final List values) {

...

}

因?yàn)?你知道……你的用戶,他們就像

// This library sucks

@SuppressWarnings("all")

Object t=(Object) (List) Arrays.asList("abc");

bad(t);

相信我。這一切我都看到過。包括下面的

這種偏執(zhí)還是不錯(cuò)的。

9.總是在Switch語句的Default中拋出異常

Switch語句……它們其中一個(gè)可笑的語句我不知道該對(duì)它敬畏還是哭泣,但無論如何,既然我們堅(jiān)持用switch,那我們不妨將它用得完美,看下面的代碼:

// Bad

switch (value) {

case 1: foo(); break;

case 2: bar(); break;

}

// Good

switch (value) {

case 1: foo(); break;

case 2: bar(); break;

default:

throw new ThreadDeath("That'll teach them");

}

當(dāng)value==3時(shí),將會(huì)出現(xiàn)無法找到的提示,而不會(huì)讓人不知所謂。

10.Switch語句帶花括號(hào)

事實(shí)上,switch是最邪惡的語句,像是一些喝醉了或者賭輸了的人在寫代碼一樣,看下面的例子:

// Bad, doesn't compile

switch (value) {

case 1: int j=1; break;

case 2: int j=2; break;

}

// Good

switch (value) {

case 1: {

final int j=1;

break;

}

case 2: {

final int j=2;

break;

}

// Remember:

default:

throw new ThreadDeath("That'll teach them");

}

在switch語句中,每一個(gè)case語句的范圍只有一行語句,事實(shí)上,這些case語句甚至不是真正的語句,他們就像goto語句中的跳轉(zhuǎn)標(biāo)記一樣。

結(jié)論

偏執(zhí)編程看起來似乎不可思議,有時(shí),因?yàn)榇a經(jīng)常被證明是更詳細(xì)一點(diǎn),但并不是需求需要。你可能會(huì)想,“哦,這是絕不會(huì)發(fā)生的”,但正如我所說。經(jīng)過20年左右的時(shí)間編程,你不希望只修復(fù)這些愚蠢的bug,因?yàn)榫幊陶Z言是如此的陳舊的和有缺陷的。因?yàn)槟阒馈?/p>

現(xiàn)在到你了!什么是你在編程最偏執(zhí)的怪癖?

本文永久更新鏈接地址:http://www.linuxidc.com/Linux/2015-08/122523.htm

linux

八成Java開發(fā)者解答不了的問題

Java程序性能優(yōu)化之代理模式

相關(guān)資訊

Java編程 Java編程技術(shù)

Java 老矣,尚能飯否? (今 19:38)

Java 并發(fā)編程中使用 ReentrantLoc (12/05/2015 22:49:19)

Java:過去、未來的互聯(lián)網(wǎng)編程之王 (07/31/2015 14:50:02)

Java編程基本概念 (03月07日)

for(int a:i)在Java 編程中的使用 (08/24/2015 07:29:34)

Java編程思想學(xué)習(xí)筆記——泛型 (07/04/2015 13:46:39)

本文評(píng)論

查看全部評(píng)論 (0)

表情: 表情

姓名:

匿名

字?jǐn)?shù)

同意評(píng)論聲明

評(píng)論聲明

尊重網(wǎng)上道德,遵守中華人民共和國(guó)的各項(xiàng)有關(guān)法律法規(guī)

承擔(dān)一切因您的行為而直接或間接導(dǎo)致的民事或刑事法律責(zé)任

本站管理人員有權(quán)保留或刪除其管轄留言中的任意內(nèi)容

本站有權(quán)在網(wǎng)站內(nèi)轉(zhuǎn)載或引用您的評(píng)論

參與本評(píng)論即表明您已經(jīng)閱讀并接受上述條款

最新資訊

Java 老矣,尚能飯否?

Google 再次從官方商店下架偽裝成合法程序

一銘桌面操作系統(tǒng)4.0 SP1安裝使用初體驗(yàn)

Opus 1.2發(fā)布,開源免專利費(fèi)音頻編解碼器

Java中抽象類的定義和使用

Java實(shí)現(xiàn)內(nèi)部類

C語言如何分離一個(gè)數(shù)的高低位,如何將兩個(gè)

C語言之鞍點(diǎn)的查找

C語言實(shí)現(xiàn)牛頓迭代法解方程

Android編譯系統(tǒng)產(chǎn)品線(基于友善之臂

背景:

閱讀新聞

Java程序性能優(yōu)化之代理模式

[日期:2015-08-31]

來源:Linux社區(qū)

作者:kimoyoyo21

[字體:大 中 小]

代理模式的用處很多,有的是為了系統(tǒng)安全,有的是為了遠(yuǎn)程調(diào)用,這里我們,主要探討下由于程序性能優(yōu)化的延遲加載。

首先我們來看下代理模式設(shè)計(jì)

先首先簡(jiǎn)單闡述下什么叫代理模式吧

代理設(shè)計(jì)模式有一個(gè)接口,另外還有真實(shí)主題類和代理類,真實(shí)類和代理類都實(shí)現(xiàn)了接口,代理類和真實(shí)主題類是關(guān)聯(lián)和聚合關(guān)系。客戶端與接口關(guān)聯(lián)。

代理分為靜態(tài)代理和動(dòng)代態(tài)代理所謂靜態(tài)代理是為真實(shí)主題手動(dòng)創(chuàng)建一個(gè)代理,而動(dòng)態(tài)代理則是jvm在運(yùn)行時(shí)運(yùn)用字節(jié)碼加載技術(shù)自動(dòng)創(chuàng)建一個(gè)代理,并不用關(guān)心接口和真是主題類

具體如何實(shí)現(xiàn)

哦,對(duì)了差點(diǎn)忘了。代理模式到底是怎樣優(yōu)化程序的,我們具體來看下。

客戶端測(cè)試代碼如下:

public class TestDynamicProxy {

public static void main(String[] args) {

IDBQuery iy=JdkDBqueryHandler.createJdkProxy();

System.out.println(iy.request());

}

}

Ps:客戶端與接口關(guān)聯(lián)

代理實(shí)現(xiàn)和邏輯處理類如下:

import java.lang.reflect.*;

public class JdkDBqueryHandler implements InvocationHandler{

IDBQuery real=null;

public Object invoke(Object object, Method method ,Object[] args ) {

if(real==null) {

real=new DBQuery();

}

return real.request();

}

public static IDBQuery createJdkProxy() {

IDBQuery jdkProxy=(IDBQuery)Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),new Class[]{IDBQuery.class},new JdkDBqueryHandler());

return jdkProxy;

}

}

Ps:代理實(shí)現(xiàn)和邏輯處理類是實(shí)現(xiàn)延遲加載的關(guān)鍵代碼

當(dāng)客戶端開始加載時(shí)會(huì)加載到代碼實(shí)現(xiàn)和邏輯處理類并創(chuàng)建代理實(shí)例,但并不會(huì)初始化真實(shí)主題類。只有當(dāng)調(diào)用iy.request()方法時(shí)才會(huì)執(zhí)行代理實(shí)現(xiàn)和邏輯處理類的invoke()方法并加載并初始化真實(shí)主題類。這樣才實(shí)現(xiàn)了延遲加載,減少系統(tǒng)初始化時(shí)間,提高用戶體驗(yàn)。在一定程度上也可以節(jié)約內(nèi)存空間,避免內(nèi)存空間浪費(fèi),(因?yàn)橛玫臅r(shí)候才記載初始化的嘛,不用也開辟內(nèi)存空間那不是浪費(fèi)了嘛)

這里另外附上接口類和真實(shí)主題類的代碼,方便大家測(cè)試

接口類

public interface IDBQuery {

String request();

}

真實(shí)主題類

public class DBQuery implements IDBQuery {

public DBQuery() {

try{

Thread.sleep(1000);

}catch(InterruptedException e) {

e.printStackTrace();

}

}

public String request() {

return "request coming";

}

}

以上是jdk自帶的動(dòng)態(tài)代理實(shí)現(xiàn) 另外還有較流行的CGLIB動(dòng)態(tài)代理,javaassist動(dòng)態(tài)代理

這里我先介紹一下CGLIB動(dòng)態(tài)代理。CGLIB動(dòng)態(tài)代理和jdk的動(dòng)態(tài)代理非常的相似,我們來看下具體的代碼

客戶端代碼如下:

public class TestDynamicProxy {

public static void main(String[] args) {

IDBQuery iy=CglibDbQueryInterceptor.createCglibProxy();

System.out.println(iy.request());

}

}

這里不過多解釋,看完上面的例子相信大家都明白了

代理實(shí)現(xiàn)和邏輯處理類如下

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;

import net.sf.cglib.proxy.MethodInterceptor;

import net.sf.cglib.proxy.MethodProxy;

public class CglibDbQueryInterceptor implements MethodInterceptor{

IDBQuery real=null;

public Object intercept(Object args0,Method arg1,Object[] args2,MethodProxy args3)throws Throwable {

if(real==null) {

real=new DBQuery();

}

return real.request();

}

public static IDBQuery createCglibProxy() {

Enhancer eh=new Enhancer();

eh.setCallback(new CglibDbQueryInterceptor());//指定切入器,定義代理類邏輯

eh.setInterfaces(new Class[]{IDBQuery.class});//指定接口

IDBQuery proxy=(IDBQuery)eh.create();//創(chuàng)建代理實(shí)例

return proxy;

}

}

Jdk 的動(dòng)態(tài)代理和 CGLIB 實(shí)現(xiàn)動(dòng)態(tài)代理大致都要指定代理類邏輯和代理接口這是共性

真實(shí)主題類和接口和上例一樣,不再貼了

JavaAssist 的動(dòng)態(tài)代理有兩種實(shí)現(xiàn)方法,一種使用代理工廠,一種使用動(dòng)態(tài) java 代碼生成字節(jié)碼

這里就直接貼代碼了:

圖片上傳失敗~~~

Ps: 以上實(shí)例方法在在邏輯處理類中處理類 , 真實(shí)主題類和接口和上面例子相同

代理工廠指定接口后生成代理類對(duì)象,代理類對(duì)象再指定處理邏輯。

大致三者都相似, javaAssist 動(dòng)態(tài) java 代碼生成字節(jié)碼就不介紹了,趕覺較麻煩

另有 ASM 動(dòng)態(tài)代理實(shí)現(xiàn)起來比較復(fù)雜,也不介紹。

本文永久更新鏈接地址:http://www.linuxidc.com/Linux/2015-08/122524.htm

linux

10個(gè)實(shí)用的但偏執(zhí)的Java編程技術(shù)

Linux 下C語言編程庫文件處理與Makefile編寫

相關(guān)資訊

Java代理模式

對(duì)Java代理模式的理解 (今 10:30)

Java中的代理模式 (01月26日)

Java動(dòng)態(tài)代理模式(從現(xiàn)實(shí)生活角度 (12/22/2016 08:37:59)

Java設(shè)計(jì)模式之代理模式詳述 (09月15日)

Java代理模式之動(dòng)態(tài)代理 (01月02日)

Java靜態(tài)代理模式(從現(xiàn)實(shí)生活角度 (12/22/2016 08:29:12)

本文評(píng)論

查看全部評(píng)論 (0)

表情: 表情

姓名:

匿名

字?jǐn)?shù)

同意評(píng)論聲明

評(píng)論聲明

尊重網(wǎng)上道德,遵守中華人民共和國(guó)的各項(xiàng)有關(guān)法律法規(guī)

承擔(dān)一切因您的行為而直接或間接導(dǎo)致的民事或刑事法律責(zé)任

本站管理人員有權(quán)保留或刪除其管轄留言中的任意內(nèi)容

本站有權(quán)在網(wǎng)站內(nèi)轉(zhuǎn)載或引用您的評(píng)論

參與本評(píng)論即表明您已經(jīng)閱讀并接受上述條款

最新資訊

對(duì)Java代理模式的理解

pnp4nagios的安裝

MySQL的SQL_MODE

Oracle Linux 7.4 安裝 Oracle 12C

Jenkins服務(wù)器搭建指南-官方文檔翻譯整理

傳 Google 將提供取代兩階段認(rèn)證的「進(jìn)階防

Google Photos 可以讓網(wǎng)速慢的地方也能分享

微軟終于放棄自家音樂服務(wù),原 Groove

三星也加入 Windows MR 設(shè)備戰(zhàn)團(tuán)

微軟收購了 AltspaceVR 虛擬現(xiàn)實(shí)社交平臺(tái)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,624評(píng)論 18 399
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,506評(píng)論 19 139
  • 小編費(fèi)力收集:給你想要的面試集合 1.C++或Java中的異常處理機(jī)制的簡(jiǎn)單原理和應(yīng)用。 當(dāng)JAVA程序違反了JA...
    八爺君閱讀 5,172評(píng)論 1 114
  • 我們來繼續(xù)這個(gè)系列,今天給大家講下IM的云旺IM快速接入,當(dāng)然也順便推薦講下其他的IM。 文章結(jié)構(gòu):(1)IM的介...
    JackFrost_fuzhu閱讀 857評(píng)論 0 5
  • 雕刻的夜版(原創(chuàng)) 我存在,我不語。我不語,我依舊在。在這里,仿佛山間一道小溪,仿如水岸一株紅柳,街邊游行的沙礫,...
    秋色文學(xué)烈火的輕云閱讀 152評(píng)論 0 0

友情鏈接更多精彩內(nèi)容