Presentation is loading. Please wait.

Presentation is loading. Please wait.

Enter Title of Presentation Here Joshua Bloch Chief Java Architect

Similar presentations


Presentation on theme: "Enter Title of Presentation Here Joshua Bloch Chief Java Architect"— Presentation transcript:

1 Enter Title of Presentation Here Joshua Bloch Chief Java Architect
More Effective Java Joshua Bloch Chief Java Architect Google Confidential

2 Enter Title of Presentation Here
The wait is over! Google Confidential

3 Enter Title of Presentation Here
What’s New? Chapter 5: Generics Chapter 6: Enums and Annotations One or more items on all other Java™ 5 language features Threads chapter renamed Concurrency Rewritten for java.util.concurrent All existing items updated to reflect current best practices A few items added to reflect newly important patterns First edition had 57 items; second has 78 What’s as important as what’s changed is what hasn’t. The style of the book is the same as it ever was. Think of it as an old friend. A bit wiser, a bit heavier, but at heart, the same old Effective Java Google Confidential

4 Enter Title of Presentation Here
Agenda Generics (Item 28) Enum types (Items 31–34, 77) Lazy initialization (Item 71) Google Confidential

5 Item 28: Bounded Wildcards for API Flexibility
Enter Title of Presentation Here Item 28: Bounded Wildcards for API Flexibility Generic types are invariant That is, List<String> is not a subtype of List<Object> Good for compile-time type safety, but inflexible Bounded wildcard types provide additional API flexibilty List<String> is a subtype of List<? extends Object> List<Object> is a subtype of List<? super String> Probalby the hardest part of generic types in Java is wildcards. They allow you to increase the flexibility of your APIs, but they’re confusing. I’m going to teach you a mnemonic that cuts through the confusion. Google Confidential

6 A Mnemonic for Wildcard Usage
Enter Title of Presentation Here A Mnemonic for Wildcard Usage PECS—Producer extends, Consumer super For a T producer, use Foo<? extends T> For a T consumer, use Foo<? super T> Only applies to input parameters Don’t use wildcard types as return types Guess who? Google Confidential

7 Enter Title of Presentation Here
PECS in Action (1) Suppose you want to add bulk methods to Stack<E> void pushAll(Collection<E> src); void popAll(Collection<E > dst); Here’s how the declarations would look without wildcards. But these declarations aren’t very flexible. The src and dst types have to match the stack is exactly. Google Confidential

8 Enter Title of Presentation Here
PECS in Action (1) Suppose you want to add bulk methods to Stack<E> void pushAll(Collection<? extends E> src); src is an E producer void popAll(Collection<E> dst); Google Confidential

9 Enter Title of Presentation Here
PECS in Action (1) Suppose you want to add bulk methods to Stack<E> void pushAll(Collection<? extends E> src); src is an E producer void popAll(Collection<? super E> dst); dst is an E consumer And what do these wildcard declarations buy you? Google Confidential

10 Enter Title of Presentation Here
PECS in Action (1) Suppose you want to add bulk methods to Stack<E> void pushAll(Collection<? extends E> src); void popAll(Collection<? super E> dst); User can pushAll from a Collection<Long> or a Collection<Number> onto a Stack<Number> User can popAll into a Collection<Object> or a Collection<Number> from a Stack<Number> Google Confidential

11 Enter Title of Presentation Here
PECS in Action (2) Consider this generic method: public static <E> Set<E> union(Set<E> s1, Set<E> s2) This example concerns a parameterized method. Google Confidential

12 Enter Title of Presentation Here
PECS in Action (2) Consider this generic method: public static <E> Set<E> union(Set<? extends E> s1, Set<? extends E> s2) Both s1 and s2 are E producers No wildcard type for return value Wouldn’t make the API any more flexible Would force user to deal with wildcard types explicitly User should not have to think about wildcards to use your API And what do these wildcard declarations buy you? Google Confidential

13 Enter Title of Presentation Here
Agenda Generics (Items 28) Enum types (Items 31–34, 77) Lazy initialization (Item 71) Google Confidential

14 Item 31: How would you implement this
Enter Title of Presentation Here Item 31: How would you implement this public enum Ensemble { SOLO, DUET, TRIO, QUARTET, QUINTET, SEXTET, SEPTET, OCTET, NONET, DECTET; public int numberOfMusicians() { ??? } Google Confidential

15 A common but flawed approach
Enter Title of Presentation Here A common but flawed approach public enum Ensemble { SOLO, DUET, TRIO, QUARTET, QUINTET, SEXTET, SEPTET, OCTET, NONET, DECTET; public int numberOfMusicians() { return ordinal() + 1; } So what’s wrong with this? Google Confidential

16 What’s Wrong With This Usage?
Enter Title of Presentation Here What’s Wrong With This Usage? It’s a maintenance nightmare If you (or someone else) reorder constants, program breaks silently Can’t add multiple constants with same int value A double quartet is 8 musicians, just like an octet Awkward to add constants out of sequence A triple quartet is 12 musicians, but there’s no term for 11 First of all, it’s a maintenance nightmare... Also, it’s very restrictive... So what’s the right way to associate an int with an enum? Google Confidential

17 The Solution—Store int in an Instance Field
Enter Title of Presentation Here The Solution—Store int in an Instance Field public enum Ensemble { SOLO(1), DUET(2), TRIO(3), QUARTET(4), QUINTET(5), SEXTET(6), SEPTET(7), OCTET(8), DOUBLE_QUARTET(8), NONET(9), DECTET(10), TRIPLE_QUARTET(12); private final int numberOfMusicians; Ensemble(int size) { numberOfMusicians = size; } public int numberOfMusicians() { return numberOfMusicians; Google Confidential

18 Item 32: Bit Fields are Obsolete
Enter Title of Presentation Here Item 32: Bit Fields are Obsolete public class Text { public static final int STYLE_BOLD = 1; public static final int STYLE_ITALIC = 2; public static final int STYLE_UNDERLINE = 4; public static final int STYLE_STRIKETHROUGH = 8; // Param is bitwise OR of 0 or more STYLE_ values public void applyStyles(int styles) { ... } } Client Code text.applyStyles(Style_BOLD | Style_ITALIC); So what’s wrong with bit fields? Google Confidential

19 All the Problems of int Constants and More
Enter Title of Presentation Here All the Problems of int Constants and More Bit fields are not typesafe No namespace—must prefix constant names Brittle—constants compiled into clients Printed values are cryptic No easy way to iterate over elements represented by bit field If number of constants grows beyond 32, you are toast. Beyond 64, you’re burnt toast. Some programmers who use enums in preference to int constants still use bit fields when they need to pass around sets of constants. There is no reason to do this; a better alternative exists. Google Confidential

20 The Solution—EnumSet A Modern Replacement for Bit Fields
Enter Title of Presentation Here The Solution—EnumSet A Modern Replacement for Bit Fields public class Text { public enum Style { BOLD, ITALIC, UNDERLINE, STRIKETHROUGH } // Any Set could be passed in, but EnumSet is best public void applyStyles(Set<Style> styles) { ... } Client Code text.applyStyles(EnumSet.of(Style.BOLD, Style.ITALIC)); Google Confidential

21 Enum sets fix all the problems of bit fields
Enter Title of Presentation Here Enum sets fix all the problems of bit fields They are typesafe Enums have name spaces Values aren’t compiled into clients Printed values are easily readable [BOLD, ITALIC] Easy to iterate over elements in an enum set for (Style style : styles) No constraints on the number of constants in enum How much do you pay for this type safety and richness? Google Confidential

22 EnumSet Combines Safety, Power, Efficiency
Enter Title of Presentation Here EnumSet Combines Safety, Power, Efficiency Provides type safety, richness, and interoperability of Set Internally, each EnumSet is represented as a bit vector If underlying enum type has <= 64 elements, a single long If underlying enum type has > 64 elements, a long[] Bulk operations implemented with bitwise arithmetic Same as you’d do manually for bit fields Insulates you from the ugliness of manual bit twiddling Google Confidential

23 Item 33: How would you implement this?
Enter Title of Presentation Here Item 33: How would you implement this? public enum Phase { SOLID, LIQUID, GAS; public enum Transition { MELT, FREEZE, BOIL, CONDENSE, SUBLIME, DEPOSIT; // Returns phase transition from one phase to another public static Transition from(Phase src, Phase dst) { ??? } Sublime: Dry Ice -> Carbon Dioxide Google Confidential

24 Another common but flawed approach
Enter Title of Presentation Here Another common but flawed approach public enum Phase { SOLID, LIQUID, GAS; public enum Transition { MELT, FREEZE, BOIL, CONDENSE, SUBLIME, DEPOSIT; // Rows indexed by src-ordinal, cols by dst-ordinal private static final Transition[][] TRANSITIONS = { { null, MELT, SUBLIME }, { FREEZE, null, BOIL }, { DEPOSIT, CONDENSE, null } }; // Returns phase transition from one phase to another public static Transition from(Phase src, Phase dst) { return TRANSITIONS[src.ordinal()][dst.ordinal()]; } On the surface the technique appears elegant, but it has serious problems Google Confidential

25 What’s Wrong With This Usage?
Enter Title of Presentation Here What’s Wrong With This Usage? Mistakes in transition table cause runtime failures If you’re lucky ArrayIndexOutOfBoundsException or NullPointerException If not, silent erroneous behavior Maintenance nightmare Easy to mess up table if you add an enum value Size of table is quadratic in the number of phases If enum is large, table will not be readable Google Confidential

26 Enter Title of Presentation Here
The Solution—Use a (nested) EnumMap (1) The Right Way to Associate Data With Enums public enum Phase { SOLID, LIQUID, GAS; public enum Transition { MELT(SOLID, LIQUID), FREEZE(LIQUID, SOLID), BOIL(LIQUID, GAS), CONDENSE(GAS, LIQUID), SUBLIME(SOLID, GAS), DEPOSIT(GAS, SOLID); private final Phase src; private final Phase dst; Transition(Phase src, Phase dst) { this.src = src; this.dst = dst; } Notice that this makes the state transitions perfectly clear. No cryptic table! Google Confidential

27 Enter Title of Presentation Here
The Solution—Use a (nested) EnumMap (2) The Right Way to Associate Data With Enums // Initialize the phase transition map private static final Map<Phase, Map<Phase,Transition>> m = new EnumMap<Phase, Map<Phase,Transition>>(Phase.class); static { // Insert empty map for each src state for (Phase p : Phase.values()) m.put(p,new EnumMap<Phase,Transition>(Phase.class)); // Insert state transitions for (Transition trans : Transition.values()) m.get(trans.src).put(trans.dst, trans); } public static Transition from(Phase src, Phase dst) { return m.get(src).get(dst); Under the covers, the EnumMap is simply an array indexed by the elements ordinal, but the system ensures that everything is type typesafe, so you get the performance benefits without the clarity and safety costs. Google Confidential

28 Adding Support for the Plasma State
Enter Title of Presentation Here Adding Support for the Plasma State With original approach: Add the constant PLASMA to Phase Add IONIZE, DEIONIZE to Transition Add 1 new row and 7 new entries to the transition table Don’t make any mistakes or you’ll be sorry (at runtime) With EnumMap approach: Add IONIZE(GAS, PLASMA), DEIONIZE(PLASMA, GAS) That’s it! Program initializes table for you Now you know not to use the ordinal method to associate data with an enum, and not to use it to index into arrays? So what should you use it for? Google Confidential

29 What is the ordinal Method Good for?
Enter Title of Presentation Here What is the ordinal Method Good for? The Enum specification says this: Most programmers will have no use for the ordinal method. It is designed for use by general-purpose enum-based data structures such as EnumSet and EnumMap. Unless you are writing such a data structure, don’t use it If you do use ordinal: Assume only a dense mapping of nonnegative int to enum Don’t depend on which int value is assigned to which enum Google Confidential

30 Item 77: Pop Quiz: Is This Class a Singleton?
Enter Title of Presentation Here Item 77: Pop Quiz: Is This Class a Singleton? public class Elvis implements Serializable { public static final Elvis INSTANCE = new Elvis(); private Elvis() { } private final String[] favoriteSongs = { "Hound Dog", "Heartbreak Hotel" }; public void printFavorites() { System.out.println(Arrays.toString(favoriteSongs)); } private Object readResolve() { return INSTANCE; Google Confidential

31 Enter Title of Presentation Here
Answer: Unfortunately Not The first edition oversold the power of readResolve Elvis has a nontransient field (favoriteSongs) Cleverly crafted attack can save reference to deserialized Elvis instance when this field is deserialized See ElvisStealer for details (Item 77) readResolve works only if all fields are transient Google Confidential

32 Enter Title of Presentation Here
The Solution—Enum Singleton Pattern The Right Way to Implement a Serializable Singleton public enum Elvis { INSTANCE; private final String[] favoriteSongs = { "Hound Dog", "Heartbreak Hotel" }; public void printFavorites() { System.out.println(Arrays.toString(favoriteSongs)); } At first it may appear unnatural to use an enum for a singleton, but its shorter, cleaner, and safer. The JRE makes an ironclad guarantee that you’ll NEVER get a duplicate instance. Google Confidential

33 Item 34: Coping With a Limitation of Enums
Enter Title of Presentation Here Item 34: Coping With a Limitation of Enums Enums provide linguistic support for typesafe enum pattern All the advantages *, and more Support for EnumSet and EnumMap Reliable support for serialization Support for switch statement * But one thing is missing—you can’t extend an enum type In most cases, you shouldn’t One compelling use case—operation codes Classic example is the operations on a calculator; you might want to allow the user of an API to add more operations by subclassing the Operation type. Luckily, there’s a way to simulate this functionality with enums. Google Confidential

34 The Solution—Couple Enum With Interface (1) Emulated Extensible Enum
Enter Title of Presentation Here The Solution—Couple Enum With Interface (1) Emulated Extensible Enum public interface Operation { double apply(double x, double y); } public enum BasicOperation implements Operation { PLUS { public double apply(double x, double y){ return x + y; } }, MINUS { public double apply(double x, double y){ return x - y; } }, TIMES { public double apply(double x, double y){ return x * y; } }, DIVIDE { public double apply(double x, double y){ return x / y; } }; Use Operation to represent an operation in APIs Use Collection<? extends Operation> to represent multiple operations At first it may appear unnatural to use an enum for a singleton, but its shorter, cleaner, and safer. The JRE makes an ironclad guarantee that you’ll NEVER get a duplicate instance. Google Confidential

35 The Solution—Couple Enum With Interface (2) Emulated Extendable Enum
Enter Title of Presentation Here The Solution—Couple Enum With Interface (2) Emulated Extendable Enum public enum ExtendedOperation implements Operation { EXP { public double apply(double x, double y) { return Math.pow(x, y); } }, REMAINDER { return x % y; }; At first it may appear unnatural to use an enum for a singleton, but its shorter, cleaner, and safer. The JRE makes an ironclad guarantee that you’ll NEVER get a duplicate instance. Google Confidential

36 Enter Title of Presentation Here
Enum Summary Don’t use ordinal to store int data; use int field Don’t use bit fields; use EnumSet Don’t use ordinal to index arrays; use EnumMap Don’t use readResolve for serializable singleton; use enum Emulate extensible enums with interfaces Google Confidential

37 Enter Title of Presentation Here
Agenda Generics (Items 28) Enum types (Items 31–34, 77) Lazy initialization (Item 71) Google Confidential

38 Item 71: lazy initialization
Enter Title of Presentation Here Item 71: lazy initialization Delaying the initialization of a field until its value is needed When should you use it? To fix an initialization circularity To solve a performance problem Otherwise, prefer normal initialization private final FieldType field = computeFieldValue(); What is the best technique for lazy initialization? It depends Google Confidential

39 To Break an Initialization Circularity, Use a Synchronized Accessor
Enter Title of Presentation Here To Break an Initialization Circularity, Use a Synchronized Accessor private FieldType field; synchronized FieldType getField() {     if (field == null)         field = computeFieldValue();     return field; } This technique is simple, and clearly correct, but it gets exclusive access to the field every time it reads it, which can be expensive. Google Confidential

40 Enter Title of Presentation Here
For High-Performance on a Static Field, Use the Lazy Initialization Holder Class Idiom private static class FieldHolder { static final FieldType field = computeFieldValue(); } static FieldType getField() { return FieldHolder.field; This technique is almost magic. It’s guaranteed to work in the presence of multiple threads, so clearly it’s doing synchronization, but you can’t see it: it’s invisible. Moreover, it’s extremely fast: the VM actually patches the code one the field is initialized so that you aren’t doing the synchronization any more. The one disadvantage of this technique is that it only works for static fields. Google Confidential

41 For High-Performance on an Instance Field, Use the Double-Check Idiom
Enter Title of Presentation Here For High-Performance on an Instance Field, Use the Double-Check Idiom private volatile FieldType field; FieldType getField() { FieldType result = field; if (result == null) { // 1st check (no lock) synchronized(this) { result = field; if (result == null) // 2nd check (w/ lock) field = result = computeFieldValue(); } return result; This code is extremely tricky and delicate. Normally I’m strongly against cutting-and-pasting, but in this case I’ll make an exception. Google Confidential

42 Lazy Initialization Summary
Enter Title of Presentation Here Lazy Initialization Summary Your default instinct should be normal (not lazy) initialization To break an initialization circularity: synchronized accessor For performance on a static field: holder class idiom For performance on an instance field: double-check idiom Google Confidential

43 Shameless Commerce Division
Enter Title of Presentation Here Shameless Commerce Division For (much) more information: Available wherever finer books are sold (?) Google Confidential

44 Enter Title of Presentation Here Joshua Bloch Chief Java Architect
More Effective Java Joshua Bloch Chief Java Architect Google Confidential


Download ppt "Enter Title of Presentation Here Joshua Bloch Chief Java Architect"

Similar presentations


Ads by Google