通用程序設(shè)計(jì)

最小化local variables的范圍
  • 最強(qiáng)有力的方式是:在該local variables第一次使用的地方declare it
  • 優(yōu)先使用for loops, 而不是while loops
  • keep methods small and focused,一個(gè)方法只執(zhí)行一個(gè)activity
for 循環(huán)和while循環(huán)相比,有哪些好處?
  • 能最小化local variables的范圍
for (Iterator<Element> i = c.iterator(); i.hasNext(); ) {
    Element e = i.next();
    ... // Do something with e and i
}
...

// Compile-time error - cannot find symbol i
for (Iterator<Element> i2 = c2.iterator(); i.hasNext(); ) {
    Element e2 = i2.next();
    ... // Do something with e2 and i2
} 
Iterator<Element> i = c.iterator();
while (i.hasNext()) {
    doSomething(i.next());
}
...
Iterator<Element> i2 = c2.iterator();
while (i.hasNext()) {             // BUG!
    doSomethingElse(i2.next());
}
  • for循環(huán)更簡潔,能增強(qiáng)可讀性
for (int i = 0, n = expensiveComputation(); i < n; i++) {
    ... // Do something with i;
}
優(yōu)先使用for-each loops,而不是傳統(tǒng)的for loops
  • 在對collections and arrays進(jìn)行迭代時(shí),優(yōu)先使用for-each loops
  • 如果想使用for-each loops迭代any object,只需要該object實(shí)現(xiàn)Iterable接口
懂得使用the libraries
  • 不要自造輪子,代價(jià)太大
// Common but deeply flawed!
static Random rnd = new Random();
static int random(int n) {
    return Math.abs(rnd.nextInt()) % n;
}
// just use
Random.nextInt(int)
// for Java 7
use ThreadLocalRandom, not Random
// for fork join pools and parallel streams
use SplittableRandom 
  • 通過使用standard library,你可以使用寫這些庫的專家的知識以及已經(jīng)使用過的這些庫的那些人的經(jīng)驗(yàn)
  • 通過使用standard library,如果有flaws被發(fā)現(xiàn),那么它們會在 the next release 中fixed掉
  • 通過使用standard library,你可以專注于自己的應(yīng)用,而不用關(guān)心某些不太緊要的細(xì)節(jié)
  • standard library,隨著時(shí)間的推移,性能會越來越高,而且不需要你維護(hù)
  • standard library,隨著時(shí)間的推移,功能越來越豐富,健全
  • 通過使用standard library,你的代碼會更易讀,可維護(hù)性更強(qiáng),因?yàn)槟愕拇a屬于mainstream
  • 為了便利的使用standard library,你需要關(guān)注 every major release,不斷學(xué)習(xí)這些新添加的特性
  • 每一個(gè)程序員都應(yīng)該熟悉 java.lang, java.util, java.io, 以及它們的 subpackages
  • 如果Java platform libraries 不能滿足你,接下來應(yīng)該先去查找高質(zhì)量的第三方庫,比如:Guava,如果你實(shí)在找不到滿足你需要的庫,再去自己編碼實(shí)現(xiàn)它
如果需要exact answer,請不要使用float 和 double類型
  • float 和 double類型尤其不適合貨幣計(jì)算
  • 應(yīng)該使用BigDecimal, int, long進(jìn)行貨幣計(jì)算
  • 如果數(shù)量級不超過9位十進(jìn)制數(shù),則用int;如果不超過18位,則用long;如果超過18位或者含有小數(shù),則用BigDecimal
說說Java的兩種類型系統(tǒng)
  • primitives 和 reference types
  • primitives 包括 比如 int, double, and boolean;reference types 包括比如String 和 List
  • primitive type對應(yīng)的reference type稱為boxed primitive
說說primitives 和 boxed primitives的區(qū)別
  • primitives僅僅擁有values,boxed primitives 除此以外,還擁有不同于values的identities
  • boxed primitives有一個(gè)nonfunctional value,即null
  • primitives 更省時(shí)間,更省空間
  • 對boxed primitives,使用== operator,一般總是錯(cuò)誤的,因?yàn)樵摬僮鞣麜容^identities,最后造成不期望的結(jié)果
// error! 由于==符號,(new Integer(42), new Integer(42))比較,會返回1
Comparator<Integer> naturalOrder =
    (i, j) -> (i < j) ? -1 : (i == j ? 0 : 1);
//right way
Comparator<Integer> naturalOrder = (iBoxed, jBoxed) -> {
“int i = iBoxed, j = jBoxed; // Auto-unboxing
    return i < j ? -1 : (i == j ? 0 : 1);
};
  • 在一個(gè)操作中,混合使用 primitives 和 boxed primitives,會使boxed primitive 自動拆箱,下面的代碼會報(bào)NullPointerException的錯(cuò)誤
public class Unbelievable {
    static Integer i;

    public static void main(String[] args) {
        if (i == 42)  //NullPointerException
            System.out.println("Unbelievable");
    }
}
public static void main(String[] args) {
    Long sum = 0L;
    for (long i = 0; i < Integer.MAX_VALUE; i++) {
        sum += i; //重復(fù)的拆箱和裝箱,影響性能
    }
    System.out.println(sum);
}
什么時(shí)候必須使用boxed primitives
  • 充當(dāng)collections中的元素
  • 激活反射方法
當(dāng)其他類型更適合時(shí),請不要使用strings類型
  • Strings不適合替代其他的value types
  • Strings不適合替代enum types
  • Strings不適合替代aggregate types(復(fù)合類型),應(yīng)該提供一個(gè)私有的靜態(tài)成員類
// Inappropriate use of string as aggregate type
String compoundKey = className + "#" + i.next(); 
小心String concatenation operator (+)的性能
  • 不要使用String 的+操作符來 combine more than a few strings,應(yīng)該使用StringBuilder 的 append 方法
使用interfaces來引用objects
  • 如果有適合的接口存在,則 parameters, return values, variables, 以及 fields 都應(yīng)該由interface types宣稱
// Good - uses interface as type
Set<Son> sonSet = new LinkedHashSet<>();
// Bad - uses class as type!
LinkedHashSet<Son> sonSet = new LinkedHashSet<>();
有哪些情況適合使用具體類來引用objects
  • value classes, 比如 String 和 BigInteger
  • class-based framework,比如 大多數(shù) java.io 類,如OutputStream
  • 該interface中沒有提供某些方法,比如PriorityQueue中有個(gè)comparator方法,該方法沒有在Queue interface中提供
優(yōu)先使用 interfaces 而不是 reflection
  • java.lang.reflect 提供獲取一個(gè)類的 Constructor, Method, Field,你可以使用它們 construct instances, invoke methods, 以及 access fields of the class
reflection的缺點(diǎn)
  • 失去了編譯期類型檢查的所有好處
  • 執(zhí)行reflective access的代碼笨拙又冗長
  • 性能差
怎么結(jié)合使用 interfaces 和 reflection
  • 僅僅使用反射 create instances,使用interfaces和superclass access them
  • 小例子
// Reflective instantiation with interface access
public static void main(String[] args) {
    // Translate the class name into a Class object
    Class<? extends Set<String>> cl = null;
    try {
        cl = (Class<? extends  Set<String>>)  // Unchecked cast!
                Class.forName(args[0]);
    } catch (ClassNotFoundException e) {
        fatalError("Class not found.");
    }
    // Get the constructor
    Constructor<? extends Set<String>> cons = null;
    try {
        cons = cl.getDeclaredConstructor();
    } catch (NoSuchMethodException e) {
        fatalError("No parameterless constructor");
    }
    // Instantiate the set
    Set<String> s = null;
    try {
        s = cons.newInstance();
    } catch (IllegalAccessException e) {
        fatalError("Constructor not accessible");
    } catch (InstantiationException e) {
        fatalError("Class not instantiable.");
    } catch (InvocationTargetException e) {
        fatalError("Constructor threw " + e.getCause());
    } catch (ClassCastException e) {
        fatalError("Class doesn't implement Set");
    }
    // Exercise the set
    s.addAll(Arrays.asList(args).subList(1, args.length));
    System.out.println(s);
}
private static void fatalError(String msg) {
    System.err.println(msg);
    System.exit(1);
}
使用native methods,要謹(jǐn)慎
  • native methods,即使用C或C++寫的方法,Java 允許使用Java Native Interface (JNI) 來調(diào)用native methods
  • native methods 使用的膠水語言難以閱讀和書寫,難以debug,可移植性差,易造成內(nèi)存污染,不利于GC。所以應(yīng)該盡可能少的使用native methods
代碼優(yōu)化,要謹(jǐn)慎
  • 過早的優(yōu)化是萬惡之源
  • 不要為了性能而犧牲好的程序結(jié)構(gòu)
  • 致力于寫好的代碼,而不是快的代碼
  • Good API design 會帶來 Good performance
  • programs spend 90 percent of their time in 10 percent of their code,必要時(shí),可以借助profiler或jmh來搜尋那10%
堅(jiān)持公認(rèn)的命名慣例
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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