Effective Java: General Programming - PowerPoint PPT Presentation

1 / 28
About This Presentation
Title:

Effective Java: General Programming

Description:

Preferred idiom for iterating over a ... the preferred idiom to iterate over ... No longer the preferred idiom to iterate over an array. for (int i=0; ... – PowerPoint PPT presentation

Number of Views:756
Avg rating:3.0/5.0
Slides: 29
Provided by: richardb45
Category:

less

Transcript and Presenter's Notes

Title: Effective Java: General Programming


1
Effective Java General Programming
  • Last Updated Spring 2009

2
Agenda
  • Material From Joshua Bloch
  • Effective Java 2nd Edition
  • Cover Items 45-56
  • General Programming Chapter
  • Bottom Line
  • Nuts and bolts of the Java language
  • Treatment of two extralinguistic language
    facilities
  • Optimization and naming conventions

3
Item 45 Minimize the Scope of Local Variables
  • Similar to Item 13 Minimize the accessibility
    of classes and members
  • Some older languages (eg C) require declarations
    at the beginning of a block
  • A habit worth breaking
  • Important Case Prefer for loops to while loops
  • // Preferred idiom for iterating over a
    collection
  • for (Element e C)
  • doSomething(e) // Note the lack (of an
    explicit) cast
  • // No for-each loop or generics before release
    1.5
  • for (Iterator i c.iterator() i.hasNext() )
  • doSomething( (Element) i.next()) // Note
    the cast

4
More Item 45 Problems with while Loops
  • Sample problem with while loops
  • Problem disappears with local declarations in a
    for loop
  • // Spot the bug?
  • IteratorltElementgt i c.iterator()
  • while (i.hasNext())
  • doSomething(i.next())
  • IteratorltElementgt i2 c2.iterator()
  • while (i.hasNext())
  • doSomething(i2.next())

BUG!
Unfortunately, this bug is silent
5
More Item 45 Solution with for Loops
  • Consider the same formulation with for loops
  • Result is compile time error
  • Note with for loop no reason to change
    variable names
  • for (IteratorltElementgt i c.iterator()
    i.hasNext() )
  • doSomething(i.next())
  • // Compile time error cannot find symbol i
  • for (IteratorltElementgt i2 c2.iterator()
    i.hasNext() )
  • doSomething(i2.next())

6
More Item 45 Example of Multiple Initializations
  • A final for loop example
  • for (int i0, n expensiveComputation() i lt n
    i)
  • doSomething(i)
  • Note that there are two loop variables i and n
  • Scope of both is limited to for loop
  • Avoid if expensiveComputation() does not have a
    constant value

7
Item 46 Prefer for-each Loops to Traditional for
Loops
  • // Preferred idiom for iterating over a
    collections and arrays
  • for (Element e elements) // read as
    in
  • doSomething(e)
  • // 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 i0 i lt a.length i )
  • doSomething( ai )
  • // Note you still need this idiom if you
    want write ai

8
More Item 46 Nested Iterations
  • // Can you spot the bug?
  • enum Suit CLUB, DIAMOND, HEART, SPADE
  • enum Rank ACE, DEUCE, , KING
  • Collection ltSuitgt suits Arrays.asList(Suit.value
    s())
  • Collection ltRankgt rank Arrays.asList(Rank.values
    ())
  • List ltCardgt deck new ArrayListltCardgt()
  • for (IteratorltSuitgt i suits.iterator()
    i.hasNext() )
  • for (IteratorltRankgt j ranks.iterator()
    j.hasNext() )
  • deck.add (new Card(i.next(), j.next())
    // throws NoSuchElementException
  • // Fixed but still ugly
  • for (IteratorltSuitgt i suits.iterator()
    i.hasNext() )
  • Suit suit i.next()
  • for (IteratorltRankgt j ranks.iterator()
    j.hasNext() )
  • deck.add (new Card(suit, j.next())

9
More Item 46 Using the for-each Loop
  • // For each loop solves problem
  • for (Suit suit suits )
  • for (Rank rank ranks)
  • deck.add (new Card(suit, rank)
  • // Similar problem, but fails silently
  • enum Face ONE, TWO, THREE, FOUR, FIVE, SIX
  • CollectionltFacegt faces Arrays.asList(Face.values
    ())
  • for (IteratorltFacegt i faces.iterator()
    i.hasNext())
  • for IteratorltFacegt j faces.iterator()
    j.hasNext())
  • System.out.println(i.next()
    j.next())
  • // Output is ONE ONE, TWO TWO, etc, instead
    of all combinations
  • // Same fix
  • for (Face face1 faces)

10
More Item 46 Iterable interface
  • Simple to implement Iterable interface
  • // public interface IterableltEgt
  • // Returns an iterator over the elements in
    this iterable
  • public IteratorltEgt iterator()
  • You should provide this API to your clients, if
    appropriate
  • Three cases where client cant use a for-each
    loop
  • Filtering client needs to traverse a collection
    and remove selected elements
  • Transforming client needs to traverse a
    collection and replace some values
  • Parallel Iteration client needs to traverse
    multiple collections in parallel, and hence need
    to control iterator or index variable

11
More Item 46 Implementing and then using Iterable
  • public class IterableExample
  • public static void main( String args)
  • ExampleltStringgt example new
    ExampleltStringgt()
  • example.add("hat") example.add("cat")
  • for (String s example)
  • System.out.println (s)
  • public class ExampleltEgt implements IterableltEgt
  • SetltEgt s new TreeSet()
  • public void add (E e) s.add(e)
  • public IteratorltEgt iterator() return
    s.iterator()

12
Item 47 Know and Use the Libraries
  • // Common, but deeply flawed!
  • private static final Random rnd new Random()
  • static int random (int n)
  • return Math.abs(rnd.nextInt()) n
  • Three flaws
  • if n is a small power of 2, sequence (quickly)
    repeats
  • if n is not a power of 2, some numbers are more
    frequent
  • See example in Bloch where 2/3 of results show up
    in half the range
  • sometimes, can fail catastrophically
  • What if rnd.nextInt() returns Integer.MIN_VALUE?
  • What to do?
  • Its easy (if you know the libraries)
  • Use Random.nextInt() - Available since 1.2

13
More Item 47 Library Advantages
  • Using a library takes advantage of
  • Knowledge of experts who wrote it
  • Experience of users who used it before you
  • Libraries evolve
  • Numerous features added to libraries in every
    major release
  • Bloch suggests studying java.lang, java.util, and
    java.io
  • Dont reinvent the wheel
  • Library code is better than your code!
  • Bloch says its not a comment about your
    abilities (But this is Bloch and peers were
    talking about)
  • You dont have the same resources

14
Item 48 Avoid float and double if Exact Answers
are Required
  • // Broken uses floating point for monetary
    calculation!
  • public static void main (String args)
  • double funds 1.00
  • int itemsBought 0
  • for (double price .10 funds gt price price
    10 )
  • funds - price
  • itemsBought
  • System.out.println ( itemsBought items
    bought.)
  • System.out.println ( Change funds)
  • Results
  • 3 items bought
  • 0.3999999999999999 in change

15
Item 49 Prefer Primitive Types to Boxed
Primitives
  • // Broken comparator can you spot the flaw?
  • Comparator lt Integergt naturalOrder
  • new ComparatorltIntegergt() // Anonymous
    type
  • public int compare (Integer first, Integer
    second)
  • return first lt second ? -1 // Auto
    unboxing
  • (first second // No auto
    unboxing (!)
  • ? 0 1)
  • Sample uses
  • naturalOrder.compare(new Integer(41), new
    Integer(42))
  • naturalOrder.compare(new Integer(42), new
    Integer(42)) naturalOrder.compare(new
    Integer(43), new Integer(42))

16
More Item 49
  • // Repaired version
  • Comparator lt Integergt naturalOrder
  • new ComparatorltIntegergt()
    // Still an anonymous type
  • public int compare (Integer first, Integer
    second)
  • int f first int s second
    // Auto unboxing
  • return f lt s ? -1 (f s ? 0 1)
    // No unboxing needed
  • // Another little gem
  • public class Unbelievable
  • static Integer i
  • public static void main(String args)
  • (if i 42)
  • System.out.println(Unbelievable)
  • Doesnt print Unbelievable
  • But does throw NullPointerException!

17
More Item 49
  • // Performance problem with autoboxing
  • public static void main(String args)
  • Long sum 0L // ok if declaration is
    long sum 0
  • for (long i 0 i lt Integer.MAX_VALUE i)
  • sum i
  • System.out.println(sum)
  • Orders of magnitude slower than it should be
  • So, when to use boxed primitives?
  • As elements, keys, and values in Collections
  • Otherwise, use primitives

18
Item 50 Avoid Strings Where Other Types Are More
Appropriate
  • Strings are a poor substitute for other value
    types
  • Input arrives as String from file, keyboard or
    network
  • Transform to underlying type, eg int, float, or
    boolean
  • Strings are a poor substitute for enum types
  • Simply use enum types directly (See Bloch Item
    30)
  • Strings are poor substitutes for aggregate types
  • // Innappropriate use of String as aggregate type
  • String compounKey classname i.next()
  • What if delimeter is in classname or
    i.next()?
  • How do you access fields (except by parsing)?
  • What about equals(), compareTo(), and toString()?
  • Better to simply write a class to represent the
    aggregate
  • Strings are poor substitutes for capabilities
  • A capability grants access to a resource
  • The problem is that the String namespace is
    global
  • Hence, anyone can create any String.

19
Item 51 Beware the Performance of String
Concatenation
  • // Inappropriate use of string concatenation
    performs horribly
  • public String statement()
  • String result
  • for (int i0 I lt numItems() i)
  • result lineForItem(i) // String
    concatenation
  • // StringBuilder version much faster
  • public String statement()
  • StringBuilder b new StringBuilder(numItems
    LINE_WIDTH)
  • for (int i0 I lt numItems() i)
  • b.append( lineForItem(i))
  • return b.toString()

20
Item 52 Refer to Objects by Their Interfaces
  • // Good uses interfaces as type
  • List ltSubscribergt subscribers new
    VectorltSubscribergt()
  • // Bad uses class as type
  • Vector ltSubscribergt subscribers new
    VectorltSubscribergt()
  • // Second form prohibits maintenance change to
  • List ltSubscribergt subscribers new
    ArrayListltSubscribergt()
  • If you get into the habit of using interfaces as
    types
  • Your programs will be much more flexible
  • If appropriate interface types exist, use for
  • parameters
  • return values
  • variables
  • fields

21
Item 53 Prefer Interfaces to Reflection
  • Reflection allows full access to any class
  • Possible to obtain, all Constructors, Methods,
    and Fields
  • Update or invoke eg Method.invoke
  • Powerful mechanism! But there is a price
  • You lose all the benefits of compile time
    checking
  • Code for reflexive access is cumbersome and
    verbose
  • Performance suffers
  • As a rule, objects should not be reflexively
    accessed at runtime
  • To limit use of reflection
  • Create instances reflectively, but
  • Access instances through an interface or
    superclass
  • You may not even have to use java.lang.reflect

22
More Item 53
  • // Reflective instantiation with interface access
  • // Bulky (vs calling a constructor), with
    possible runtime errors
  • public static void main (String args)
  • // Translate the class name into a Class
    object
  • Classlt?gt cl null // note that try/catch
    block interrupts declaration
  • try
  • cl Class.forName (args0)
  • catch (ClassNotFoundException e)
    // runtime, not compile time, error
  • System.err.println(Class not found.)
  • System.exit(1)
    // terminates JVM! generally bad practice

  • // ok for command line utility
  • // Instantiate the class
  • Set ltStringgt s null
  • try
  • s (SetltStringgt) cl.newInstance()
  • catch (IllegalAccessException e)
    // runtime, not compile time, error
  • System.err.println(Class not
    accessible.) System.exit(1)
  • catch (InstantiationException e)
    // runtime, not compile time, error

23
Item 54 Use Native Methods Judiciously
  • Java allows calls to code written in other
    languages
  • Three historical reasons
  • Access to platform specific facilities
  • Access to legacy code
  • Performance critical sections
  • First and third reasons less compelling now
  • Java releases now features access to platform
    specific facilities
  • It is rarely advisable to use native methods for
    performance
  • Calls to native methods are now often slower
  • JVMs are much more efficient

24
Item 55 Optimize Judiciously
  • Three quotes
  • 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, 1972)
  • We should forget about small efficiencies, say
    about 97 of the time premature optimization is
    the root of all evil (Donald E. Knuth, 1974)
  • We follow two rules in the matter of optimization
    (M.A. Jackson, 1975)
  • Rule 1 Dont do it.
  • Rule 2 (for experts only) Dont do it yet that
    is, not until you have a perfectly clear and
    unoptimized solution
  • Note that this advice is 3 decades old
  • Think how slow/limited computer systems were in
    the 1970s
  • Bottom line Advice is even more relevant
    now

25
More Item 55
  • Strive to write good programs rather than fast
    ones
  • But avoid design decisions that limit performance
  • Consider effect of API decisions, wire-level
    protocols, and data formats
  • Example java.awt.Component class
  • public Dimension getSize() // return component
    size
  • Return type is a mutable height/width record
  • No sharing possible, so, a new object created on
    every call
  • Ideally, Dimension should be immutable
  • Too late now!
  • As of release 1.2, two new methods added
  • int getHeight(), int getWidth()
  • Unfortunately, doesnt help legacy code

26
More Item 55
  • Fortunate fact
  • Good API design usually consistent with good
    performance
  • Dont warp an API for performance reasons
  • Performance problem may go away in future
    releases
  • But API design is permanent
  • If you have to optimize (for experts only!)
  • Measure performance before and after optimization
  • Use a profiling tool
  • Results often conflict with intuition
  • Performance problems are needles in haystacks
  • In a big haystack, you need a metal detector
  • In a big program, you need hard data
  • Java resists easy definition of costs for
    primitive operations
  • Performance varies from JVM to JVM

27
Item 56 Adhere to Generally Accepted Naming
Conventions
  • Packages
  • com.google.inject, org.joda.time.format
  • Class and Interface names
  • Timer, FutureTask, LinkedHashMap, HttpServlet
  • Method and Field names
  • Remove(), ensureCapacity(), getCrc()
  • Local Variable
  • i, xref, houseNumber
  • Constant
  • MIN_VALUE, NEGATIVE_INFINITY
  • Type Parameter
  • T, E, K, V, X, T1, T2

28
More Item 56
  • Methods that perform some actions
  • Verb or verb phrase
  • append(), drawImage()
  • Methods that return boolean
  • Name usually starts with is sometimes has
  • isDigit(), isProbablePrime(), isEmpty(),
    isEnabled(), hasSiblings()
  • Methods that return nonboolean
  • noun, noun phrase, or verb phrase starting with
    get
  • size(), hashCode(), getTime()
  • get form required for Beans other form often
    more readable
  • getters usually have setters (unless
    immutable)
  • Special cases
  • type conversion methods use to
  • toString(), toArray()
  • view methods use as
  • asType(), asList()
  • Common static factory names
  • valueOf(), of(), getInstance(), newInstance(),
    getType(), and newType()
Write a Comment
User Comments (0)
About PowerShow.com