Download presentation
Presentation is loading. Please wait.
Published byGinger McBride Modified over 9 years ago
1
Effective Java – General Programming Global Server Dept. Hu Qiongkai qkhu@telenav.cn
2
Content Minimize the scope of local variables Beware performance of string concatenation Prefer for-each loops to traditional for loops Refer to objects by their interfaces Avoid float/double if exact answers required Prefer interfaces to reflection Prefer primitive types to boxed primitives Avoid strings where other types are more appropriate Other practical principals
3
Minimize the scope of local variables Before use a variable declare variable variable initialization Variable scope Inside a block try { String s = “”; } catch (Exception e){} in for statement // Preferred idiom for iterating over a collection since JDK1.5 for (Element e : c) { doSomething(e); } // No for-each loop or generics before release 1.5 for (Iterator i = c.iterator(); i.hasNext(); ) { doSomething((Element) i.next()); } outside a block String s = null; try { s = “”; } catch (Exception e){}
4
Minimize the scope of local variables(2) cut-and-paste error Iterator i = c.iterator(); while (i.hasNext()) { doSomething(i.next()); }... Iterator i2 = c2.iterator(); while (i.hasNext()) { // runtime BUG! doSomethingElse(i2.next()); } Better practice Time to declare variable: at where it is first used Initialization tip: in a try/catch block, if variable needs be used outside block, should initilize it outside try/catch prefer ‘for’ loops to ‘while’ loops keep methods small and focused for (Iterator i = c.iterator(); i.hasNext(); ) { doSomething(i.next()); }... // Compile-time error - cannot find symbol i for (Iterator i2 = c2.iterator(); i.hasNext(); ) { doSomething(i2.next()); }
5
Beware performance of string concatenation Simple concatenation with ‘+’ public String concat4(String s1, String s2, String s3, String s4) { return s1 + s2 + s3 + s4; } # Before JDK5 Using ‘+’ repeatedly to concatenate n strings requires time quadratic in n(n 2 ). String is immutable, for concatenation with ‘+’, needs characters copied and a new result String object created. # Since JDK5 auto optimized by compiled into using StringBuilder.append(). compiled sample: String ss = (new StringBuilder("ok")).append(s).append("xyz").append(5).toString();
6
Beware performance of string concatenation(2) Complex concatenation with ‘+’ what if concatenation in a ‘for’ statement? Random rand = new Random(); for (int i = 0; i < 10; i++) { s = s + rand.nextInt(1000) + " "; } # compiled sample: StringBuilder result = new StringBuilder(); for(int i = 0; i < 10; i++) { s = (new StringBuilder(String.valueOf(s))).append(rand.nextInt(1000)).append(" ").toString(); } # Tip new a StringBuilder Object for each item in ‘for’ statement
7
Beware performance of string concatenation(3) Better performance: use StringBuilder/StringBuffer instead java.lang.StringBuilder mutable sequence of characters no guarantee for thread safe java.lang.StringBuffer thread-safe, mutable sequence of characters Class Hierarchy
8
Prefer for-each loops to traditional for loops traditional for loops // No longer the preferred idiom to iterate over a collection! for (Iterator i = c.iterator(); i.hasNext(); ) { doSomething((Element) i.next()); // (No generics before 1.5) } // No longer the preferred idiom to iterate over an array! for (int i = 0; i < a.length; i++) { doSomething(a[i]); } for-each loops // The preferred idiom for iterating over collections and arrays for (Element e : elements) { doSomething(e); } advantages by using for-each code clarity no performance penalty, even slight better during loop an array, only computes index once bug prevention?
9
Prefer for-each loops to traditional for loops(2) Can you spot the bug? enum Suit { CLUB, DIAMOND, HEART, SPADE } enum Rank { ACE, DEUCE, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING }... Collection suits = Arrays.asList(Suit.values()); Collection ranks = Arrays.asList(Rank.values()); List deck = new ArrayList (); for (Iterator i = suits.iterator(); i.hasNext(); ) for (Iterator j = ranks.iterator(); j.hasNext(); ) deck.add(new Card(i.next(), j.next())); Solutions to prevent the bug fix it in traditional way // Fixed, but ugly - you can do better! for (Iterator i = suits.iterator(); i.hasNext(); ) { Suit suit = i.next(); for (Iterator j = ranks.iterator(); j.hasNext(); ) deck.add(new Card(suit, j.next())); } use for-each instead // Preferred idiom for nested iteration for (Suit suit : suits) for (Rank rank : ranks) deck.add(new Card(suit, rank));
10
Refer to objects by their interfaces Interface oriented programming methodology big advantage: much more flexible sample case // Bad - uses class as type! Vector subscribers = new Vector (); // Good - uses interface as type List subscribers = new Vector (); // We can change subscribers to other List types easily List subscribers = new ArrayList (); practical case in spring
11
Avoid float/double if exact answers required Problems System.out.println(1.03 -.42); # output 0.6100000000000001 Why it happens binary floating-point arithmetic float/double types are particularly illsuited for monetary calculations Solutions to achieve exact computation using java.math.BigDecimal BigDecimal bigDecimal = new BigDecimal("1.03"); System.out.println(bigDecimal.subtract(new BigDecimal(".42"))); # Tips -exact computation -performance impacted using primitive arithmetic type: int or long -high performance -decimal point has to be handled manually
12
Prefer interfaces to reflection What reflection can do Given a Class object, you can obtain Constructor, Method, and Field instances representing the constructors, methods, and fields of the class represented by the Class instance. case study initialize class instance via reflection Class cl = null; try { cl = Class.forName(args[0]); // Instantiate the class Set s = null; s = (Set ) cl.newInstance(); } catch(Exception e) {} access class method/field via reflection Field f = cl.getClass().getDeclaredField(“f1"); f.setAccessible(true); Method m = f.getType().getDeclaredMethod(“f1m1", new Class[0]); m.setAccessible(true); m.invoke(cl, new Object[0]);
13
Prefer interfaces to reflection cost on using reflection no compile-time type checking code clumsy and verbose Performance suffers When to use reflection in runtime, better to use class instance normal access, unless necessary base framework Spring Struts OSGI dynamic class loading management
14
Prefer primitive types to boxed primitives auto-boxing and auto-unboxing since JDK1.5 sample case study // Broken comparator - can you spot the flaw? Comparator naturalOrder = new Comparator () { public int compare(Integer first, Integer second) { return first < second ? -1 : (first == second ? 0 : 1); } }; Primitive typeReference type intjava.lang.Integer doublejava.lang.Double booleanjava.lang.Boolean
15
Prefer primitive types to boxed primitives(2) fix the bug Comparator naturalOrder = new Comparator () { public int compare(Integer first, Integer second) { int f = first; // Auto-unboxing int s = second; // Auto-unboxing return f < s ? -1 : (f == s ? 0 : 1); // No unboxing } }; when you mix primitives and boxed primitives in a single operation, the boxed primitive is auto-unboxing public class Unbelievable { static Integer i; public static void main(String[] args) { if (i == 42) throws NullPointerException for Integer auto-unboxing System.out.println("Unbelievable"); }
16
Prefer primitive types to boxed primitives(3) performance suffers during auto-boxing/unboxing // Hideously slow program! Can you spot the object creation? public static void main(String[] args) { Long sum = 0L; for (long i = 0; i < Integer.MAX_VALUE; i++) { sum += i; } System.out.println(sum); } more practice tips primitive types are simpler and faster auto-boxing reduces the verbosity, but not the danger, of using boxed primitives use boxed primitives as type parameter in in parameterized types // sample List l = new ArrayList (); ThreadLocal tl = new ThreadLocal ();
17
Avoid strings where other types are more appropriate Strings are designed to represent text poor substitutes for capabilities // Broken - inappropriate use of string as capability! public class ThreadLocal1 { private ThreadLocal1() { } // Non-instantiable // Sets the current thread's value for the named variable. public static void set(String key, Object value); // Returns the current thread's value for the named variable. public static Object get(String key); } poor substitutes for enum types, hard to maintain public static enum UserRole { Admin, PM, BusinessOwner, Marketing, Finance, Legal } poor substitutes for not text value types Other
18
Other practical principles Know and use the standard JDK libraries By using a standard library, you take advantage of the knowledge of the experts who wrote it and the experience of those who used it before you. java.lang, java.util, java.io Use native methods judiciously JNI: Java Native Interface Platform dependent, less portable Not safe, need anually memory control Has a fixed cost associated with going into/out of native code JVM gets faster, rarely advisable to use native method for performance gain Optimize judiciously write good program, architecture first, performance follows avoid design decisions that limit performance use profiling tools to determine performance optimization focus Adhere to generally accepted naming conventions
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.