Effective java general programming l.jpg
This presentation is the property of its rightful owner.
Sponsored Links
1 / 28

Effective Java: General Programming PowerPoint PPT Presentation


  • 118 Views
  • Uploaded on
  • Presentation posted in: General

Effective Java: General Programming. Last Updated: Fall 2013. Agenda. Material From Joshua Bloch Effective Java 2 nd Edition Cover Items 45-56 “General Programming” Chapter Bottom Line: Nuts and bolts of the Java language Treatment of two extralinguistic language facilities

Download Presentation

Effective Java: General Programming

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Effective java general programming l.jpg

Effective Java: General Programming

Last Updated: Fall 2013


Agenda l.jpg

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


Item 45 minimize the scope of local variables l.jpg

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

    }


More item 45 problems with while loops l.jpg

More Item 45: Problems with while Loops

  • Sample problem with while loops

    • Problem disappears with local declarations in a for loop

      // Spot the bug?

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

      while (i.hasNext()) {

      doSomething(i.next());

      }

      Iterator<Element> i2 = c2.iterator();

      while (i.hasNext()) {

      doSomething(i2.next());

      }

BUG!

Unfortunately, this bug is silent


More item 45 solution with for loops l.jpg

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

      doSomething(i.next());

      }

      // Compile time error – cannot find symbol i

      for (Iterator<Element> i2 = c2.iterator(); i.hasNext(); ) {

      doSomething(i2.next());

      }


More item 45 example of multiple initializations l.jpg

More Item 45: Example of Multiple Initializations

  • A final for loop example

    for (int i=0, n = expensiveComputation(); i < 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


Item 46 prefer for each loops to traditional for loops l.jpg

Item 46: Prefer for-each Loops to Traditional for Loops

// Preferred idiom for iterating over collections / arrays

for (Element e: elements) { // read “:” as “in”

doSomething(e);

}

// No longer the preferred idiom to iterate

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] );

// Note: still need this idiom if you want a[i] = …

}


More item 46 nested iterations l.jpg

More Item 46: Nested Iterations

// Can you spot the bug?

enum Suit { CLUB, DIAMOND, HEART, SPADE }

enum Rank { ACE, DEUCE, …, KING }

Collection <Suit> suits = Arrays.asList(Suit.values());

Collection <Rank> rank = 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()); // throws NoSuchElementException

}

}

// Fixed – but still ugly

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

}

}


More item 46 using the for each loop l.jpg

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 }

Collection<Face> faces = Arrays.asList(Face.values());

for (Iterator<Face> i = faces.iterator(); i.hasNext()) {

for Iterator<Face> 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) {

for (Face face2 : faces) {

System.out.println(face1 + “ “ + face2);

}

}


More item 46 iterable interface l.jpg

More Item 46: Iterable interface

  • Simple to implement Iterable interface:

    // public interface Iterable<E> {

    // Returns an iterator over the elements in this iterable

    public Iterator<E> iterator();

    }

  • You should provide this API to your clients, if appropriate

  • Three cases where client can’t 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


More item 46 implementing and then using iterable l.jpg

More Item 46: Implementing and then using Iterable

public class IterableExample {

public static void main( String[] args) {

Example<String> example = new Example<String>();

example.add("hat"); example.add("cat");

for (String s: example) {

System.out.println (s);

}

}

}

public class Example<E> implements Iterable<E> {

Set<E> s = new TreeSet();

public void add (E e) { s.add(e);}

public Iterator<E> iterator() { return s.iterator(); }

}


Item 47 know and use the libraries l.jpg

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?

    • It’s easy (if you know the libraries)

    • Use Random.nextInt() - Available since 1.2


More item 47 library advantages l.jpg

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

  • Don’t reinvent the wheel

    • Library code is better than your code!

    • Bloch says it’s not a comment about your abilities (But this is Bloch and peers we’re talking about…)

      • You don’t have the same resources


Item 48 avoid float and double if exact answers are required l.jpg

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 >= 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


Item 49 prefer primitive types to boxed primitives l.jpg

Item 49: Prefer Primitive Types to Boxed Primitives

// Broken comparator – can you spot the flaw?

Comparator < Integer> naturalOrder =

new Comparator<Integer>() { // Anonymous type

public int compare (Integer first, Integer second) {

return first < 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));


More item 49 l.jpg

More Item 49

// Repaired version

Comparator < Integer> naturalOrder =

new Comparator<Integer>() { // Still an anonymous type

public int compare (Integer first, Integer second) {

int f = first; int s = second; // Auto unboxing

return f < 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”);

}

}

  • Doesn’t print “Unbelievable”

  • But does throw NullPointerException!

  • When mixing primitives and boxed primitives, the boxed primitive is auto unboxed


More item 4917 l.jpg

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 < 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


Item 50 avoid strings where other types are more appropriate l.jpg

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.


  • Item 51 beware the performance of string concatenation l.jpg

    Item 51: Beware the Performance of String Concatenation

    // Inappropriate use of string concatenation – performs horribly

    public String statement() {

    String result = “”;

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

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

    }

    }

    // StringBuilder version – much faster

    public String statement() {

    StringBuilder b = new StringBuilder(numItems * LINE_WIDTH);

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

    b.append( lineForItem(i));

    }

    return b.toString();

    }


    Item 52 refer to objects by their interfaces l.jpg

    Item 52: Refer to Objects by Their Interfaces

    // Good – uses interfaces as type

    List <Subscriber> subscribers = new Vector<Subscriber>();

    // Bad – uses class as type

    Vector <Subscriber> subscribers = new Vector<Subscriber>();

    // Second form prohibits maintenance change to

    List <Subscriber> subscribers = new ArrayList<Subscriber>();

    • 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


    Item 53 prefer interfaces to reflection l.jpg

    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


    More item 53 l.jpg

    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

    Class<?> cl = null; // note that try/catch block interrupts declaration

    try{

    cl = Class.forName (args[0]);

    } 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 <String> s = null;

    try{

    s = (Set<String>) 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

    System.err.println(”Class not instantiable.”); System.exit(1);

    }

    // Exercise the set

    s.addAll(Arrays.asList(args).subList(1, args.length));

    System.out.println(s);

    }


    Item 54 use native methods judiciously l.jpg

    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


    Item 55 optimize judiciously l.jpg

    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: 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

    • 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


    More item 55 l.jpg

    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, doesn’t help legacy code


    More item 5526 l.jpg

    More Item 55

    • Fortunate fact

      • Good API design usually consistent with good performance

    • Don’t 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


    Item 56 adhere to generally accepted naming conventions l.jpg

    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


    More item 56 l.jpg

    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()


  • Login