effective java general programming
Download
Skip this Video
Download Presentation
Effective Java: General Programming

Loading in 2 Seconds...

play fullscreen
1 / 28

Effective Java: General Programming - PowerPoint PPT Presentation


  • 143 Views
  • Uploaded on

Agenda. Material From Joshua BlochEffective Java 2nd EditionCover Items 45-56?General Programming\" ChapterBottom Line: Nuts and bolts of the Java languageTreatment of two extralinguistic language facilitiesOptimization and naming conventions. Item 45: Minimize the Scope of Local Variables

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about 'Effective Java: General Programming' - shae


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
agenda
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
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
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 i = c.iterator();

while (i.hasNext()) {

doSomething(i.next());

}

Iterator i2 = c2.iterator();

while (i.hasNext()) {

doSomething(i2.next());

}

BUG!

Unfortunately, this bug is silent

more item 45 solution with for loops
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 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());

}

more item 45 example of multiple initializations
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
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
More Item 46: Nested Iterations

// Can you spot the bug?

enum Suit { CLUB, DIAMOND, HEART, SPADE }

enum Rank { ACE, DEUCE, …, KING }

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

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

}

}

// Fixed – but still ugly

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

}

}

more item 46 using the for each loop
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 faces = Arrays.asList(Face.values());

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

for Iterator 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
More Item 46: Iterable interface
  • Simple to implement Iterable interface:

// public interface Iterable {

// Returns an iterator over the elements in this iterable

public Iterator 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
More Item 46: Implementing and then using Iterable

public class IterableExample {

public static void main( String[] args) {

Example example = new Example();

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

for (String s: example) {

System.out.println (s);

}

}

}

public class Example implements Iterable {

Set s = new TreeSet();

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

public Iterator iterator() { return s.iterator(); }

}

item 47 know and use the libraries
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
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
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
Item 49: Prefer Primitive Types to Boxed Primitives

// Broken comparator – can you spot the flaw?

Comparator < Integer> naturalOrder =

new Comparator() { // 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
More Item 49

// Repaired version

Comparator < Integer> naturalOrder =

new Comparator() { // 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
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
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
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
Item 52: Refer to Objects by Their Interfaces

// Good – uses interfaces as type

List subscribers = new Vector();

// Bad – uses class as type

Vector subscribers = new Vector();

// Second form prohibits maintenance change to

List subscribers = new ArrayList();

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

try{

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