19
Effective Java – General Programming Global Server Dept. Hu Qiongkai [email protected]

Effective Java – General Programming Global Server Dept. Hu Qiongkai [email protected]

Embed Size (px)

Citation preview

Page 1: Effective Java – General Programming Global Server Dept. Hu Qiongkai qkhu@telenav.cn

Effective Java – General Programming

Global Server Dept.

Hu Qiongkai

[email protected]

Page 2: Effective Java – General Programming Global Server Dept. Hu Qiongkai qkhu@telenav.cn

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

Page 3: Effective Java – General Programming Global Server Dept. Hu Qiongkai qkhu@telenav.cn

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.5for (Element e : c) {

doSomething(e);}// No for-each loop or generics before release 1.5for (Iterator i = c.iterator(); i.hasNext(); ) {

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

outside a blockString s = null;try { s = “”;} catch (Exception e){}

Page 4: Effective Java – General Programming Global Server Dept. Hu Qiongkai qkhu@telenav.cn

Minimize the scope of local variables(2)

cut-and-paste error

Iterator<Element> i = c.iterator();while (i.hasNext()) {

doSomething(i.next());}...Iterator<Element> 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<Element> i = c.iterator(); i.hasNext(); ) {doSomething(i.next());

}...// Compile-time error - cannot find symbol ifor (Iterator<Element> i2 = c2.iterator(); i.hasNext(); ) {

doSomething(i2.next());}

Page 5: Effective Java – General Programming Global Server Dept. Hu Qiongkai qkhu@telenav.cn

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(n2). 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();

Page 6: Effective Java – General Programming Global Server Dept. Hu Qiongkai qkhu@telenav.cn

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

Page 7: Effective Java – General Programming Global Server Dept. Hu Qiongkai qkhu@telenav.cn

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

Page 8: Effective Java – General Programming Global Server Dept. Hu Qiongkai qkhu@telenav.cn

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 arraysfor (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?

Page 9: Effective Java – General Programming Global Server Dept. Hu Qiongkai qkhu@telenav.cn

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<Suit> suits = Arrays.asList(Suit.values());Collection<Rank> ranks = Arrays.asList(Rank.values());List<Card> deck = new ArrayList<Card>();for (Iterator<Suit> i = suits.iterator(); i.hasNext(); )

for (Iterator<Rank> 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<Suit> i = suits.iterator(); i.hasNext(); ) {

Suit suit = i.next();for (Iterator<Rank> j = ranks.iterator(); j.hasNext(); )

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

use for-each instead

// Preferred idiom for nested iterationfor (Suit suit : suits)

for (Rank rank : ranks)deck.add(new Card(suit,

rank));

Page 10: Effective Java – General Programming Global Server Dept. Hu Qiongkai qkhu@telenav.cn

Refer to objects by their interfaces

Interface oriented programming methodology big advantage: much more flexible

sample case// Bad - uses class as type!Vector<Subscriber> subscribers = new Vector<Subscriber>();

// Good - uses interface as typeList<Subscriber> subscribers = new Vector<Subscriber>();

// We can change subscribers to other List types easilyList<Subscriber> subscribers = new ArrayList<Subscriber>();

practical case in spring

Page 11: Effective Java – General Programming Global Server Dept. Hu Qiongkai qkhu@telenav.cn

Avoid float/double if exact answers required

ProblemsSystem.out.println(1.03 - .42);

# output0.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.BigDecimalBigDecimal 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

Page 12: Effective Java – General Programming Global Server Dept. Hu Qiongkai qkhu@telenav.cn

Prefer interfaces to reflection

What reflection can doGiven 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 reflectionClass<?> cl = null;try {

cl = Class.forName(args[0]);// Instantiate the classSet<String> s = null;s = (Set<String>) cl.newInstance();

} catch(Exception e) {}

access class method/field via reflectionField 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]);

Page 13: Effective Java – General Programming Global Server Dept. Hu Qiongkai qkhu@telenav.cn

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

Page 14: Effective Java – General Programming Global Server Dept. Hu Qiongkai qkhu@telenav.cn

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<Integer> naturalOrder = new Comparator<Integer>() {

public int compare(Integer first, Integer second) {return first < second ? -1 : (first == second ? 0 : 1);

}};

Primitive type Reference type

int java.lang.Integer

double java.lang.Double

boolean java.lang.Boolean

Page 15: Effective Java – General Programming Global Server Dept. Hu Qiongkai qkhu@telenav.cn

Prefer primitive types to boxed primitives(2)

fix the bugComparator<Integer> naturalOrder = new Comparator<Integer>() {

public int compare(Integer first, Integer second) {int f = first; // Auto-unboxingint s = second; // Auto-unboxingreturn 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");}

}

Page 16: Effective Java – General Programming Global Server Dept. Hu Qiongkai qkhu@telenav.cn

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// sampleList<Integer> l = new ArrayList<Integer>();ThreadLocal<Integer> tl = new ThreadLocal<Integer>();

Page 17: Effective Java – General Programming Global Server Dept. Hu Qiongkai qkhu@telenav.cn

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 maintainpublic static enum UserRole {

Admin, PM, BusinessOwner, Marketing, Finance, Legal}

poor substitutes for not text value types Other

Page 18: Effective Java – General Programming Global Server Dept. Hu Qiongkai qkhu@telenav.cn

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

Page 19: Effective Java – General Programming Global Server Dept. Hu Qiongkai qkhu@telenav.cn

Q & A