日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

java最小访问原则_Android基础进阶之EffectiveJava翻译系列(第七章:通用原则)

發(fā)布時間:2025/3/21 Android 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java最小访问原则_Android基础进阶之EffectiveJava翻译系列(第七章:通用原则) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

本章主要討論語言的具體內(nèi)容。它討論了局部變量的處理、控制結(jié)構(gòu)、庫的使用、各種數(shù)據(jù)類型的使用,以及使用反射和本地方法。最后,討論了優(yōu)化和命名約定

Item 45:最小化局部變量作用域

作用域:一個花括號{}包裹起來的區(qū)域

此條例同Item13相似:最小化類和成員變量的訪問權(quán)限

Java允許你在任何地方聲明變量,但是最重要的是在首次使用的地方聲明變量,并初始化

循環(huán)提供了一種實現(xiàn)此種方式的機制,而且for循環(huán)比while循環(huán)好,如

for (Element e : c) {

doSomething(e);

}

//before JDK1.5

for (Iterator i = c.iterator(); i.hasNext(); ) {

doSomething((Element) i.next());

}

為什么for比while好呢?

//bad

Iteratori = c.iterator();

while (i.hasNext()) {

doSomething(i.next());

}

...

Iteratori2 = c2.iterator();

while (i.hasNext()) { // BUG! 應(yīng)該是i2

doSomethingElse(i2.next());

}

當(dāng)我們寫一個差不多的代碼,從一個地方copy過來的時候,很有可能忘記修改某個變量值(如i2),它不會在編譯期報錯,我們很可能長時間遺留這個bug

使用for循環(huán)可以避免這個bug

for (Iteratori = c.iterator(); i.hasNext(); ) {

doSomething(i.next());

}

...

// Compile-time error - cannot find symbol i

for (Iteratori2 = c2.iterator(); i.hasNext(); ) {

doSomething(i2.next());

}

這就是最小化作用域的好處

Item 46: Prefer for-each loops to traditional for loops

對于不需要下標(biāo)來做特殊操作的遍歷,推薦使用增強for循環(huán)

你能發(fā)現(xiàn)下面的bug嗎?

enum Suit { CLUB, DIAMOND, HEART, SPADE }

enum Rank { ACE, DEUCE, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT,

NINE, TEN, JACK, QUEEN, KING }

...

Collectionsuits = Arrays.asList(Suit.values());

Collectionranks = Arrays.asList(Rank.values());

Listdeck = new ArrayList();

for (Iteratori = suits.iterator(); i.hasNext(); )

for (Iteratorj = ranks.iterator(); j.hasNext(); )

deck.add(new Card(i.next(), j.next()));

...

...

...

...

...

...

發(fā)現(xiàn)不了也不要難過,很多有經(jīng)驗的程序員也會犯這個錯誤

原因在于i.next()會被重復(fù)調(diào)用,導(dǎo)致結(jié)果異常

可以修復(fù)如下

for (Iteratori = suits.iterator(); i.hasNext(); ){

Suit suit = i.next();

for (Iteratorj = ranks.iterator(); j.hasNext(); )

deck.add(new Card(suit, j.next()));

}

雖然解決了問題,但是很丑,更簡潔的寫法如下

for (Suit suit : suits)

for (Rank rank : ranks)

deck.add(new Card(suit, rank));

盡可能的使用增強for循環(huán)

Item 47: Know and use the libraries

不要重復(fù)造輪子

如果需要一個常用的功能,去發(fā)現(xiàn)一個庫并使用它,往往比自己寫的要好

因為庫會隨著時間推移更新迭代越來越好,自己也節(jié)約了時間

這并不會評論一個人的能力

Item 48: Avoid float and double if exact answers are required

當(dāng)需要一個精確的答案時,避免使用float或double類型的變量

float或double是為了科學(xué)和工程計算而設(shè)計的,特別不適用于貨幣計算

推薦使用int或long代替

Item 49: Prefer primitive types to boxed primitives

使用原始類型替代裝箱類型

byte short char int long float double boolbean等是Java中的基本類型,也有對應(yīng)的裝箱類型,如 Integer, Double, and Boolean.應(yīng)當(dāng)謹(jǐn)慎對待這兩者之間的差別

首先第一個差別,原始類型僅僅包含對應(yīng)的值,裝箱類型既包含對應(yīng)的值也有對應(yīng)的引用,第二個差別是裝箱類型有可能為null,第三個差別是原始類型在時間和空間消耗中更高效

Item 50: Avoid strings where other types are more appropriate

如果有更合適的類型,避免使用String

string被設(shè)計成描述文本類型的數(shù)據(jù),而且干得很好,本章主要討論將string用于其它情況的錯誤用法

string不能替代值類型 如果我們正在等待鍵盤的輸入,或者從網(wǎng)絡(luò)獲取某個值,我們很方便的使用string作為接收類型,但是如果我們輸入的是數(shù)字或者真假值的話,對應(yīng)的int或boolean能更好的標(biāo)識輸入 雖然這條規(guī)則很明顯,但是經(jīng)常被違反

string不能替代枚舉 如Item30:枚舉討論的那樣,對于靜態(tài)常量使用枚舉

string不能替代聚合字符

String compoundKey = className + "#" + i.next();//bad

我們經(jīng)常寫上述代碼,這樣的寫法有很多缺點.如果我們想使用某一部分字段需要解析字符串,很耗時而且容易出錯.String提供的equals,compareTo等方法也不能使用

比較好的方式是寫一個靜態(tài)內(nèi)部類來表示聚合字符

static class CompoundKey{

private String className;

private String next;

...

}

Item 51: Beware the performance of string concatenation

考慮字符連接(+)的性能

使用(+)能很方便的拼接若干個字符串,但是我們也要考慮到開銷

如下兩個代碼都是拼接字符

//方式一

public String statement() {

String result = "";

for (int i = 0; i < numItems(); i++)

result += lineForItem(i); // String concatenation

return result;

}

//方式二

public String statement() {

StringBuilder b = new StringBuilder(numItems() * LINE_WIDTH);

for (int i = 0; i < numItems(); i++)

b.append(lineForItem(i));

return b.toString();

}

當(dāng)numItems()==100;lineForItem(i)返回80個長度的字符時,在作者的機器上方式二比方式一快85倍

如果我們需要拼接大量字符時,使用StringBuilder代替

Item 52: Refer to objects by their interfaces

使用接口代替對象引用

如果有一個合適的接口來描述當(dāng)前類的時候使用這個接口來引用,如

// Good - uses interface as type

Listsubscribers = new Vector();

// Bad - uses class as type!

Vectorsubscribers = new Vector();

如果你養(yǎng)成了這個習(xí)慣,那么你的代碼將會更靈活

有幾種情況不能使用接口

1.沒有合適的接口聲明

2.接口中沒有想要的某個方法

3.使用的類集成自framework,并且是一個抽象類

Item 53: Prefer interfaces to reflection

使用接口代替反射

反射核心類java.lang.reflect提供了對加載類信息的訪問

例如,Method.Invoke允許在任何類的任何對象上調(diào)用任何方法(受通常的安全約束)。 即使編譯后的類不存在,也允許一個類使用另一個類。然而,這種力量是有代價的。

你不能在編譯時檢查出異常 如果你使用了對應(yīng)的反射操作,在發(fā)生異常時,只有在運行時才能發(fā)現(xiàn)

閱讀性極差

性能有影響 使用反射比普通調(diào)用要慢些,因為受很多因素的影響,慢多少很難說,在作者的機器上,速度差在兩倍到五十倍不止

反射核心用在基于組件設(shè)計的應(yīng)用,為了按需加載類,使用反射找到對應(yīng)的類構(gòu)造與否;普通應(yīng)用盡量不要使用反射,找到代替的接口或者父類對象

Item 54: Use native methods judiciously

明智地使用本地方法

JNI允許Java調(diào)用C或C++寫的本地方法

從歷史上看,本地方法有三種主要用途。

1.它們提供了對特定于平臺的設(shè)施的訪問,例如注冊表和文件鎖。

2.他們提供了對舊代碼庫(Java想使用歷史上C或C++寫的庫)

的訪問,可以反過來提供對舊數(shù)據(jù)的訪問。

3.使用本地方法用本地語言編寫應(yīng)用程序關(guān)鍵部分,以提高性能。

Java平臺在不斷發(fā)展,訪問特定平臺設(shè)施,使用Java提供的工具類就可做到,而且也不建議使用本地方法來提升程序性能

使用本地方法有嚴(yán)重的缺點

1.本地語言是不安全的,會受機器內(nèi)存錯誤的影響

2.依賴于平臺,不便于移植

3.本地代碼很難調(diào)式

4.訪問本地代碼開銷很大

5.本地代碼不宜閱讀

總之,要再三思考是否使用本地代碼,如果需要使用以前的代碼庫,請盡可能減少本地代碼片段并加強測試,很小很小的本地代碼錯誤將破壞你的整個程序

Item 55: Optimize judiciously

明智的優(yōu)化

有三個人人都應(yīng)該知道的優(yōu)化格言

More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single reason—including blind stupidity.

—William A. Wulf [Wulf72]

更多的計算罪惡是以效率的名義犯下的(不一定要達到這一目的),而不是因為任何其他單一的原因-包括盲目的愚蠢

?

We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.

—Donald E. Knuth [Knuth74]

我們應(yīng)該忽略小效率,大約百分之97的情況下,邪惡之源就是過早優(yōu)化

?

We follow two rules in the matter of optimization:

Rule 1. Don’t do it.

Rule 2 (for experts only). Don’t do it yet—that is, not until you have a

perfectly clear and unoptimized solution.

—M. A. Jackson [Jackson75]

關(guān)于優(yōu)化遵循如下兩個原則:

原則1.別這樣做

原則2.(僅對專家而言).還不要做,直到你找到一個清晰的解決方案或者一個未優(yōu)化的解決辦法

不要為了性能而損壞架構(gòu),致力于寫出好的程序而不是快的程序,如果一個好的程序還不夠快,它的架構(gòu)會允許優(yōu)化.

這并不意味著當(dāng)你的程序完后不需要優(yōu)化,你應(yīng)該在設(shè)計階段就考慮到性能

盡量避免影響性能的設(shè)計,已經(jīng)實現(xiàn)好的組件很難在改變,尤其是API,數(shù)據(jù)結(jié)構(gòu),多方約定好的協(xié)議

考慮好API使用效果,設(shè)計一個可變的類可能會導(dǎo)致后續(xù)使用中出現(xiàn)過多的深拷貝,造成對象分配的額外開銷

API的設(shè)計對性能有很真實的影響,如java.awt.Component中的getSize()方法,每調(diào)用一次就會返回一個新的 Dimension 實例(JDK1.2版本已經(jīng)修復(fù)),雖然分配一個實例的開銷很小,但是成百上千次調(diào)用也會對程序有嚴(yán)重影響

幸運的是,好的API設(shè)計自然帶來了好的性能

總之,致力于寫出好的程序,快隨之而來 當(dāng)做出一部分改變后就要測量代碼的性能,對于Android來說內(nèi)存,卡頓,anr等方面

參考DDMS性能調(diào)優(yōu)

?

Item 56: Adhere to generally accepted naming conventions

遵循公共的命名規(guī)范,參考阿里巴巴發(fā)布的Android手冊

上一章:方法

下一章:異常

總結(jié)

以上是生活随笔為你收集整理的java最小访问原则_Android基础进阶之EffectiveJava翻译系列(第七章:通用原则)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。