diff --git a/.gitignore b/.gitignore index af9c1434..e13565ec 100644 --- a/.gitignore +++ b/.gitignore @@ -1,50 +1,53 @@ -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Avoid ignoring Maven wrapper jar file (.jar files are usually ignored) +!/.mvn/wrapper/maven-wrapper.jar + + +### Java template +*.class + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.ear + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 -# I [jjb] added this to ignore emacs autosaves -*~ - -# User-specific stuff -# .idea/**/workspace.xml -# .idea/**/tasks.xml -# .idea/**/usage.statistics.xml -# .idea/**/dictionaries -# .idea/**/shelf -.idea - -# Sensitive or high-churn files -# .idea/**/dataSources/ -# .idea/**/dataSources.ids -# .idea/**/dataSources.local.xml -# .idea/**/sqlDataSources.xml -# .idea/**/dynamic.xml -# .idea/**/uiDesigner.xml -# .idea/**/dbnavigator.xml - -# Gradle -.idea/**/gradle.xml -.idea/**/libraries - -# Gradle and Maven with auto-import -# When using Gradle or Maven with auto-import, you should exclude module files, -# since they will be recreated, and may cause churn. Uncomment if using -# auto-import. -# .idea/modules.xml -# .idea/*.iml -# .idea/modules - -# CMake -cmake-build-*/ - -# Mongo Explorer plugin -# .idea/**/mongoSettings.xml - -# File-based project format +# User-specific stuff: +.idea/workspace.xml +.idea/tasks.xml +.idea/dictionaries +.idea/vcs.xml +.idea/jsLibraryMappings.xml + +# Sensitive or high-churn files: +.idea/dataSources.ids +.idea/dataSources.xml +.idea/dataSources.local.xml +.idea/sqlDataSources.xml +.idea/dynamic.xml +.idea/uiDesigner.xml + +# Gradle: +.idea/gradle.xml +.idea/ + +# Mongo Explorer plugin: +.idea/mongoSettings.xml + +## File-based project format: *.iws -*.iml + +## Plugin-specific files: # IntelliJ -out/ +/out/ # mpeltonen/sbt-idea plugin .idea_modules/ @@ -52,14 +55,47 @@ out/ # JIRA plugin atlassian-ide-plugin.xml -# Cursive Clojure plugin -# .idea/replstate.xml - # Crashlytics plugin (for Android Studio and IntelliJ) com_crashlytics_export_strings.xml crashlytics.properties crashlytics-build.properties fabric.properties +### Windows template +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini -# Editor-based Rest Client -# .idea/httpRequests +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# Windows shortcuts +*.lnk +### Maven template +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +# ignore eclipse files +.project +.classpath +.settings +.metadata + +# 日志文件 +*.log +*.iml +/.idea/vcs.xml diff --git a/pom.xml b/pom.xml new file mode 100644 index 00000000..4634cd0a --- /dev/null +++ b/pom.xml @@ -0,0 +1,37 @@ + + + 4.0.0 + + effective-java-3e-source-code + book.example + 1.0.0-SNAPSHOT + + + + junit + junit + 4.12 + + + com.fasterxml.jackson.module + jackson-module-jaxb-annotations + 2.3.1 + + + org.slf4j + slf4j-simple + 1.7.25 + + + + + + org.apache.maven.plugins + maven-resources-plugin + + + + + \ No newline at end of file diff --git a/src/effectivejava/chapter11/item79/ForwardingSet.java b/src/effectivejava/chapter11/item79/ForwardingSet.java deleted file mode 100644 index 9b0c83ea..00000000 --- a/src/effectivejava/chapter11/item79/ForwardingSet.java +++ /dev/null @@ -1,30 +0,0 @@ -package effectivejava.chapter11.item79; -import java.util.*; - -// Reusable forwarding class (Page XXX) -public class ForwardingSet implements Set { - private final Set s; - public ForwardingSet(Set s) { this.s = s; } - - public void clear() { s.clear(); } - public boolean contains(Object o) { return s.contains(o); } - public boolean isEmpty() { return s.isEmpty(); } - public int size() { return s.size(); } - public Iterator iterator() { return s.iterator(); } - public boolean add(E e) { return s.add(e); } - public boolean remove(Object o) { return s.remove(o); } - public boolean containsAll(Collection c) - { return s.containsAll(c); } - public boolean addAll(Collection c) - { return s.addAll(c); } - public boolean removeAll(Collection c) - { return s.removeAll(c); } - public boolean retainAll(Collection c) - { return s.retainAll(c); } - public Object[] toArray() { return s.toArray(); } - public T[] toArray(T[] a) { return s.toArray(a); } - @Override public boolean equals(Object o) - { return s.equals(o); } - @Override public int hashCode() { return s.hashCode(); } - @Override public String toString() { return s.toString(); } -} diff --git a/src/effectivejava/chapter2/item6/Sum.java b/src/effectivejava/chapter2/item6/Sum.java deleted file mode 100644 index 2a7a7ebd..00000000 --- a/src/effectivejava/chapter2/item6/Sum.java +++ /dev/null @@ -1,29 +0,0 @@ -package effectivejava.chapter2.item6; - -import java.util.Comparator; - -// Hideously slow program! Can you spot the object creation? (Page 24) -public class Sum { - private static long sum() { - Long sum = 0L; - for (long i = 0; i <= Integer.MAX_VALUE; i++) - sum += i; - return sum; - } - - public static void main(String[] args) { - int numSets = Integer.parseInt(args[0]); - long x = 0; - - for (int i = 0; i < numSets; i++) { - long start = System.nanoTime(); - x += sum(); - long end = System.nanoTime(); - System.out.println((end - start) / 1_000_000. + " ms."); - } - - // Prevents VM from optimizing away everything. - if (x == 42) - System.out.println(); - } -} \ No newline at end of file diff --git a/src/effectivejava/chapter2/item8/Adult.java b/src/effectivejava/chapter2/item8/Adult.java deleted file mode 100644 index 9f71f762..00000000 --- a/src/effectivejava/chapter2/item8/Adult.java +++ /dev/null @@ -1,10 +0,0 @@ -package effectivejava.chapter2.item8; - -// Well-behaved client of resource with cleaner safety-net (Page 33) -public class Adult { - public static void main(String[] args) { - try (Room myRoom = new Room(7)) { - System.out.println("Goodbye"); - } - } -} diff --git a/src/effectivejava/chapter2/item8/Room.java b/src/effectivejava/chapter2/item8/Room.java deleted file mode 100644 index a52a2d45..00000000 --- a/src/effectivejava/chapter2/item8/Room.java +++ /dev/null @@ -1,38 +0,0 @@ -package effectivejava.chapter2.item8; - -import java.lang.ref.Cleaner; - -// An autocloseable class using a cleaner as a safety net (Page 32) -public class Room implements AutoCloseable { - private static final Cleaner cleaner = Cleaner.create(); - - // Resource that requires cleaning. Must not refer to Room! - private static class State implements Runnable { - int numJunkPiles; // Number of junk piles in this room - - State(int numJunkPiles) { - this.numJunkPiles = numJunkPiles; - } - - // Invoked by close method or cleaner - @Override public void run() { - System.out.println("Cleaning room"); - numJunkPiles = 0; - } - } - - // The state of this room, shared with our cleanable - private final State state; - - // Our cleanable. Cleans the room when it’s eligible for gc - private final Cleaner.Cleanable cleanable; - - public Room(int numJunkPiles) { - state = new State(numJunkPiles); - cleanable = cleaner.register(this, state); - } - - @Override public void close() { - cleanable.clean(); - } -} diff --git a/src/effectivejava/chapter2/item8/Teenager.java b/src/effectivejava/chapter2/item8/Teenager.java deleted file mode 100644 index 28d080ce..00000000 --- a/src/effectivejava/chapter2/item8/Teenager.java +++ /dev/null @@ -1,14 +0,0 @@ -package effectivejava.chapter2.item8; - -import java.util.concurrent.TimeUnit; - -// Ill-behaved client of resource with cleaner safety-net (Page 33) -public class Teenager { - public static void main(String[] args) { - new Room(99); - System.out.println("Peace out"); - - // Uncomment next line and retest behavior, but note that you MUST NOT depend on this behavior! -// System.gc(); - } -} diff --git a/src/effectivejava/chapter4/item18/ForwardingSet.java b/src/effectivejava/chapter4/item18/ForwardingSet.java deleted file mode 100644 index 307822ff..00000000 --- a/src/effectivejava/chapter4/item18/ForwardingSet.java +++ /dev/null @@ -1,30 +0,0 @@ -package effectivejava.chapter4.item18; -import java.util.*; - -// Reusable forwarding class (Page 90) -public class ForwardingSet implements Set { - private final Set s; - public ForwardingSet(Set s) { this.s = s; } - - public void clear() { s.clear(); } - public boolean contains(Object o) { return s.contains(o); } - public boolean isEmpty() { return s.isEmpty(); } - public int size() { return s.size(); } - public Iterator iterator() { return s.iterator(); } - public boolean add(E e) { return s.add(e); } - public boolean remove(Object o) { return s.remove(o); } - public boolean containsAll(Collection c) - { return s.containsAll(c); } - public boolean addAll(Collection c) - { return s.addAll(c); } - public boolean removeAll(Collection c) - { return s.removeAll(c); } - public boolean retainAll(Collection c) - { return s.retainAll(c); } - public Object[] toArray() { return s.toArray(); } - public T[] toArray(T[] a) { return s.toArray(a); } - @Override public boolean equals(Object o) - { return s.equals(o); } - @Override public int hashCode() { return s.hashCode(); } - @Override public String toString() { return s.toString(); } -} diff --git a/src/effectivejava/chapter6/item34/Operation.java b/src/effectivejava/chapter6/item34/Operation.java deleted file mode 100644 index 6b88fc3a..00000000 --- a/src/effectivejava/chapter6/item34/Operation.java +++ /dev/null @@ -1,47 +0,0 @@ -package effectivejava.chapter6.item34; -import java.util.*; -import java.util.stream.Stream; - -import static java.util.stream.Collectors.toMap; - -// Enum type with constant-specific class bodies and data (Page 161) -public enum 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; } - }; - - private final String symbol; - - Operation(String symbol) { this.symbol = symbol; } - - @Override public String toString() { return symbol; } - - public abstract double apply(double x, double y); - - // Implementing a fromString method on an enum type - private static final Map stringToEnum = - Stream.of(values()).collect( - toMap(Object::toString, e -> e)); - - // Returns Operation for string, if any - public static Optional fromString(String symbol) { - return Optional.ofNullable(stringToEnum.get(symbol)); - } - - public static void main(String[] args) { - double x = Double.parseDouble(args[0]); - double y = Double.parseDouble(args[1]); - for (Operation op : Operation.values()) - System.out.printf("%f %s %f = %f%n", - x, op, y, op.apply(x, y)); - } -} diff --git a/src/effectivejava/chapter6/item34/PayrollDay.java b/src/effectivejava/chapter6/item34/PayrollDay.java deleted file mode 100644 index 0dc831ab..00000000 --- a/src/effectivejava/chapter6/item34/PayrollDay.java +++ /dev/null @@ -1,39 +0,0 @@ -package effectivejava.chapter6.item34; - -// The strategy enum pattern -enum PayrollDay { - MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, - SATURDAY(PayType.WEEKEND), SUNDAY(PayType.WEEKEND); - - private final PayType payType; - - PayrollDay(PayType payType) { this.payType = payType; } - PayrollDay() { this(PayType.WEEKDAY); } // Default - - int pay(int minutesWorked, int payRate) { - return payType.pay(minutesWorked, payRate); - } - - // The strategy enum type - private enum PayType { - WEEKDAY { - int overtimePay(int minsWorked, int payRate) { - return minsWorked <= MINS_PER_SHIFT ? 0 : - (minsWorked - MINS_PER_SHIFT) * payRate / 2; - } - }, - WEEKEND { - int overtimePay(int minsWorked, int payRate) { - return minsWorked * payRate / 2; - } - }; - - abstract int overtimePay(int mins, int payRate); - private static final int MINS_PER_SHIFT = 8 * 60; - - int pay(int minsWorked, int payRate) { - int basePay = minsWorked * payRate; - return basePay + overtimePay(minsWorked, payRate); - } - } -} diff --git a/src/effectivejava/chapter6/item34/WeightTable.java b/src/effectivejava/chapter6/item34/WeightTable.java deleted file mode 100644 index 8569a739..00000000 --- a/src/effectivejava/chapter6/item34/WeightTable.java +++ /dev/null @@ -1,12 +0,0 @@ -package effectivejava.chapter6.item34; - -// Takes earth-weight and prints table of weights on all planets - Page 158 -public class WeightTable { - public static void main(String[] args) { - double earthWeight = Double.parseDouble(args[0]); - double mass = earthWeight / Planet.EARTH.surfaceGravity(); - for (Planet p : Planet.values()) - System.out.printf("Weight on %s is %f%n", - p, p.surfaceWeight(mass)); - } -} diff --git a/src/effectivejava/chapter6/item38/BasicOperation.java b/src/effectivejava/chapter6/item38/BasicOperation.java deleted file mode 100644 index dd49d331..00000000 --- a/src/effectivejava/chapter6/item38/BasicOperation.java +++ /dev/null @@ -1,27 +0,0 @@ -package effectivejava.chapter6.item38; - -// Emulated extensible enum using an interface - Basic implementation - Page 174 -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; } - }; - - private final String symbol; - - BasicOperation(String symbol) { - this.symbol = symbol; - } - - @Override public String toString() { - return symbol; - } -} diff --git a/src/effectivejava/chapter6/item39/regularannotation/Sample.java b/src/effectivejava/chapter6/item39/regularannotation/Sample.java deleted file mode 100644 index 4131fe77..00000000 --- a/src/effectivejava/chapter6/item39/regularannotation/Sample.java +++ /dev/null @@ -1,17 +0,0 @@ -package effectivejava.chapter6.item39.regularannotation; - -// Program containing marker annotations - Page 170 -public class Sample { - @Test public static void m1() { } // Test should pass - public static void m2() { } - @Test public static void m3() { // Test should fail - throw new RuntimeException("Boom"); - } - public static void m4() { } - @Test public void m5() { } // INVALID USE: nonstatic method - public static void m6() { } - @Test public static void m7() { // Test should fail - throw new RuntimeException("Crash"); - } - public static void m8() { } -} \ No newline at end of file diff --git a/src/effectivejava/chapter6/item40/Bigram.java b/src/effectivejava/chapter6/item40/Bigram.java deleted file mode 100644 index 0a9a33e6..00000000 --- a/src/effectivejava/chapter6/item40/Bigram.java +++ /dev/null @@ -1,29 +0,0 @@ -package effectivejava.chapter6.item40; -import java.util.*; - -// Can you spot the bug? (Page 188) -public class Bigram { - private final char first; - private final char second; - - public Bigram(char first, char second) { - this.first = first; - this.second = second; - } - - public boolean equals(Bigram b) { - return b.first == first && b.second == second; - } - - public int hashCode() { - return 31 * first + second; - } - - public static void main(String[] args) { - Set s = new HashSet<>(); - for (int i = 0; i < 10; i++) - for (char ch = 'a'; ch <= 'z'; ch++) - s.add(new Bigram(ch, ch)); - System.out.println(s.size()); - } -} diff --git a/src/effectivejava/chapter8/item50/Period.java b/src/effectivejava/chapter8/item50/Period.java deleted file mode 100644 index a02240d8..00000000 --- a/src/effectivejava/chapter8/item50/Period.java +++ /dev/null @@ -1,54 +0,0 @@ -package effectivejava.chapter8.item50; -import java.util.*; - -// Broken "immutable" time period class - Page 231-3 -public final class Period { - private final Date start; - private final Date end; - - /** - * @param start the beginning of the period - * @param end the end of the period; must not precede start - * @throws IllegalArgumentException if start is after end - * @throws NullPointerException if start or end is null - */ - public Period(Date start, Date end) { - if (start.compareTo(end) > 0) - throw new IllegalArgumentException( - start + " after " + end); - this.start = start; - this.end = end; - } - - public Date start() { - return start; - } - public Date end() { - return end; - } - - public String toString() { - return start + " - " + end; - } - -// // Repaired constructor - makes defensive copies of parameters -// public Period(Date start, Date end) { -// this.start = new Date(start.getTime()); -// this.end = new Date(end.getTime()); -// -// if (this.start.compareTo(this.end) > 0) -// throw new IllegalArgumentException( -// this.start + " after " + this.end); -// } - -// // Repaired accessors - make defensive copies of internal fields (Page 233) -// public Date start() { -// return new Date(start.getTime()); -// } -// -// public Date end() { -// return new Date(end.getTime()); -// } - - // Remainder omitted -} \ No newline at end of file diff --git a/src/effectivejava/chapter8/item52/CollectionClassifier.java b/src/effectivejava/chapter8/item52/CollectionClassifier.java deleted file mode 100644 index fc92d2aa..00000000 --- a/src/effectivejava/chapter8/item52/CollectionClassifier.java +++ /dev/null @@ -1,34 +0,0 @@ -package effectivejava.chapter8.item52; -import java.util.*; -import java.math.*; - -// Broken! - What does this program print? (Page 238) -public class CollectionClassifier { - public static String classify(Set s) { - return "Set"; - } - - public static String classify(List lst) { - return "List"; - } - - public static String classify(Collection c) { - return "Unknown Collection"; - } - - public static void main(String[] args) { - Collection[] collections = { - new HashSet(), - new ArrayList(), - new HashMap().values() - }; - - for (Collection c : collections) - System.out.println(classify(c)); - } - // Repaired static classifier method. (Page 240) -// public static String classify(Collection c) { -// return c instanceof Set ? "Set" : -// c instanceof List ? "List" : "Unknown Collection"; -// } -} diff --git a/src/effectivejava/chapter9/item61/BrokenComparator.java b/src/effectivejava/chapter9/item61/BrokenComparator.java deleted file mode 100644 index c520e404..00000000 --- a/src/effectivejava/chapter9/item61/BrokenComparator.java +++ /dev/null @@ -1,20 +0,0 @@ -package effectivejava.chapter9.item61; -import java.util.*; - -// Broken comparator - can you spot the flaw? - Page 273 -public class BrokenComparator { - public static void main(String[] args) { - -// Comparator naturalOrder = -// (i, j) -> (i < j) ? -1 : (i == j ? 0 : 1); - - // Fixed Comparator - Page 274 - Comparator naturalOrder = (iBoxed, jBoxed) -> { - int i = iBoxed, j = jBoxed; // Auto-unboxing - return i < j ? -1 : (i == j ? 0 : 1); - }; - - int result = naturalOrder.compare(new Integer(42), new Integer(42)); - System.out.println(result); - } -} diff --git a/src/main/dst.txt b/src/main/dst.txt new file mode 100644 index 00000000..274c0052 --- /dev/null +++ b/src/main/dst.txt @@ -0,0 +1 @@ +1234 \ No newline at end of file diff --git a/src/effectivejava/chapter10/item74/IndexOutOfBoundsException.java b/src/main/java/effectivejava/chapter10/item74/IndexOutOfBoundsException.java similarity index 100% rename from src/effectivejava/chapter10/item74/IndexOutOfBoundsException.java rename to src/main/java/effectivejava/chapter10/item74/IndexOutOfBoundsException.java diff --git a/src/effectivejava/chapter11/item78/brokenstopthread/StopThread.java b/src/main/java/effectivejava/chapter11/item78/brokenstopthread/StopThread.java similarity index 84% rename from src/effectivejava/chapter11/item78/brokenstopthread/StopThread.java rename to src/main/java/effectivejava/chapter11/item78/brokenstopthread/StopThread.java index d5bc6659..c5cab87e 100644 --- a/src/effectivejava/chapter11/item78/brokenstopthread/StopThread.java +++ b/src/main/java/effectivejava/chapter11/item78/brokenstopthread/StopThread.java @@ -1,5 +1,6 @@ package effectivejava.chapter11.item78.brokenstopthread; -import java.util.concurrent.*; + +import java.util.concurrent.TimeUnit; // Broken! - How long would you expect this program to run? (Page 312) public class StopThread { @@ -9,8 +10,9 @@ public static void main(String[] args) throws InterruptedException { Thread backgroundThread = new Thread(() -> { int i = 0; - while (!stopRequested) + while (!stopRequested) { i++; + } }); backgroundThread.start(); diff --git a/src/effectivejava/chapter11/item78/fixedstopthread1/StopThread.java b/src/main/java/effectivejava/chapter11/item78/fixedstopthread1/StopThread.java similarity index 87% rename from src/effectivejava/chapter11/item78/fixedstopthread1/StopThread.java rename to src/main/java/effectivejava/chapter11/item78/fixedstopthread1/StopThread.java index c20c62b6..c625433b 100644 --- a/src/effectivejava/chapter11/item78/fixedstopthread1/StopThread.java +++ b/src/main/java/effectivejava/chapter11/item78/fixedstopthread1/StopThread.java @@ -1,5 +1,6 @@ package effectivejava.chapter11.item78.fixedstopthread1; -import java.util.concurrent.*; + +import java.util.concurrent.TimeUnit; // Properly synchronized cooperative thread termination public class StopThread { @@ -17,8 +18,9 @@ public static void main(String[] args) throws InterruptedException { Thread backgroundThread = new Thread(() -> { int i = 0; - while (!stopRequested()) + while (!stopRequested()) { i++; + } }); backgroundThread.start(); diff --git a/src/effectivejava/chapter11/item78/fixedstopthread2/StopThread.java b/src/main/java/effectivejava/chapter11/item78/fixedstopthread2/StopThread.java similarity index 84% rename from src/effectivejava/chapter11/item78/fixedstopthread2/StopThread.java rename to src/main/java/effectivejava/chapter11/item78/fixedstopthread2/StopThread.java index 3a11ab2a..fccee0b2 100644 --- a/src/effectivejava/chapter11/item78/fixedstopthread2/StopThread.java +++ b/src/main/java/effectivejava/chapter11/item78/fixedstopthread2/StopThread.java @@ -1,5 +1,6 @@ package effectivejava.chapter11.item78.fixedstopthread2; -import java.util.concurrent.*; + +import java.util.concurrent.TimeUnit; // Cooperative thread termination with a volatile field public class StopThread { @@ -9,8 +10,9 @@ public static void main(String[] args) throws InterruptedException { Thread backgroundThread = new Thread(() -> { int i = 0; - while (!stopRequested) + while (!stopRequested) { i++; + } }); backgroundThread.start(); diff --git a/src/main/java/effectivejava/chapter11/item79/ForwardingSet.java b/src/main/java/effectivejava/chapter11/item79/ForwardingSet.java new file mode 100644 index 00000000..9fd7193d --- /dev/null +++ b/src/main/java/effectivejava/chapter11/item79/ForwardingSet.java @@ -0,0 +1,94 @@ +package effectivejava.chapter11.item79; + +import java.util.Collection; +import java.util.Iterator; +import java.util.Set; + +// Reusable forwarding class (Page XXX) +public class ForwardingSet implements Set { + private final Set s; + + public ForwardingSet(Set s) { + this.s = s; + } + + @Override + public void clear() { + s.clear(); + } + + @Override + public boolean contains(Object o) { + return s.contains(o); + } + + @Override + public boolean isEmpty() { + return s.isEmpty(); + } + + @Override + public int size() { + return s.size(); + } + + @Override + public Iterator iterator() { + return s.iterator(); + } + + @Override + public boolean add(E e) { + return s.add(e); + } + + @Override + public boolean remove(Object o) { + return s.remove(o); + } + + @Override + public boolean containsAll(Collection c) { + return s.containsAll(c); + } + + @Override + public boolean addAll(Collection c) { + return s.addAll(c); + } + + @Override + public boolean removeAll(Collection c) { + return s.removeAll(c); + } + + @Override + public boolean retainAll(Collection c) { + return s.retainAll(c); + } + + @Override + public Object[] toArray() { + return s.toArray(); + } + + @Override + public T[] toArray(T[] a) { + return s.toArray(a); + } + + @Override + public boolean equals(Object o) { + return s.equals(o); + } + + @Override + public int hashCode() { + return s.hashCode(); + } + + @Override + public String toString() { + return s.toString(); + } +} diff --git a/src/effectivejava/chapter11/item79/ObservableSet.java b/src/main/java/effectivejava/chapter11/item79/ObservableSet.java similarity index 52% rename from src/effectivejava/chapter11/item79/ObservableSet.java rename to src/main/java/effectivejava/chapter11/item79/ObservableSet.java index 82ffb00f..24db523d 100644 --- a/src/effectivejava/chapter11/item79/ObservableSet.java +++ b/src/main/java/effectivejava/chapter11/item79/ObservableSet.java @@ -1,71 +1,81 @@ package effectivejava.chapter11.item79; -import java.util.*; -import java.util.concurrent.CopyOnWriteArrayList; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Set; // Broken - invokes alien method from synchronized block! public class ObservableSet extends ForwardingSet { - public ObservableSet(Set set) { super(set); } + public ObservableSet(Set set) { + super(set); + } -// private final List> observers -// = new ArrayList<>(); + private final List> observers + = new ArrayList<>(); -// public void addObserver(SetObserver observer) { -// synchronized(observers) { -// observers.add(observer); -// } -// } -// -// public boolean removeObserver(SetObserver observer) { -// synchronized(observers) { -// return observers.remove(observer); -// } -// } + public void addObserver(SetObserver observer) { + synchronized (observers) { + observers.add(observer); + } + } -// private void notifyElementAdded(E element) { -// synchronized(observers) { -// for (SetObserver observer : observers) -// observer.added(this, element); -// } -// } + public boolean removeObserver(SetObserver observer) { + synchronized (observers) { + return observers.remove(observer); + } + } -// // Alien method moved outside of synchronized block - open calls + private void notifyElementAdded(E element) { + synchronized (observers) { + for (SetObserver observer : observers) { + observer.added(this, element); + } + } + } + + // Alien method moved outside of synchronized block - open calls // private void notifyElementAdded(E element) { // List> snapshot = null; -// synchronized(observers) { +// synchronized (observers) { // snapshot = new ArrayList<>(observers); // } -// for (SetObserver observer : snapshot) +// for (SetObserver observer : snapshot) { // observer.added(this, element); +// } // } // Thread-safe observable set with CopyOnWriteArrayList - private final List> observers = - new CopyOnWriteArrayList<>(); - - public void addObserver(SetObserver observer) { - observers.add(observer); - } - - public boolean removeObserver(SetObserver observer) { - return observers.remove(observer); - } - - private void notifyElementAdded(E element) { - for (SetObserver observer : observers) - observer.added(this, element); - } - +// private final List> observers = +// new CopyOnWriteArrayList<>(); +// +// public void addObserver(SetObserver observer) { +// observers.add(observer); +// } +// +// public boolean removeObserver(SetObserver observer) { +// return observers.remove(observer); +// } +// +// private void notifyElementAdded(E element) { +// for (SetObserver observer : observers) { +// observer.added(this, element); +// } +// } +// @Override public boolean add(E element) { boolean added = super.add(element); - if (added) + if (added) { notifyElementAdded(element); + } return added; } @Override public boolean addAll(Collection c) { boolean result = false; - for (E element : c) + for (E element : c) { result |= add(element); // Calls notifyElementAdded + } return result; } } diff --git a/src/effectivejava/chapter11/item79/SetObserver.java b/src/main/java/effectivejava/chapter11/item79/SetObserver.java similarity index 100% rename from src/effectivejava/chapter11/item79/SetObserver.java rename to src/main/java/effectivejava/chapter11/item79/SetObserver.java diff --git a/src/effectivejava/chapter11/item79/Test1.java b/src/main/java/effectivejava/chapter11/item79/Test1.java similarity index 81% rename from src/effectivejava/chapter11/item79/Test1.java rename to src/main/java/effectivejava/chapter11/item79/Test1.java index ea1ae9ea..e76af6ad 100644 --- a/src/effectivejava/chapter11/item79/Test1.java +++ b/src/main/java/effectivejava/chapter11/item79/Test1.java @@ -1,5 +1,6 @@ package effectivejava.chapter11.item79; -import java.util.*; + +import java.util.HashSet; // Simple test of ObservableSet - Page 318 public class Test1 { @@ -9,7 +10,8 @@ public static void main(String[] args) { set.addObserver((s, e) -> System.out.println(e)); - for (int i = 0; i < 100; i++) + for (int i = 0; i < 100; i++) { set.add(i); + } } } diff --git a/src/effectivejava/chapter11/item79/Test2.java b/src/main/java/effectivejava/chapter11/item79/Test2.java similarity index 77% rename from src/effectivejava/chapter11/item79/Test2.java rename to src/main/java/effectivejava/chapter11/item79/Test2.java index 275f092c..f876af63 100644 --- a/src/effectivejava/chapter11/item79/Test2.java +++ b/src/main/java/effectivejava/chapter11/item79/Test2.java @@ -1,5 +1,6 @@ package effectivejava.chapter11.item79; -import java.util.*; + +import java.util.HashSet; // More complex test of ObservableSet - Page 318-9 public class Test2 { @@ -8,14 +9,17 @@ public static void main(String[] args) { new ObservableSet<>(new HashSet<>()); set.addObserver(new SetObserver<>() { + @Override public void added(ObservableSet s, Integer e) { System.out.println(e); - if (e == 23) + if (e == 23) { s.removeObserver(this); + } } }); - for (int i = 0; i < 100; i++) + for (int i = 0; i < 100; i++) { set.add(i); + } } } diff --git a/src/effectivejava/chapter11/item79/Test3.java b/src/main/java/effectivejava/chapter11/item79/Test3.java similarity index 94% rename from src/effectivejava/chapter11/item79/Test3.java rename to src/main/java/effectivejava/chapter11/item79/Test3.java index d7534224..25af765e 100644 --- a/src/effectivejava/chapter11/item79/Test3.java +++ b/src/main/java/effectivejava/chapter11/item79/Test3.java @@ -12,6 +12,7 @@ public static void main(String[] args) { // Observer that uses a background thread needlessly set.addObserver(new SetObserver<>() { + @Override public void added(ObservableSet s, Integer e) { System.out.println(e); if (e == 23) { @@ -28,7 +29,8 @@ public void added(ObservableSet s, Integer e) { } }); - for (int i = 0; i < 100; i++) + for (int i = 0; i < 100; i++) { set.add(i); + } } } \ No newline at end of file diff --git a/src/effectivejava/chapter11/item81/ConcurrentTimer.java b/src/main/java/effectivejava/chapter11/item81/ConcurrentTimer.java similarity index 58% rename from src/effectivejava/chapter11/item81/ConcurrentTimer.java rename to src/main/java/effectivejava/chapter11/item81/ConcurrentTimer.java index c9f2304c..bf47541e 100644 --- a/src/effectivejava/chapter11/item81/ConcurrentTimer.java +++ b/src/main/java/effectivejava/chapter11/item81/ConcurrentTimer.java @@ -1,15 +1,29 @@ package effectivejava.chapter11.item81; -import java.util.concurrent.*; + +import java.util.Date; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; // Simple framework for timing concurrent execution 327 public class ConcurrentTimer { - private ConcurrentTimer() { } // Noninstantiable + private ConcurrentTimer() { + } // Noninstantiable + /** + * 多个线程同时执行单个任务,并等待最后的执行单元完成 + * + * @param executor 执行单元 + * @param concurrency 同时执行任务数,并发数 + * @param action 任务动作 + * @return + * @throws InterruptedException + */ public static long time(Executor executor, int concurrency, Runnable action) throws InterruptedException { CountDownLatch ready = new CountDownLatch(concurrency); CountDownLatch start = new CountDownLatch(1); - CountDownLatch done = new CountDownLatch(concurrency); + CountDownLatch done = new CountDownLatch(concurrency); for (int i = 0; i < concurrency; i++) { executor.execute(() -> { @@ -31,4 +45,10 @@ public static long time(Executor executor, int concurrency, done.await(); // Wait for all workers to finish return System.nanoTime() - startNanos; } + + public static void main(String[] args) throws InterruptedException { + Executor executor = Executors.newFixedThreadPool(5); + long time = time(executor, 3, () -> System.out.println(new Date())); + System.out.println(time); + } } diff --git a/src/effectivejava/chapter11/item81/Intern.java b/src/main/java/effectivejava/chapter11/item81/Intern.java similarity index 94% rename from src/effectivejava/chapter11/item81/Intern.java rename to src/main/java/effectivejava/chapter11/item81/Intern.java index 0e422c94..20d1f6b4 100644 --- a/src/effectivejava/chapter11/item81/Intern.java +++ b/src/main/java/effectivejava/chapter11/item81/Intern.java @@ -17,8 +17,9 @@ public static String intern(String s) { String result = map.get(s); if (result == null) { result = map.putIfAbsent(s, s); - if (result == null) + if (result == null) { result = s; + } } return result; } diff --git a/src/effectivejava/chapter11/item83/FieldType.java b/src/main/java/effectivejava/chapter11/item83/FieldType.java similarity index 100% rename from src/effectivejava/chapter11/item83/FieldType.java rename to src/main/java/effectivejava/chapter11/item83/FieldType.java diff --git a/src/effectivejava/chapter11/item83/Initialization.java b/src/main/java/effectivejava/chapter11/item83/Initialization.java similarity index 86% rename from src/effectivejava/chapter11/item83/Initialization.java rename to src/main/java/effectivejava/chapter11/item83/Initialization.java index 3a60ad1d..5b9e9269 100644 --- a/src/effectivejava/chapter11/item83/Initialization.java +++ b/src/main/java/effectivejava/chapter11/item83/Initialization.java @@ -8,9 +8,11 @@ public class Initialization { // Lazy initialization of instance field - synchronized accessor - Page 333 private FieldType field2; + private synchronized FieldType getField2() { - if (field2 == null) + if (field2 == null) { field2 = computeFieldValue(); + } return field2; } @@ -19,8 +21,9 @@ private static class FieldHolder { static final FieldType field = computeFieldValue(); } - private static FieldType getField() { return FieldHolder.field; } - + private static FieldType getField() { + return FieldHolder.field; + } // Double-check idiom for lazy initialization of instance fields - Page 334 private volatile FieldType field4; @@ -28,9 +31,11 @@ private static class FieldHolder { private FieldType getField4() { FieldType result = field4; if (result == null) { // First check (no locking) - synchronized(this) { + synchronized (this) { if (field4 == null) // Second check (with locking) + { field4 = result = computeFieldValue(); + } } } return result; @@ -41,8 +46,9 @@ private FieldType getField4() { private FieldType getField5() { FieldType result = field5; - if (result == null) + if (result == null) { field5 = result = computeFieldValue(); + } return result; } diff --git a/src/effectivejava/chapter11/item84/SlowCountDownLatch.java b/src/main/java/effectivejava/chapter11/item84/SlowCountDownLatch.java similarity index 75% rename from src/effectivejava/chapter11/item84/SlowCountDownLatch.java rename to src/main/java/effectivejava/chapter11/item84/SlowCountDownLatch.java index d0f1e892..b5f6a8e5 100644 --- a/src/effectivejava/chapter11/item84/SlowCountDownLatch.java +++ b/src/main/java/effectivejava/chapter11/item84/SlowCountDownLatch.java @@ -5,21 +5,25 @@ public class SlowCountDownLatch { private int count; public SlowCountDownLatch(int count) { - if (count < 0) + if (count < 0) { throw new IllegalArgumentException(count + " < 0"); + } this.count = count; } public void await() { while (true) { - synchronized(this) { - if (count == 0) + synchronized (this) { + if (count == 0) { return; + } } } } + public synchronized void countDown() { - if (count != 0) + if (count != 0) { count--; + } } } diff --git a/src/effectivejava/chapter12/Util.java b/src/main/java/effectivejava/chapter12/Util.java similarity index 79% rename from src/effectivejava/chapter12/Util.java rename to src/main/java/effectivejava/chapter12/Util.java index 0cfb2c91..aaf9bf41 100644 --- a/src/effectivejava/chapter12/Util.java +++ b/src/main/java/effectivejava/chapter12/Util.java @@ -1,6 +1,10 @@ package effectivejava.chapter12; -import java.io.*; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; public class Util { public static byte[] serialize(Object o) { diff --git a/src/effectivejava/chapter12/item85/DeserializationBomb.java b/src/main/java/effectivejava/chapter12/item85/DeserializationBomb.java similarity index 88% rename from src/effectivejava/chapter12/item85/DeserializationBomb.java rename to src/main/java/effectivejava/chapter12/item85/DeserializationBomb.java index 7a5de631..05353cc5 100644 --- a/src/effectivejava/chapter12/item85/DeserializationBomb.java +++ b/src/main/java/effectivejava/chapter12/item85/DeserializationBomb.java @@ -1,9 +1,11 @@ package effectivejava.chapter12.item85; -import static effectivejava.chapter12.Util.*; import java.util.HashSet; import java.util.Set; +import static effectivejava.chapter12.Util.deserialize; +import static effectivejava.chapter12.Util.serialize; + // Deserialization bomb - deserializing this stream takes forever - Page 340 public class DeserializationBomb { public static void main(String[] args) throws Exception { diff --git a/src/effectivejava/chapter12/item87/StringList.java b/src/main/java/effectivejava/chapter12/item87/StringList.java similarity index 75% rename from src/effectivejava/chapter12/item87/StringList.java rename to src/main/java/effectivejava/chapter12/item87/StringList.java index b50989c2..9b31f325 100644 --- a/src/effectivejava/chapter12/item87/StringList.java +++ b/src/main/java/effectivejava/chapter12/item87/StringList.java @@ -1,20 +1,25 @@ package effectivejava.chapter12.item87; -import java.io.*; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; // StringList with a reasonable custom serialized form - Page 349 public final class StringList implements Serializable { - private transient int size = 0; + private transient int size = 0; private transient Entry head = null; // No longer Serializable! private static class Entry { String data; - Entry next; - Entry previous; + Entry next; + Entry previous; } // Appends the specified string to the list - public final void add(String s) { } + public final void add(String s) { + } /** * Serialize this {@code StringList} instance. @@ -30,8 +35,9 @@ private void writeObject(ObjectOutputStream s) s.writeInt(size); // Write out all elements in the proper order. - for (Entry e = head; e != null; e = e.next) + for (Entry e = head; e != null; e = e.next) { s.writeObject(e.data); + } } private void readObject(ObjectInputStream s) @@ -40,8 +46,9 @@ private void readObject(ObjectInputStream s) int numElements = s.readInt(); // Read in all elements and insert them in list - for (int i = 0; i < numElements; i++) + for (int i = 0; i < numElements; i++) { add((String) s.readObject()); + } } // Remainder omitted diff --git a/src/effectivejava/chapter12/item89/enumsingleton/Elvis.java b/src/main/java/effectivejava/chapter12/item89/enumsingleton/Elvis.java similarity index 79% rename from src/effectivejava/chapter12/item89/enumsingleton/Elvis.java rename to src/main/java/effectivejava/chapter12/item89/enumsingleton/Elvis.java index 2f1a24be..84e9ef81 100644 --- a/src/effectivejava/chapter12/item89/enumsingleton/Elvis.java +++ b/src/main/java/effectivejava/chapter12/item89/enumsingleton/Elvis.java @@ -1,12 +1,13 @@ package effectivejava.chapter12.item89.enumsingleton; -import java.util.*; +import java.util.Arrays; // Enum singleton - the preferred approach - Page 311 public enum Elvis { INSTANCE; private String[] favoriteSongs = - { "Hound Dog", "Heartbreak Hotel" }; + {"Hound Dog", "Heartbreak Hotel"}; + public void printFavorites() { System.out.println(Arrays.toString(favoriteSongs)); } diff --git a/src/effectivejava/chapter12/item90/Period.java b/src/main/java/effectivejava/chapter12/item90/Period.java similarity index 67% rename from src/effectivejava/chapter12/item90/Period.java rename to src/main/java/effectivejava/chapter12/item90/Period.java index 71aaf712..6d471322 100644 --- a/src/effectivejava/chapter12/item90/Period.java +++ b/src/main/java/effectivejava/chapter12/item90/Period.java @@ -2,8 +2,10 @@ // Period class with serialization proxy - Pages 363-364 -import java.util.*; -import java.io.*; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.io.Serializable; +import java.util.Date; // Immutable class that uses defensive copying public final class Period implements Serializable { @@ -11,25 +13,32 @@ public final class Period implements Serializable { private final Date end; /** - * @param start the beginning of the period - * @param end the end of the period; must not precede start + * @param start the beginning of the period + * @param end the end of the period; must not precede start * @throws IllegalArgumentException if start is after end - * @throws NullPointerException if start or end is null + * @throws NullPointerException if start or end is null */ public Period(Date start, Date end) { this.start = new Date(start.getTime()); - this.end = new Date(end.getTime()); - if (this.start.compareTo(this.end) > 0) + this.end = new Date(end.getTime()); + if (this.start.compareTo(this.end) > 0) { throw new IllegalArgumentException( start + " after " + end); + } } - public Date start () { return new Date(start.getTime()); } - - public Date end () { return new Date(end.getTime()); } + public Date start() { + return new Date(start.getTime()); + } - public String toString() { return start + " - " + end; } + public Date end() { + return new Date(end.getTime()); + } + @Override + public String toString() { + return start + " - " + end; + } // Serialization proxy for Period class private static class SerializationProxy implements Serializable { diff --git a/src/effectivejava/chapter2/item2/builder/NutritionFacts.java b/src/main/java/effectivejava/chapter2/item2/builder/NutritionFacts.java similarity index 53% rename from src/effectivejava/chapter2/item2/builder/NutritionFacts.java rename to src/main/java/effectivejava/chapter2/item2/builder/NutritionFacts.java index 0c630099..ebd90715 100644 --- a/src/effectivejava/chapter2/item2/builder/NutritionFacts.java +++ b/src/main/java/effectivejava/chapter2/item2/builder/NutritionFacts.java @@ -15,24 +15,35 @@ public static class Builder { private final int servings; // Optional parameters - initialized to default values - private int calories = 0; - private int fat = 0; - private int sodium = 0; - private int carbohydrate = 0; + private int calories = 0; + private int fat = 0; + private int sodium = 0; + private int carbohydrate = 0; public Builder(int servingSize, int servings) { this.servingSize = servingSize; - this.servings = servings; + this.servings = servings; } - public Builder calories(int val) - { calories = val; return this; } - public Builder fat(int val) - { fat = val; return this; } - public Builder sodium(int val) - { sodium = val; return this; } - public Builder carbohydrate(int val) - { carbohydrate = val; return this; } + public Builder calories(int val) { + calories = val; + return this; + } + + public Builder fat(int val) { + fat = val; + return this; + } + + public Builder sodium(int val) { + sodium = val; + return this; + } + + public Builder carbohydrate(int val) { + carbohydrate = val; + return this; + } public NutritionFacts build() { return new NutritionFacts(this); @@ -40,16 +51,16 @@ public NutritionFacts build() { } private NutritionFacts(Builder builder) { - servingSize = builder.servingSize; - servings = builder.servings; - calories = builder.calories; - fat = builder.fat; - sodium = builder.sodium; + servingSize = builder.servingSize; + servings = builder.servings; + calories = builder.calories; + fat = builder.fat; + sodium = builder.sodium; carbohydrate = builder.carbohydrate; } public static void main(String[] args) { - NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8) + NutritionFacts cocaCola = new Builder(240, 8) .calories(100).sodium(35).carbohydrate(27).build(); } } \ No newline at end of file diff --git a/src/main/java/effectivejava/chapter2/item2/builder/NutritionFactsTest.java b/src/main/java/effectivejava/chapter2/item2/builder/NutritionFactsTest.java new file mode 100644 index 00000000..c33e6253 --- /dev/null +++ b/src/main/java/effectivejava/chapter2/item2/builder/NutritionFactsTest.java @@ -0,0 +1,27 @@ +package effectivejava.chapter2.item2.builder; + +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * NutritionFactsTest + * + * @author huangfl + * @since 2018/8/7 + */ +public class NutritionFactsTest { + + private Logger logger = LoggerFactory.getLogger(getClass()); + + @Test + public void test01() { + NutritionFacts.Builder builder = new NutritionFacts.Builder(1, 2); + builder.calories(3); + builder.carbohydrate(4); + builder.fat(5); + builder.sodium(6); + NutritionFacts nutritionFacts = builder.build(); + } + +} diff --git a/src/effectivejava/chapter2/item2/hierarchicalbuilder/Calzone.java b/src/main/java/effectivejava/chapter2/item2/hierarchicalbuilder/Calzone.java similarity index 100% rename from src/effectivejava/chapter2/item2/hierarchicalbuilder/Calzone.java rename to src/main/java/effectivejava/chapter2/item2/hierarchicalbuilder/Calzone.java diff --git a/src/effectivejava/chapter2/item2/hierarchicalbuilder/NyPizza.java b/src/main/java/effectivejava/chapter2/item2/hierarchicalbuilder/NyPizza.java similarity index 100% rename from src/effectivejava/chapter2/item2/hierarchicalbuilder/NyPizza.java rename to src/main/java/effectivejava/chapter2/item2/hierarchicalbuilder/NyPizza.java diff --git a/src/effectivejava/chapter2/item2/hierarchicalbuilder/Pizza.java b/src/main/java/effectivejava/chapter2/item2/hierarchicalbuilder/Pizza.java similarity index 99% rename from src/effectivejava/chapter2/item2/hierarchicalbuilder/Pizza.java rename to src/main/java/effectivejava/chapter2/item2/hierarchicalbuilder/Pizza.java index 77925cda..25a280a0 100644 --- a/src/effectivejava/chapter2/item2/hierarchicalbuilder/Pizza.java +++ b/src/main/java/effectivejava/chapter2/item2/hierarchicalbuilder/Pizza.java @@ -21,7 +21,7 @@ public T addTopping(Topping topping) { // Subclasses must override this method to return "this" protected abstract T self(); } - + Pizza(Builder builder) { toppings = builder.toppings.clone(); // See Item 50 } diff --git a/src/effectivejava/chapter2/item2/hierarchicalbuilder/PizzaTest.java b/src/main/java/effectivejava/chapter2/item2/hierarchicalbuilder/PizzaTest.java similarity index 100% rename from src/effectivejava/chapter2/item2/hierarchicalbuilder/PizzaTest.java rename to src/main/java/effectivejava/chapter2/item2/hierarchicalbuilder/PizzaTest.java diff --git a/src/effectivejava/chapter2/item2/javabeans/NutritionFacts.java b/src/main/java/effectivejava/chapter2/item2/javabeans/NutritionFacts.java similarity index 100% rename from src/effectivejava/chapter2/item2/javabeans/NutritionFacts.java rename to src/main/java/effectivejava/chapter2/item2/javabeans/NutritionFacts.java diff --git a/src/effectivejava/chapter2/item2/telescopingconstructor/NutritionFacts.java b/src/main/java/effectivejava/chapter2/item2/telescopingconstructor/NutritionFacts.java similarity index 100% rename from src/effectivejava/chapter2/item2/telescopingconstructor/NutritionFacts.java rename to src/main/java/effectivejava/chapter2/item2/telescopingconstructor/NutritionFacts.java diff --git a/src/effectivejava/chapter2/item3/enumtype/Elvis.java b/src/main/java/effectivejava/chapter2/item3/enumtype/Elvis.java similarity index 100% rename from src/effectivejava/chapter2/item3/enumtype/Elvis.java rename to src/main/java/effectivejava/chapter2/item3/enumtype/Elvis.java diff --git a/src/effectivejava/chapter2/item3/field/Elvis.java b/src/main/java/effectivejava/chapter2/item3/field/Elvis.java similarity index 100% rename from src/effectivejava/chapter2/item3/field/Elvis.java rename to src/main/java/effectivejava/chapter2/item3/field/Elvis.java diff --git a/src/effectivejava/chapter2/item3/staticfactory/Elvis.java b/src/main/java/effectivejava/chapter2/item3/staticfactory/Elvis.java similarity index 100% rename from src/effectivejava/chapter2/item3/staticfactory/Elvis.java rename to src/main/java/effectivejava/chapter2/item3/staticfactory/Elvis.java diff --git a/src/effectivejava/chapter2/item4/UtilityClass.java b/src/main/java/effectivejava/chapter2/item4/UtilityClass.java similarity index 71% rename from src/effectivejava/chapter2/item4/UtilityClass.java rename to src/main/java/effectivejava/chapter2/item4/UtilityClass.java index 2fb40990..87068765 100644 --- a/src/effectivejava/chapter2/item4/UtilityClass.java +++ b/src/main/java/effectivejava/chapter2/item4/UtilityClass.java @@ -8,4 +8,8 @@ private UtilityClass() { } // Remainder omitted + + public static void main(String[] args) { + UtilityClass utilityClass = new UtilityClass(); + } } diff --git a/src/effectivejava/chapter2/item6/RomanNumerals.java b/src/main/java/effectivejava/chapter2/item6/RomanNumerals.java similarity index 92% rename from src/effectivejava/chapter2/item6/RomanNumerals.java rename to src/main/java/effectivejava/chapter2/item6/RomanNumerals.java index bf451409..c41c1859 100644 --- a/src/effectivejava/chapter2/item6/RomanNumerals.java +++ b/src/main/java/effectivejava/chapter2/item6/RomanNumerals.java @@ -1,4 +1,5 @@ package effectivejava.chapter2.item6; + import java.util.regex.Pattern; // Reusing expensive object for improved performance (Pages 22 and 23) @@ -29,12 +30,13 @@ public static void main(String[] args) { b ^= isRomanNumeralSlow("MCMLXXVI"); // Change Slow to Fast to see performance difference } long end = System.nanoTime(); - System.out.println(((end - start) / (1_000. * numReps)) + " μs."); + System.out.println(((end - start) / (1000. * numReps)) + " μs."); } // Prevents VM from optimizing away everything. - if (!b) + if (!b) { System.out.println(); + } } } diff --git a/src/main/java/effectivejava/chapter2/item6/Sum.java b/src/main/java/effectivejava/chapter2/item6/Sum.java new file mode 100644 index 00000000..1d4ccac4 --- /dev/null +++ b/src/main/java/effectivejava/chapter2/item6/Sum.java @@ -0,0 +1,48 @@ +package effectivejava.chapter2.item6; + +// Hideously slow program! Can you spot the object creation? (Page 24) +public class Sum { + private static long sumLong() { + Long sum = 0L; + for (long i = 0; i <= Integer.MAX_VALUE; i++) { + sum += i; + } + return sum; + } + + private static long sumlong() { + long sum = 0L; + for (long i = 0; i <= Integer.MAX_VALUE; i++) { + sum += i; + } + return sum; + } + + public static void main(String[] args) { + + // int numSets = Integer.parseInt(args[0]); + int numSets = 5; + long x = 0; + for (int i = 0; i < numSets; i++) { + long start = System.nanoTime(); + x += sumLong(); + long end = System.nanoTime(); + System.out.println((end - start) / 1000000. + " ms."); + } + + // Prevents VM from optimizing away everything. + if (x == 42) { + System.out.println(); + } + + System.out.println("======================"); + + x = 0; + for (int i = 0; i < numSets; i++) { + long start = System.nanoTime(); + x += sumlong(); + long end = System.nanoTime(); + System.out.println((end - start) / 1000000. + " ms."); + } + } +} \ No newline at end of file diff --git a/src/effectivejava/chapter2/item7/EmptyStackException.java b/src/main/java/effectivejava/chapter2/item7/EmptyStackException.java similarity index 100% rename from src/effectivejava/chapter2/item7/EmptyStackException.java rename to src/main/java/effectivejava/chapter2/item7/EmptyStackException.java diff --git a/src/effectivejava/chapter2/item7/Stack.java b/src/main/java/effectivejava/chapter2/item7/Stack.java similarity index 86% rename from src/effectivejava/chapter2/item7/Stack.java rename to src/main/java/effectivejava/chapter2/item7/Stack.java index d27d83d6..6dfba0c6 100644 --- a/src/effectivejava/chapter2/item7/Stack.java +++ b/src/main/java/effectivejava/chapter2/item7/Stack.java @@ -1,5 +1,6 @@ package effectivejava.chapter2.item7; -import java.util.*; + +import java.util.Arrays; // Can you spot the "memory leak"? (Pages 26-27) public class Stack { @@ -17,8 +18,9 @@ public void push(Object e) { } public Object pop() { - if (size == 0) + if (size == 0) { throw new EmptyStackException(); + } return elements[--size]; } @@ -27,8 +29,9 @@ public Object pop() { * doubling the capacity each time the array needs to grow. */ private void ensureCapacity() { - if (elements.length == size) + if (elements.length == size) { elements = Arrays.copyOf(elements, 2 * size + 1); + } } // // Corrected version of pop method (Page 27) @@ -42,10 +45,12 @@ private void ensureCapacity() { public static void main(String[] args) { Stack stack = new Stack(); - for (String arg : args) + for (String arg : args) { stack.push(arg); + } - while (true) + while (true) { System.err.println(stack.pop()); + } } } diff --git a/src/main/java/effectivejava/chapter2/item8/Adult.java b/src/main/java/effectivejava/chapter2/item8/Adult.java new file mode 100644 index 00000000..cde82a02 --- /dev/null +++ b/src/main/java/effectivejava/chapter2/item8/Adult.java @@ -0,0 +1,10 @@ +//package effectivejava.chapter2.item8; +// +//// Well-behaved client of resource with cleaner safety-net (Page 33) +//public class Adult { +// public static void main(String[] args) { +// try (Room myRoom = new Room(7)) { +// System.out.println("Goodbye"); +// } +// } +//} diff --git a/src/main/java/effectivejava/chapter2/item8/Room.java b/src/main/java/effectivejava/chapter2/item8/Room.java new file mode 100644 index 00000000..199a7550 --- /dev/null +++ b/src/main/java/effectivejava/chapter2/item8/Room.java @@ -0,0 +1,38 @@ +//package effectivejava.chapter2.item8; +// +//import java.lang.ref.Cleaner; +// +//// An autocloseable class using a cleaner as a safety net (Page 32) +//public class Room implements AutoCloseable { +// private static final Cleaner cleaner = Cleaner.create(); +// +// // Resource that requires cleaning. Must not refer to Room! +// private static class State implements Runnable { +// int numJunkPiles; // Number of junk piles in this room +// +// State(int numJunkPiles) { +// this.numJunkPiles = numJunkPiles; +// } +// +// // Invoked by close method or cleaner +// @Override public void run() { +// System.out.println("Cleaning room"); +// numJunkPiles = 0; +// } +// } +// +// // The state of this room, shared with our cleanable +// private final State state; +// +// // Our cleanable. Cleans the room when it’s eligible for gc +// private final Cleaner.Cleanable cleanable; +// +// public Room(int numJunkPiles) { +// state = new State(numJunkPiles); +// cleanable = cleaner.register(this, state); +// } +// +// @Override public void close() { +// cleanable.clean(); +// } +//} diff --git a/src/main/java/effectivejava/chapter2/item8/Teenager.java b/src/main/java/effectivejava/chapter2/item8/Teenager.java new file mode 100644 index 00000000..86a9dfbf --- /dev/null +++ b/src/main/java/effectivejava/chapter2/item8/Teenager.java @@ -0,0 +1,14 @@ +//package effectivejava.chapter2.item8; +// +//import java.util.concurrent.TimeUnit; +// +//// Ill-behaved client of resource with cleaner safety-net (Page 33) +//public class Teenager { +// public static void main(String[] args) { +// new Room(99); +// System.out.println("Peace out"); +// +// // Uncomment next line and retest behavior, but note that you MUST NOT depend on this behavior! +//// System.gc(); +// } +//} diff --git a/src/effectivejava/chapter2/item9/tryfinally/Copy.java b/src/main/java/effectivejava/chapter2/item9/tryfinally/Copy.java similarity index 62% rename from src/effectivejava/chapter2/item9/tryfinally/Copy.java rename to src/main/java/effectivejava/chapter2/item9/tryfinally/Copy.java index 19b2e469..afbaf26d 100644 --- a/src/effectivejava/chapter2/item9/tryfinally/Copy.java +++ b/src/main/java/effectivejava/chapter2/item9/tryfinally/Copy.java @@ -1,6 +1,10 @@ package effectivejava.chapter2.item9.tryfinally; -import java.io.*; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; public class Copy { private static final int BUFFER_SIZE = 8 * 1024; @@ -13,19 +17,25 @@ static void copy(String src, String dst) throws IOException { try { byte[] buf = new byte[BUFFER_SIZE]; int n; - while ((n = in.read(buf)) >= 0) + while ((n = in.read(buf)) >= 0) { out.write(buf, 0, n); + } } finally { + System.out.println("out close"); out.close(); } } finally { in.close(); + System.out.println("in close"); } } public static void main(String[] args) throws IOException { - String src = args[0]; - String dst = args[1]; +// String src = args[0]; +// String dst = args[1]; + + String src = "src/main/src.txt"; + String dst = "src/main/dst.txt"; copy(src, dst); } } diff --git a/src/effectivejava/chapter2/item9/tryfinally/TopLine.java b/src/main/java/effectivejava/chapter2/item9/tryfinally/TopLine.java similarity index 100% rename from src/effectivejava/chapter2/item9/tryfinally/TopLine.java rename to src/main/java/effectivejava/chapter2/item9/tryfinally/TopLine.java diff --git a/src/effectivejava/chapter2/item9/trywithresources/Copy.java b/src/main/java/effectivejava/chapter2/item9/trywithresources/Copy.java similarity index 69% rename from src/effectivejava/chapter2/item9/trywithresources/Copy.java rename to src/main/java/effectivejava/chapter2/item9/trywithresources/Copy.java index 15a77dfb..5cfacbcb 100644 --- a/src/effectivejava/chapter2/item9/trywithresources/Copy.java +++ b/src/main/java/effectivejava/chapter2/item9/trywithresources/Copy.java @@ -1,18 +1,23 @@ package effectivejava.chapter2.item9.trywithresources; -import java.io.*; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; public class Copy { private static final int BUFFER_SIZE = 8 * 1024; // try-with-resources on multiple resources - short and sweet (Page 35) static void copy(String src, String dst) throws IOException { - try (InputStream in = new FileInputStream(src); + try (InputStream in = new FileInputStream(src); OutputStream out = new FileOutputStream(dst)) { byte[] buf = new byte[BUFFER_SIZE]; int n; - while ((n = in.read(buf)) >= 0) + while ((n = in.read(buf)) >= 0) { out.write(buf, 0, n); + } } } diff --git a/src/effectivejava/chapter2/item9/trywithresources/TopLine.java b/src/main/java/effectivejava/chapter2/item9/trywithresources/TopLine.java similarity index 100% rename from src/effectivejava/chapter2/item9/trywithresources/TopLine.java rename to src/main/java/effectivejava/chapter2/item9/trywithresources/TopLine.java diff --git a/src/effectivejava/chapter2/item9/trywithresources/TopLineWithDefault.java b/src/main/java/effectivejava/chapter2/item9/trywithresources/TopLineWithDefault.java similarity index 86% rename from src/effectivejava/chapter2/item9/trywithresources/TopLineWithDefault.java rename to src/main/java/effectivejava/chapter2/item9/trywithresources/TopLineWithDefault.java index f51334c0..c892eaee 100644 --- a/src/effectivejava/chapter2/item9/trywithresources/TopLineWithDefault.java +++ b/src/main/java/effectivejava/chapter2/item9/trywithresources/TopLineWithDefault.java @@ -1,6 +1,5 @@ package effectivejava.chapter2.item9.trywithresources; - import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; @@ -8,8 +7,7 @@ public class TopLineWithDefault { // try-with-resources with a catch clause (Page 36) static String firstLineOfFile(String path, String defaultVal) { - try (BufferedReader br = new BufferedReader( - new FileReader(path))) { + try (BufferedReader br = new BufferedReader(new FileReader(path))) { return br.readLine(); } catch (IOException e) { return defaultVal; diff --git a/src/effectivejava/chapter3/item10/CaseInsensitiveString.java b/src/main/java/effectivejava/chapter3/item10/CaseInsensitiveString.java similarity index 84% rename from src/effectivejava/chapter3/item10/CaseInsensitiveString.java rename to src/main/java/effectivejava/chapter3/item10/CaseInsensitiveString.java index dcb0c228..0274a673 100644 --- a/src/effectivejava/chapter3/item10/CaseInsensitiveString.java +++ b/src/main/java/effectivejava/chapter3/item10/CaseInsensitiveString.java @@ -13,12 +13,16 @@ public CaseInsensitiveString(String s) { } // Broken - violates symmetry! - @Override public boolean equals(Object o) { - if (o instanceof CaseInsensitiveString) + @Override + public boolean equals(Object o) { + if (o instanceof CaseInsensitiveString) { return s.equalsIgnoreCase( ((CaseInsensitiveString) o).s); - if (o instanceof String) // One-way interoperability! + } + // One-way interoperability! + if (o instanceof String) { return s.equalsIgnoreCase((String) o); + } return false; } diff --git a/src/effectivejava/chapter3/item10/Color.java b/src/main/java/effectivejava/chapter3/item10/Color.java similarity index 100% rename from src/effectivejava/chapter3/item10/Color.java rename to src/main/java/effectivejava/chapter3/item10/Color.java diff --git a/src/effectivejava/chapter3/item10/PhoneNumber.java b/src/main/java/effectivejava/chapter3/item10/PhoneNumber.java similarity index 53% rename from src/effectivejava/chapter3/item10/PhoneNumber.java rename to src/main/java/effectivejava/chapter3/item10/PhoneNumber.java index 244d78f6..8d817d13 100644 --- a/src/effectivejava/chapter3/item10/PhoneNumber.java +++ b/src/main/java/effectivejava/chapter3/item10/PhoneNumber.java @@ -1,30 +1,42 @@ package effectivejava.chapter3.item10; +import java.util.HashMap; + // Class with a typical equals method (Page 48) public final class PhoneNumber { private final short areaCode, prefix, lineNum; public PhoneNumber(int areaCode, int prefix, int lineNum) { this.areaCode = rangeCheck(areaCode, 999, "area code"); - this.prefix = rangeCheck(prefix, 999, "prefix"); - this.lineNum = rangeCheck(lineNum, 9999, "line num"); + this.prefix = rangeCheck(prefix, 999, "prefix"); + this.lineNum = rangeCheck(lineNum, 9999, "line num"); } private static short rangeCheck(int val, int max, String arg) { - if (val < 0 || val > max) + if (val < 0 || val > max) { throw new IllegalArgumentException(arg + ": " + val); + } return (short) val; } - @Override public boolean equals(Object o) { - if (o == this) + @Override + public boolean equals(Object o) { + if (o == this) { return true; - if (!(o instanceof PhoneNumber)) + } + if (!(o instanceof PhoneNumber)) { return false; - PhoneNumber pn = (PhoneNumber)o; + } + PhoneNumber pn = (PhoneNumber) o; return pn.lineNum == lineNum && pn.prefix == prefix && pn.areaCode == areaCode; } // Remainder omitted - note that hashCode is REQUIRED (Item 11)! + public static void main(String[] args) { + HashMap map = new HashMap<>(); + map.put(new PhoneNumber(1, 2, 3), "11111111111"); + System.out.println(map.get(new PhoneNumber(1, 2, 3))); + } + } diff --git a/src/effectivejava/chapter3/item10/Point.java b/src/main/java/effectivejava/chapter3/item10/Point.java similarity index 60% rename from src/effectivejava/chapter3/item10/Point.java rename to src/main/java/effectivejava/chapter3/item10/Point.java index d3acd2e9..bb42350d 100644 --- a/src/effectivejava/chapter3/item10/Point.java +++ b/src/main/java/effectivejava/chapter3/item10/Point.java @@ -10,23 +10,27 @@ public Point(int x, int y) { this.y = y; } - @Override public boolean equals(Object o) { - if (!(o instanceof Point)) - return false; - Point p = (Point)o; - return p.x == x && p.y == y; - } - -// // Broken - violates Liskov substitution principle (page 43) // @Override public boolean equals(Object o) { -// if (o == null || o.getClass() != getClass()) +// if (!(o instanceof Point)) { // return false; -// Point p = (Point) o; +// } +// Point p = (Point)o; // return p.x == x && p.y == y; // } + // Broken - violates Liskov substitution principle (page 43) + @Override + public boolean equals(Object o) { + if (o == null || o.getClass() != getClass()) { + return false; + } + Point p = (Point) o; + return p.x == x && p.y == y; + } + // See Item 11 - @Override public int hashCode() { + @Override + public int hashCode() { return 31 * x + y; } } diff --git a/src/effectivejava/chapter3/item10/composition/ColorPoint.java b/src/main/java/effectivejava/chapter3/item10/composition/ColorPoint.java similarity index 100% rename from src/effectivejava/chapter3/item10/composition/ColorPoint.java rename to src/main/java/effectivejava/chapter3/item10/composition/ColorPoint.java diff --git a/src/effectivejava/chapter3/item10/inheritance/ColorPoint.java b/src/main/java/effectivejava/chapter3/item10/inheritance/ColorPoint.java similarity index 100% rename from src/effectivejava/chapter3/item10/inheritance/ColorPoint.java rename to src/main/java/effectivejava/chapter3/item10/inheritance/ColorPoint.java diff --git a/src/effectivejava/chapter3/item10/inheritance/CounterPoint.java b/src/main/java/effectivejava/chapter3/item10/inheritance/CounterPoint.java similarity index 100% rename from src/effectivejava/chapter3/item10/inheritance/CounterPoint.java rename to src/main/java/effectivejava/chapter3/item10/inheritance/CounterPoint.java diff --git a/src/effectivejava/chapter3/item10/inheritance/CounterPointTest.java b/src/main/java/effectivejava/chapter3/item10/inheritance/CounterPointTest.java similarity index 76% rename from src/effectivejava/chapter3/item10/inheritance/CounterPointTest.java rename to src/main/java/effectivejava/chapter3/item10/inheritance/CounterPointTest.java index 7e72d262..15437ac5 100644 --- a/src/effectivejava/chapter3/item10/inheritance/CounterPointTest.java +++ b/src/main/java/effectivejava/chapter3/item10/inheritance/CounterPointTest.java @@ -1,22 +1,23 @@ package effectivejava.chapter3.item10.inheritance; + import effectivejava.chapter3.item10.Point; -import java.util.*; +import java.util.Set; // Test program that uses CounterPoint as Point public class CounterPointTest { // Initialize unitCircle to contain all Points on the unit circle (Page 43) private static final Set unitCircle = Set.of( - new Point( 1, 0), new Point( 0, 1), - new Point(-1, 0), new Point( 0, -1)); + new Point(1, 0), new Point(0, 1), + new Point(-1, 0), new Point(0, -1)); public static boolean onUnitCircle(Point p) { return unitCircle.contains(p); } public static void main(String[] args) { - Point p1 = new Point(1, 0); - Point p2 = new CounterPoint(1, 0); + Point p1 = new Point(1, 0); + Point p2 = new CounterPoint(1, 0); // Prints true System.out.println(onUnitCircle(p1)); diff --git a/src/effectivejava/chapter3/item11/PhoneNumber.java b/src/main/java/effectivejava/chapter3/item11/PhoneNumber.java similarity index 63% rename from src/effectivejava/chapter3/item11/PhoneNumber.java rename to src/main/java/effectivejava/chapter3/item11/PhoneNumber.java index 084f1e95..f7780f94 100644 --- a/src/effectivejava/chapter3/item11/PhoneNumber.java +++ b/src/main/java/effectivejava/chapter3/item11/PhoneNumber.java @@ -1,5 +1,7 @@ package effectivejava.chapter3.item11; -import java.util.*; + +import java.util.HashMap; +import java.util.Map; // Shows the need for overriding hashcode when you override equals (Pages 50-53 ) public final class PhoneNumber { @@ -7,8 +9,8 @@ public final class PhoneNumber { public PhoneNumber(int areaCode, int prefix, int lineNum) { this.areaCode = rangeCheck(areaCode, 999, "area code"); - this.prefix = rangeCheck(prefix, 999, "prefix"); - this.lineNum = rangeCheck(lineNum, 9999, "line num"); + this.prefix = rangeCheck(prefix, 999, "prefix"); + this.lineNum = rangeCheck(lineNum, 9999, "line num"); } private static short rangeCheck(int val, int max, String arg) { @@ -17,45 +19,46 @@ private static short rangeCheck(int val, int max, String arg) { return (short) val; } - @Override public boolean equals(Object o) { + @Override + public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof PhoneNumber)) return false; - PhoneNumber pn = (PhoneNumber)o; + PhoneNumber pn = (PhoneNumber) o; return pn.lineNum == lineNum && pn.prefix == prefix && pn.areaCode == areaCode; } - // Broken with no hashCode; works with any of the three below -// // Typical hashCode method (Page 52) -// @Override public int hashCode() { +// @Override +// public int hashCode() { // int result = Short.hashCode(areaCode); // result = 31 * result + Short.hashCode(prefix); // result = 31 * result + Short.hashCode(lineNum); // return result; -// } +// } // Typical hashCode method (Page 52) // // One-line hashCode method - mediocre performance (page 53) // @Override public int hashCode() { // return Objects.hash(lineNum, prefix, areaCode); // } -// // hashCode method with lazily initialized cached hash code (page 53) -// private int hashCode; // Automatically initialized to 0 -// -// @Override public int hashCode() { -// int result = hashCode; -// if (result == 0) { -// result = Short.hashCode(areaCode); -// result = 31 * result + Short.hashCode(prefix); -// result = 31 * result + Short.hashCode(lineNum); -// hashCode = result; -// } -// return result; -// } + // hashCode method with lazily initialized cached hash code (page 53) + private int hashCode; // Automatically initialized to 0 + + @Override + public int hashCode() { + int result = hashCode; + if (result == 0) { + result = Short.hashCode(areaCode); + result = 31 * result + Short.hashCode(prefix); + result = 31 * result + Short.hashCode(lineNum); + hashCode = result; + } + return result; + } public static void main(String[] args) { Map m = new HashMap<>(); diff --git a/src/effectivejava/chapter3/item12/PhoneNumber.java b/src/main/java/effectivejava/chapter3/item12/PhoneNumber.java similarity index 93% rename from src/effectivejava/chapter3/item12/PhoneNumber.java rename to src/main/java/effectivejava/chapter3/item12/PhoneNumber.java index ccc3206c..613dec89 100644 --- a/src/effectivejava/chapter3/item12/PhoneNumber.java +++ b/src/main/java/effectivejava/chapter3/item12/PhoneNumber.java @@ -45,10 +45,11 @@ private static short rangeCheck(int val, int max, String arg) { * For example, if the value of the line number is 123, the last * four characters of the string representation will be "0123". */ -// @Override public String toString() { -// return String.format("%03d-%03d-%04d", -// areaCode, prefix, lineNum); -// } + @Override + public String toString() { + return String.format("%03d-%03d-%04d", + areaCode, prefix, lineNum); + } public static void main(String[] args) { PhoneNumber jenny = new PhoneNumber(707, 867, 5309); diff --git a/src/effectivejava/chapter3/item13/EmptyStackException.java b/src/main/java/effectivejava/chapter3/item13/EmptyStackException.java similarity index 100% rename from src/effectivejava/chapter3/item13/EmptyStackException.java rename to src/main/java/effectivejava/chapter3/item13/EmptyStackException.java diff --git a/src/effectivejava/chapter3/item13/PhoneNumber.java b/src/main/java/effectivejava/chapter3/item13/PhoneNumber.java similarity index 100% rename from src/effectivejava/chapter3/item13/PhoneNumber.java rename to src/main/java/effectivejava/chapter3/item13/PhoneNumber.java diff --git a/src/effectivejava/chapter3/item13/Stack.java b/src/main/java/effectivejava/chapter3/item13/Stack.java similarity index 81% rename from src/effectivejava/chapter3/item13/Stack.java rename to src/main/java/effectivejava/chapter3/item13/Stack.java index 1c49e014..22350886 100644 --- a/src/effectivejava/chapter3/item13/Stack.java +++ b/src/main/java/effectivejava/chapter3/item13/Stack.java @@ -1,4 +1,5 @@ package effectivejava.chapter3.item13; + import java.util.Arrays; // A cloneable version of Stack (Pages 60-61) @@ -15,21 +16,23 @@ public void push(Object e) { ensureCapacity(); elements[size++] = e; } - + public Object pop() { - if (size == 0) + if (size == 0) { throw new EmptyStackException(); + } Object result = elements[--size]; elements[size] = null; // Eliminate obsolete reference return result; } public boolean isEmpty() { - return size ==0; + return size == 0; } // Clone method for class with references to mutable state - @Override public Stack clone() { + @Override + public Stack clone() { try { Stack result = (Stack) super.clone(); result.elements = elements.clone(); @@ -41,20 +44,27 @@ public boolean isEmpty() { // Ensure space for at least one more element. private void ensureCapacity() { - if (elements.length == size) + if (elements.length == size) { elements = Arrays.copyOf(elements, 2 * size + 1); + } } - + // To see that clone works, call with several command line arguments public static void main(String[] args) { + + args = new String[]{"1", "2", "3", "4"}; + Stack stack = new Stack(); - for (String arg : args) + for (String arg : args) { stack.push(arg); + } Stack copy = stack.clone(); - while (!stack.isEmpty()) + while (!stack.isEmpty()) { System.out.print(stack.pop() + " "); + } System.out.println(); - while (!copy.isEmpty()) + while (!copy.isEmpty()) { System.out.print(copy.pop() + " "); + } } } diff --git a/src/effectivejava/chapter3/item14/CaseInsensitiveString.java b/src/main/java/effectivejava/chapter3/item14/CaseInsensitiveString.java similarity index 77% rename from src/effectivejava/chapter3/item14/CaseInsensitiveString.java rename to src/main/java/effectivejava/chapter3/item14/CaseInsensitiveString.java index 9304ad19..2b0456eb 100644 --- a/src/effectivejava/chapter3/item14/CaseInsensitiveString.java +++ b/src/main/java/effectivejava/chapter3/item14/CaseInsensitiveString.java @@ -1,6 +1,8 @@ package effectivejava.chapter3.item14; -import java.util.*; +import java.util.Objects; +import java.util.Set; +import java.util.TreeSet; // Single-field Comparable with object reference field (Page 69) public final class CaseInsensitiveString @@ -12,28 +14,33 @@ public CaseInsensitiveString(String s) { } // Fixed equals method (Page 40) - @Override public boolean equals(Object o) { + @Override + public boolean equals(Object o) { return o instanceof CaseInsensitiveString && ((CaseInsensitiveString) o).s.equalsIgnoreCase(s); } - @Override public int hashCode() { + @Override + public int hashCode() { return s.hashCode(); } - @Override public String toString() { + @Override + public String toString() { return s; } // Using an existing comparator to make a class comparable + @Override public int compareTo(CaseInsensitiveString cis) { return String.CASE_INSENSITIVE_ORDER.compare(s, cis.s); } public static void main(String[] args) { Set s = new TreeSet<>(); - for (String arg : args) + for (String arg : args) { s.add(new CaseInsensitiveString(arg)); + } System.out.println(s); } } \ No newline at end of file diff --git a/src/effectivejava/chapter3/item14/PhoneNumber.java b/src/main/java/effectivejava/chapter3/item14/PhoneNumber.java similarity index 61% rename from src/effectivejava/chapter3/item14/PhoneNumber.java rename to src/main/java/effectivejava/chapter3/item14/PhoneNumber.java index 22d5ee95..db31b852 100644 --- a/src/effectivejava/chapter3/item14/PhoneNumber.java +++ b/src/main/java/effectivejava/chapter3/item14/PhoneNumber.java @@ -1,7 +1,9 @@ package effectivejava.chapter3.item14; -import java.util.*; + +import java.util.NavigableSet; +import java.util.Random; +import java.util.TreeSet; import java.util.concurrent.ThreadLocalRandom; -import static java.util.Comparator.*; // Making PhoneNumber comparable (Pages 69-70) public final class PhoneNumber implements Cloneable, Comparable { @@ -9,27 +11,32 @@ public final class PhoneNumber implements Cloneable, Comparable { public PhoneNumber(int areaCode, int prefix, int lineNum) { this.areaCode = rangeCheck(areaCode, 999, "area code"); - this.prefix = rangeCheck(prefix, 999, "prefix"); - this.lineNum = rangeCheck(lineNum, 9999, "line num"); + this.prefix = rangeCheck(prefix, 999, "prefix"); + this.lineNum = rangeCheck(lineNum, 9999, "line num"); } private static short rangeCheck(int val, int max, String arg) { - if (val < 0 || val > max) + if (val < 0 || val > max) { throw new IllegalArgumentException(arg + ": " + val); + } return (short) val; } - @Override public boolean equals(Object o) { - if (o == this) + @Override + public boolean equals(Object o) { + if (o == this) { return true; - if (!(o instanceof effectivejava.chapter3.item11.PhoneNumber)) + } + if (!(o instanceof effectivejava.chapter3.item11.PhoneNumber)) { return false; - PhoneNumber pn = (PhoneNumber)o; + } + PhoneNumber pn = (PhoneNumber) o; return pn.lineNum == lineNum && pn.prefix == prefix && pn.areaCode == areaCode; } - @Override public int hashCode() { + @Override + public int hashCode() { int result = Short.hashCode(areaCode); result = 31 * result + Short.hashCode(prefix); result = 31 * result + Short.hashCode(lineNum); @@ -42,49 +49,54 @@ private static short rangeCheck(int val, int max, String arg) { * "XXX-YYY-ZZZZ", where XXX is the area code, YYY is the * prefix, and ZZZZ is the line number. Each of the capital * letters represents a single decimal digit. - * + *

* If any of the three parts of this phone number is too small * to fill up its field, the field is padded with leading zeros. * For example, if the value of the line number is 123, the last * four characters of the string representation will be "0123". */ - @Override public String toString() { + @Override + public String toString() { return String.format("%03d-%03d-%04d", areaCode, prefix, lineNum); } -// // Multiple-field Comparable with primitive fields (page 69) -// public int compareTo(PhoneNumber pn) { -// int result = Short.compare(areaCode, pn.areaCode); -// if (result == 0) { -// result = Short.compare(prefix, pn.prefix); -// if (result == 0) -// result = Short.compare(lineNum, pn.lineNum); -// } -// return result; -// } - - // Comparable with comparator construction methods (page 70) - private static final Comparator COMPARATOR = - comparingInt((PhoneNumber pn) -> pn.areaCode) - .thenComparingInt(pn -> pn.prefix) - .thenComparingInt(pn -> pn.lineNum); - + // Multiple-field Comparable with primitive fields (page 69) + @Override public int compareTo(PhoneNumber pn) { - return COMPARATOR.compare(this, pn); + int result = Short.compare(areaCode, pn.areaCode); + if (result == 0) { + result = Short.compare(prefix, pn.prefix); + if (result == 0) { + result = Short.compare(lineNum, pn.lineNum); + } + } + return result; } +// // Comparable with comparator construction methods (page 70) +// private static final Comparator COMPARATOR = +// comparingInt((PhoneNumber pn) -> pn.areaCode) +// .thenComparingInt(pn -> pn.prefix) +// .thenComparingInt(pn -> pn.lineNum); +// +// @Override +// public int compareTo(PhoneNumber pn) { +// return COMPARATOR.compare(this, pn); +// } + private static PhoneNumber randomPhoneNumber() { Random rnd = ThreadLocalRandom.current(); return new PhoneNumber((short) rnd.nextInt(1000), - (short) rnd.nextInt(1000), - (short) rnd.nextInt(10000)); + (short) rnd.nextInt(1000), + (short) rnd.nextInt(10000)); } public static void main(String[] args) { NavigableSet s = new TreeSet(); - for (int i = 0; i < 10; i++) + for (int i = 0; i < 10; i++) { s.add(randomPhoneNumber()); + } System.out.println(s); } } diff --git a/src/effectivejava/chapter3/item14/WordList.java b/src/main/java/effectivejava/chapter3/item14/WordList.java similarity index 100% rename from src/effectivejava/chapter3/item14/WordList.java rename to src/main/java/effectivejava/chapter3/item14/WordList.java diff --git a/src/effectivejava/chapter4/item16/Point.java b/src/main/java/effectivejava/chapter4/item16/Point.java similarity index 53% rename from src/effectivejava/chapter4/item16/Point.java rename to src/main/java/effectivejava/chapter4/item16/Point.java index 9ef9f681..1dd4be1f 100644 --- a/src/effectivejava/chapter4/item16/Point.java +++ b/src/main/java/effectivejava/chapter4/item16/Point.java @@ -10,9 +10,19 @@ public Point(double x, double y) { this.y = y; } - public double getX() { return x; } - public double getY() { return y; } + public double getX() { + return x; + } + + public double getY() { + return y; + } + + public void setX(double x) { + this.x = x; + } - public void setX(double x) { this.x = x; } - public void setY(double y) { this.y = y; } + public void setY(double y) { + this.y = y; + } } diff --git a/src/effectivejava/chapter4/item16/Time.java b/src/main/java/effectivejava/chapter4/item16/Time.java similarity index 74% rename from src/effectivejava/chapter4/item16/Time.java rename to src/main/java/effectivejava/chapter4/item16/Time.java index aabb8055..6393e2f0 100644 --- a/src/effectivejava/chapter4/item16/Time.java +++ b/src/main/java/effectivejava/chapter4/item16/Time.java @@ -2,17 +2,19 @@ // Public class with exposed immutable fields - questionable (Page 79) public final class Time { - private static final int HOURS_PER_DAY = 24; + private static final int HOURS_PER_DAY = 24; private static final int MINUTES_PER_HOUR = 60; public final int hour; public final int minute; public Time(int hour, int minute) { - if (hour < 0 || hour >= HOURS_PER_DAY) + if (hour < 0 || hour >= HOURS_PER_DAY) { throw new IllegalArgumentException("Hour: " + hour); - if (minute < 0 || minute >= MINUTES_PER_HOUR) + } + if (minute < 0 || minute >= MINUTES_PER_HOUR) { throw new IllegalArgumentException("Min: " + minute); + } this.hour = hour; this.minute = minute; } diff --git a/src/effectivejava/chapter4/item17/Complex.java b/src/main/java/effectivejava/chapter4/item17/Complex.java similarity index 75% rename from src/effectivejava/chapter4/item17/Complex.java rename to src/main/java/effectivejava/chapter4/item17/Complex.java index 49d33d81..47f5a272 100644 --- a/src/effectivejava/chapter4/item17/Complex.java +++ b/src/main/java/effectivejava/chapter4/item17/Complex.java @@ -6,16 +6,21 @@ public final class Complex { private final double im; public static final Complex ZERO = new Complex(0, 0); - public static final Complex ONE = new Complex(1, 0); - public static final Complex I = new Complex(0, 1); + public static final Complex ONE = new Complex(1, 0); + public static final Complex I = new Complex(0, 1); public Complex(double re, double im) { this.re = re; this.im = im; } - public double realPart() { return re; } - public double imaginaryPart() { return im; } + public double realPart() { + return re; + } + + public double imaginaryPart() { + return im; + } public Complex plus(Complex c) { return new Complex(re + c.re, im + c.im); @@ -41,22 +46,28 @@ public Complex dividedBy(Complex c) { (im * c.re - re * c.im) / tmp); } - @Override public boolean equals(Object o) { - if (o == this) + @Override + public boolean equals(Object o) { + if (o == this) { return true; - if (!(o instanceof Complex)) + } + if (!(o instanceof Complex)) { return false; + } Complex c = (Complex) o; // See page 47 to find out why we use compare instead of == return Double.compare(c.re, re) == 0 && Double.compare(c.im, im) == 0; } - @Override public int hashCode() { + + @Override + public int hashCode() { return 31 * Double.hashCode(re) + Double.hashCode(im); } - @Override public String toString() { + @Override + public String toString() { return "(" + re + " + " + im + "i)"; } } diff --git a/src/main/java/effectivejava/chapter4/item18/ForwardingSet.java b/src/main/java/effectivejava/chapter4/item18/ForwardingSet.java new file mode 100644 index 00000000..b8aced60 --- /dev/null +++ b/src/main/java/effectivejava/chapter4/item18/ForwardingSet.java @@ -0,0 +1,98 @@ +package effectivejava.chapter4.item18; + +import java.util.Collection; +import java.util.Iterator; +import java.util.Set; + +// Reusable forwarding class (Page 90) +public class ForwardingSet implements Set { + + /** + * 包装一个 Set 类型的实例。 + */ + private final Set s; + + public ForwardingSet(Set s) { + this.s = s; + } + + @Override + public void clear() { + s.clear(); + } + + @Override + public boolean contains(Object o) { + return s.contains(o); + } + + @Override + public boolean isEmpty() { + return s.isEmpty(); + } + + @Override + public int size() { + return s.size(); + } + + @Override + public Iterator iterator() { + return s.iterator(); + } + + @Override + public boolean add(E e) { + return s.add(e); + } + + @Override + public boolean remove(Object o) { + return s.remove(o); + } + + @Override + public boolean containsAll(Collection c) { + return s.containsAll(c); + } + + @Override + public boolean addAll(Collection c) { + return s.addAll(c); + } + + @Override + public boolean removeAll(Collection c) { + return s.removeAll(c); + } + + @Override + public boolean retainAll(Collection c) { + return s.retainAll(c); + } + + @Override + public Object[] toArray() { + return s.toArray(); + } + + @Override + public T[] toArray(T[] a) { + return s.toArray(a); + } + + @Override + public boolean equals(Object o) { + return s.equals(o); + } + + @Override + public int hashCode() { + return s.hashCode(); + } + + @Override + public String toString() { + return s.toString(); + } +} diff --git a/src/effectivejava/chapter4/item18/InstrumentedHashSet.java b/src/main/java/effectivejava/chapter4/item18/InstrumentedHashSet.java similarity index 80% rename from src/effectivejava/chapter4/item18/InstrumentedHashSet.java rename to src/main/java/effectivejava/chapter4/item18/InstrumentedHashSet.java index 7533c7f2..5f3e06c8 100644 --- a/src/effectivejava/chapter4/item18/InstrumentedHashSet.java +++ b/src/main/java/effectivejava/chapter4/item18/InstrumentedHashSet.java @@ -1,5 +1,8 @@ package effectivejava.chapter4.item18; -import java.util.*; + +import java.util.Collection; +import java.util.HashSet; +import java.util.List; // Broken - Inappropriate use of inheritance! (Page 87) public class InstrumentedHashSet extends HashSet { @@ -13,12 +16,14 @@ public InstrumentedHashSet(int initCap, float loadFactor) { super(initCap, loadFactor); } - @Override public boolean add(E e) { + @Override + public boolean add(E e) { addCount++; return super.add(e); } - @Override public boolean addAll(Collection c) { + @Override + public boolean addAll(Collection c) { addCount += c.size(); return super.addAll(c); } diff --git a/src/effectivejava/chapter4/item18/InstrumentedSet.java b/src/main/java/effectivejava/chapter4/item18/InstrumentedSet.java similarity index 75% rename from src/effectivejava/chapter4/item18/InstrumentedSet.java rename to src/main/java/effectivejava/chapter4/item18/InstrumentedSet.java index 920fd3f2..98f3ab94 100644 --- a/src/effectivejava/chapter4/item18/InstrumentedSet.java +++ b/src/main/java/effectivejava/chapter4/item18/InstrumentedSet.java @@ -1,5 +1,9 @@ package effectivejava.chapter4.item18; -import java.util.*; + +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; // Wrapper class - uses composition in place of inheritance (Page 90) public class InstrumentedSet extends ForwardingSet { @@ -9,14 +13,18 @@ public InstrumentedSet(Set s) { super(s); } - @Override public boolean add(E e) { + @Override + public boolean add(E e) { addCount++; return super.add(e); } - @Override public boolean addAll(Collection c) { + + @Override + public boolean addAll(Collection c) { addCount += c.size(); return super.addAll(c); } + public int getAddCount() { return addCount; } diff --git a/src/effectivejava/chapter4/item19/Sub.java b/src/main/java/effectivejava/chapter4/item19/Sub.java similarity index 92% rename from src/effectivejava/chapter4/item19/Sub.java rename to src/main/java/effectivejava/chapter4/item19/Sub.java index 90b9f007..f02222d2 100644 --- a/src/effectivejava/chapter4/item19/Sub.java +++ b/src/main/java/effectivejava/chapter4/item19/Sub.java @@ -12,7 +12,8 @@ public final class Sub extends Super { } // Overriding method invoked by superclass constructor - @Override public void overrideMe() { + @Override + public void overrideMe() { System.out.println(instant); } @@ -20,4 +21,5 @@ public static void main(String[] args) { Sub sub = new Sub(); sub.overrideMe(); } + } diff --git a/src/effectivejava/chapter4/item19/Super.java b/src/main/java/effectivejava/chapter4/item19/Super.java similarity index 85% rename from src/effectivejava/chapter4/item19/Super.java rename to src/main/java/effectivejava/chapter4/item19/Super.java index 0235641c..3940fab4 100644 --- a/src/effectivejava/chapter4/item19/Super.java +++ b/src/main/java/effectivejava/chapter4/item19/Super.java @@ -8,5 +8,6 @@ public Super() { } public void overrideMe() { + System.out.println("super overrideMe()"); } } diff --git a/src/effectivejava/chapter4/item20/AbstractMapEntry.java b/src/main/java/effectivejava/chapter4/item20/AbstractMapEntry.java similarity index 54% rename from src/effectivejava/chapter4/item20/AbstractMapEntry.java rename to src/main/java/effectivejava/chapter4/item20/AbstractMapEntry.java index 97f4cf44..f99ba637 100644 --- a/src/effectivejava/chapter4/item20/AbstractMapEntry.java +++ b/src/main/java/effectivejava/chapter4/item20/AbstractMapEntry.java @@ -1,32 +1,40 @@ package effectivejava.chapter4.item20; -import java.util.*; + +import java.util.Map; +import java.util.Objects; // Skeletal implementation class (Pages 102-3) -public abstract class AbstractMapEntry - implements Map.Entry { +public abstract class AbstractMapEntry + implements Map.Entry { // Entries in a modifiable map must override this method - @Override public V setValue(V value) { + @Override + public V setValue(V value) { throw new UnsupportedOperationException(); } - + // Implements the general contract of Map.Entry.equals - @Override public boolean equals(Object o) { - if (o == this) + @Override + public boolean equals(Object o) { + if (o == this) { return true; - if (!(o instanceof Map.Entry)) + } + if (!(o instanceof Map.Entry)) { return false; - Map.Entry e = (Map.Entry) o; - return Objects.equals(e.getKey(), getKey()) + } + Map.Entry e = (Map.Entry) o; + return Objects.equals(e.getKey(), getKey()) && Objects.equals(e.getValue(), getValue()); } // Implements the general contract of Map.Entry.hashCode - @Override public int hashCode() { + @Override + public int hashCode() { return Objects.hashCode(getKey()) ^ Objects.hashCode(getValue()); } - @Override public String toString() { + @Override + public String toString() { return getKey() + "=" + getValue(); } } diff --git a/src/effectivejava/chapter4/item20/IntArrays.java b/src/main/java/effectivejava/chapter4/item20/IntArrays.java similarity index 100% rename from src/effectivejava/chapter4/item20/IntArrays.java rename to src/main/java/effectivejava/chapter4/item20/IntArrays.java diff --git a/src/main/java/effectivejava/chapter4/item20/java8/Car.java b/src/main/java/effectivejava/chapter4/item20/java8/Car.java new file mode 100644 index 00000000..ad2ea19b --- /dev/null +++ b/src/main/java/effectivejava/chapter4/item20/java8/Car.java @@ -0,0 +1,18 @@ +package effectivejava.chapter4.item20.java8; + +/** + * Car + * + * @author huangfl + * @since 2018/8/13 + */ +class Car implements Vehicle, FourWheeler { + + @Override + public void print() { + Vehicle.super.print(); + FourWheeler.super.print(); + Vehicle.blowHorn(); + System.out.println("我是一辆汽车!"); + } +} \ No newline at end of file diff --git a/src/main/java/effectivejava/chapter4/item20/java8/FourWheeler.java b/src/main/java/effectivejava/chapter4/item20/java8/FourWheeler.java new file mode 100644 index 00000000..cf0b74d6 --- /dev/null +++ b/src/main/java/effectivejava/chapter4/item20/java8/FourWheeler.java @@ -0,0 +1,13 @@ +package effectivejava.chapter4.item20.java8; + +/** + * FourWheeler + * + * @author huangfl + * @since 2018/8/13 + */ +interface FourWheeler { + default void print() { + System.out.println("我是一辆四轮车!"); + } +} \ No newline at end of file diff --git a/src/main/java/effectivejava/chapter4/item20/java8/Java8Tester.java b/src/main/java/effectivejava/chapter4/item20/java8/Java8Tester.java new file mode 100644 index 00000000..23f20495 --- /dev/null +++ b/src/main/java/effectivejava/chapter4/item20/java8/Java8Tester.java @@ -0,0 +1,14 @@ +package effectivejava.chapter4.item20.java8; + +/** + * Java8Tester + * + * @author huangfl + * @since 2018/8/13 + */ +public class Java8Tester { + public static void main(String args[]) { + Vehicle vehicle = new Car(); + vehicle.print(); + } +} \ No newline at end of file diff --git a/src/main/java/effectivejava/chapter4/item20/java8/Vehicle.java b/src/main/java/effectivejava/chapter4/item20/java8/Vehicle.java new file mode 100644 index 00000000..744514d8 --- /dev/null +++ b/src/main/java/effectivejava/chapter4/item20/java8/Vehicle.java @@ -0,0 +1,24 @@ +package effectivejava.chapter4.item20.java8; + +/** + * Vehicle + * + * @author huangfl + * @since 2018/8/13 + */ +public interface Vehicle { + + /** + * jdk1.8 接口引入了默认方法,使用default修饰。 + */ + default void print() { + System.out.println("我是一辆车!"); + } + + /** + * 默认的静态方法 + */ + static void blowHorn() { + System.out.println("按喇叭!!!"); + } +} \ No newline at end of file diff --git a/src/effectivejava/chapter4/item22/constantinterface/PhysicalConstants.java b/src/main/java/effectivejava/chapter4/item22/constantinterface/PhysicalConstants.java similarity index 100% rename from src/effectivejava/chapter4/item22/constantinterface/PhysicalConstants.java rename to src/main/java/effectivejava/chapter4/item22/constantinterface/PhysicalConstants.java diff --git a/src/effectivejava/chapter4/item22/constantutilityclass/PhysicalConstants.java b/src/main/java/effectivejava/chapter4/item22/constantutilityclass/PhysicalConstants.java similarity index 100% rename from src/effectivejava/chapter4/item22/constantutilityclass/PhysicalConstants.java rename to src/main/java/effectivejava/chapter4/item22/constantutilityclass/PhysicalConstants.java diff --git a/src/effectivejava/chapter4/item23/hierarchy/Circle.java b/src/main/java/effectivejava/chapter4/item23/hierarchy/Circle.java similarity index 100% rename from src/effectivejava/chapter4/item23/hierarchy/Circle.java rename to src/main/java/effectivejava/chapter4/item23/hierarchy/Circle.java diff --git a/src/effectivejava/chapter4/item23/hierarchy/Figure.java b/src/main/java/effectivejava/chapter4/item23/hierarchy/Figure.java similarity index 100% rename from src/effectivejava/chapter4/item23/hierarchy/Figure.java rename to src/main/java/effectivejava/chapter4/item23/hierarchy/Figure.java diff --git a/src/effectivejava/chapter4/item23/hierarchy/Rectangle.java b/src/main/java/effectivejava/chapter4/item23/hierarchy/Rectangle.java similarity index 100% rename from src/effectivejava/chapter4/item23/hierarchy/Rectangle.java rename to src/main/java/effectivejava/chapter4/item23/hierarchy/Rectangle.java diff --git a/src/effectivejava/chapter4/item23/hierarchy/Square.java b/src/main/java/effectivejava/chapter4/item23/hierarchy/Square.java similarity index 100% rename from src/effectivejava/chapter4/item23/hierarchy/Square.java rename to src/main/java/effectivejava/chapter4/item23/hierarchy/Square.java diff --git a/src/effectivejava/chapter4/item23/taggedclass/Figure.java b/src/main/java/effectivejava/chapter4/item23/taggedclass/Figure.java similarity index 100% rename from src/effectivejava/chapter4/item23/taggedclass/Figure.java rename to src/main/java/effectivejava/chapter4/item23/taggedclass/Figure.java diff --git a/src/effectivejava/chapter4/item25/Dessert.java b/src/main/java/effectivejava/chapter4/item25/Dessert.java similarity index 100% rename from src/effectivejava/chapter4/item25/Dessert.java rename to src/main/java/effectivejava/chapter4/item25/Dessert.java diff --git a/src/effectivejava/chapter4/item25/Main.java b/src/main/java/effectivejava/chapter4/item25/Main.java similarity index 100% rename from src/effectivejava/chapter4/item25/Main.java rename to src/main/java/effectivejava/chapter4/item25/Main.java diff --git a/src/effectivejava/chapter4/item25/Test.java b/src/main/java/effectivejava/chapter4/item25/Test.java similarity index 100% rename from src/effectivejava/chapter4/item25/Test.java rename to src/main/java/effectivejava/chapter4/item25/Test.java diff --git a/src/effectivejava/chapter4/item25/Utensil.java b/src/main/java/effectivejava/chapter4/item25/Utensil.java similarity index 100% rename from src/effectivejava/chapter4/item25/Utensil.java rename to src/main/java/effectivejava/chapter4/item25/Utensil.java diff --git a/src/main/java/effectivejava/chapter5/item26/MyTest.java b/src/main/java/effectivejava/chapter5/item26/MyTest.java new file mode 100644 index 00000000..7b9285c4 --- /dev/null +++ b/src/main/java/effectivejava/chapter5/item26/MyTest.java @@ -0,0 +1,15 @@ +package effectivejava.chapter5.item26; + +/** + * MyTest + * + * @author huangfl + * @since 2018/8/18 + */ +public class MyTest { + + public static void main(String[] args) { + + } + +} diff --git a/src/effectivejava/chapter5/item26/Raw.java b/src/main/java/effectivejava/chapter5/item26/Raw.java similarity index 100% rename from src/effectivejava/chapter5/item26/Raw.java rename to src/main/java/effectivejava/chapter5/item26/Raw.java diff --git a/src/effectivejava/chapter5/item28/Chooser.java b/src/main/java/effectivejava/chapter5/item28/Chooser.java similarity index 100% rename from src/effectivejava/chapter5/item28/Chooser.java rename to src/main/java/effectivejava/chapter5/item28/Chooser.java diff --git a/src/effectivejava/chapter5/item29/EmptyStackException.java b/src/main/java/effectivejava/chapter5/item29/EmptyStackException.java similarity index 100% rename from src/effectivejava/chapter5/item29/EmptyStackException.java rename to src/main/java/effectivejava/chapter5/item29/EmptyStackException.java diff --git a/src/effectivejava/chapter5/item29/technqiue1/Stack.java b/src/main/java/effectivejava/chapter5/item29/technqiue1/Stack.java similarity index 100% rename from src/effectivejava/chapter5/item29/technqiue1/Stack.java rename to src/main/java/effectivejava/chapter5/item29/technqiue1/Stack.java diff --git a/src/effectivejava/chapter5/item29/technqiue2/Stack.java b/src/main/java/effectivejava/chapter5/item29/technqiue2/Stack.java similarity index 100% rename from src/effectivejava/chapter5/item29/technqiue2/Stack.java rename to src/main/java/effectivejava/chapter5/item29/technqiue2/Stack.java diff --git a/src/effectivejava/chapter5/item30/GenericSingletonFactory.java b/src/main/java/effectivejava/chapter5/item30/GenericSingletonFactory.java similarity index 100% rename from src/effectivejava/chapter5/item30/GenericSingletonFactory.java rename to src/main/java/effectivejava/chapter5/item30/GenericSingletonFactory.java diff --git a/src/effectivejava/chapter5/item30/RecursiveTypeBound.java b/src/main/java/effectivejava/chapter5/item30/RecursiveTypeBound.java similarity index 100% rename from src/effectivejava/chapter5/item30/RecursiveTypeBound.java rename to src/main/java/effectivejava/chapter5/item30/RecursiveTypeBound.java diff --git a/src/effectivejava/chapter5/item30/Union.java b/src/main/java/effectivejava/chapter5/item30/Union.java similarity index 92% rename from src/effectivejava/chapter5/item30/Union.java rename to src/main/java/effectivejava/chapter5/item30/Union.java index 47f595fc..7e944adf 100644 --- a/src/effectivejava/chapter5/item30/Union.java +++ b/src/main/java/effectivejava/chapter5/item30/Union.java @@ -1,5 +1,7 @@ package effectivejava.chapter5.item30; -import java.util.*; + +import java.util.HashSet; +import java.util.Set; // Generic union method and program to exercise it - pages 135-6 public class Union { diff --git a/src/effectivejava/chapter5/item32/Chooser.java b/src/main/java/effectivejava/chapter5/item32/Chooser.java similarity index 100% rename from src/effectivejava/chapter5/item32/Chooser.java rename to src/main/java/effectivejava/chapter5/item32/Chooser.java diff --git a/src/effectivejava/chapter5/item32/EmptyStackException.java b/src/main/java/effectivejava/chapter5/item32/EmptyStackException.java similarity index 100% rename from src/effectivejava/chapter5/item32/EmptyStackException.java rename to src/main/java/effectivejava/chapter5/item32/EmptyStackException.java diff --git a/src/effectivejava/chapter5/item32/Function.java b/src/main/java/effectivejava/chapter5/item32/Function.java similarity index 100% rename from src/effectivejava/chapter5/item32/Function.java rename to src/main/java/effectivejava/chapter5/item32/Function.java diff --git a/src/effectivejava/chapter5/item32/RecursiveTypeBound.java b/src/main/java/effectivejava/chapter5/item32/RecursiveTypeBound.java similarity index 67% rename from src/effectivejava/chapter5/item32/RecursiveTypeBound.java rename to src/main/java/effectivejava/chapter5/item32/RecursiveTypeBound.java index 7870961b..f81d11ef 100644 --- a/src/effectivejava/chapter5/item32/RecursiveTypeBound.java +++ b/src/main/java/effectivejava/chapter5/item32/RecursiveTypeBound.java @@ -1,17 +1,22 @@ package effectivejava.chapter5.item32; -import java.util.*; + +import java.util.Arrays; +import java.util.List; // Using a recursive type bound with wildcards - Page 138-139 public class RecursiveTypeBound { public static > E max( - List list) { - if (list.isEmpty()) + List list) { + if (list.isEmpty()) { throw new IllegalArgumentException("Empty list"); + } E result = null; - for (E e : list) - if (result == null || e.compareTo(result) > 0) + for (E e : list) { + if (result == null || e.compareTo(result) > 0) { result = e; + } + } return result; } diff --git a/src/effectivejava/chapter5/item32/Reduction.java b/src/main/java/effectivejava/chapter5/item32/Reduction.java similarity index 77% rename from src/effectivejava/chapter5/item32/Reduction.java rename to src/main/java/effectivejava/chapter5/item32/Reduction.java index bb1bb9d9..5163c616 100644 --- a/src/effectivejava/chapter5/item32/Reduction.java +++ b/src/main/java/effectivejava/chapter5/item32/Reduction.java @@ -1,5 +1,8 @@ package effectivejava.chapter5.item32; -import java.util.*; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; // List-based generic reduction with wildcard type - Page 136 public class Reduction { @@ -7,30 +10,32 @@ public class Reduction { static E reduce(List list, Function f, E initVal) { List snapshot; - synchronized(list) { + synchronized (list) { snapshot = new ArrayList(list); } E result = initVal; - for (E e : snapshot) + for (E e : snapshot) { result = f.apply(result, e); + } return result; } - private static final Function MAX = new Function(){ + private static final Function MAX = new Function() { + @Override public Number apply(Number n1, Number n2) { return Double.compare(n1.doubleValue(), n2.doubleValue()) > 0 ? - n1 : n2; + n1 : n2; } }; public static void main(String[] args) { // We can use a Number functionto reduce a list of Integer or Double List intList = Arrays.asList( - 2, 7, 1, 8, 2, 8, 1, 8, 2, 8); + 2, 7, 1, 8, 2, 8, 1, 8, 2, 8); System.out.println(reduce(intList, MAX, Integer.MIN_VALUE)); List doubleList = Arrays.asList( - 2.718281828, 3.141592654, 1.61803399); + 2.718281828, 3.141592654, 1.61803399); System.out.println(reduce(doubleList, MAX, Double.NEGATIVE_INFINITY)); } } diff --git a/src/effectivejava/chapter5/item32/Stack.java b/src/main/java/effectivejava/chapter5/item32/Stack.java similarity index 84% rename from src/effectivejava/chapter5/item32/Stack.java rename to src/main/java/effectivejava/chapter5/item32/Stack.java index 7bc47d6b..c0f01a1d 100644 --- a/src/effectivejava/chapter5/item32/Stack.java +++ b/src/main/java/effectivejava/chapter5/item32/Stack.java @@ -1,28 +1,44 @@ package effectivejava.chapter5.item32; -import java.util.*; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; // Generic stack with bulk methods using wildcard types - Pages 138-140 public class Stack { + private static final int DEFAULT_INITIAL_CAPACITY = 16; private E[] elements; private int size = 0; - private static final int DEFAULT_INITIAL_CAPACITY = 16; // The elements array will contain only E instances from push(E). // This is sufficient to ensure type safety, but the runtime // type of the array won't be E[]; it will always be Object[]! - @SuppressWarnings("unchecked") - public Stack() { + @SuppressWarnings("unchecked") + public Stack() { elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY]; } + // Little program to exercise our generic Stack + public static void main(String[] args) { + Stack numberStack = new Stack(); + Iterable integers = Arrays.asList(3, 1, 4, 1, 5, 9); + numberStack.pushAll(integers); + + Collection objects = new ArrayList(); + numberStack.popAll(objects); + + System.out.println(objects); + } + public void push(E e) { ensureCapacity(); elements[size++] = e; } public E pop() { - if (size==0) + if (size == 0) { throw new EmptyStackException(); + } E result = elements[--size]; elements[size] = null; // Eliminate obsolete reference return result; @@ -32,21 +48,16 @@ public boolean isEmpty() { return size == 0; } - private void ensureCapacity() { - if (elements.length == size) - elements = Arrays.copyOf(elements, 2 * size + 1); - } - // // pushAll staticfactory without wildcard type - deficient! // public void pushAll(Iterable src) { // for (E e : src) // push(e); // } - // Wildcard type for parameter that serves as an E producer - public void pushAll(Iterable src) { - for (E e : src) - push(e); + private void ensureCapacity() { + if (elements.length == size) { + elements = Arrays.copyOf(elements, 2 * size + 1); + } } // // popAll staticfactory without wildcard type - deficient! @@ -55,21 +66,17 @@ public void pushAll(Iterable src) { // dst.add(pop()); // } + // Wildcard type for parameter that serves as an E producer + public void pushAll(Iterable src) { + for (E e : src) { + push(e); + } + } + // Wildcard type for parameter that serves as an E consumer public void popAll(Collection dst) { - while (!isEmpty()) + while (!isEmpty()) { dst.add(pop()); - } - - // Little program to exercise our generic Stack - public static void main(String[] args) { - Stack numberStack = new Stack(); - Iterable integers = Arrays.asList(3, 1, 4, 1, 5, 9); - numberStack.pushAll(integers); - - Collection objects = new ArrayList(); - numberStack.popAll(objects); - - System.out.println(objects); + } } } diff --git a/src/effectivejava/chapter5/item32/Swap.java b/src/main/java/effectivejava/chapter5/item32/Swap.java similarity index 100% rename from src/effectivejava/chapter5/item32/Swap.java rename to src/main/java/effectivejava/chapter5/item32/Swap.java diff --git a/src/effectivejava/chapter5/item32/Union.java b/src/main/java/effectivejava/chapter5/item32/Union.java similarity index 100% rename from src/effectivejava/chapter5/item32/Union.java rename to src/main/java/effectivejava/chapter5/item32/Union.java diff --git a/src/effectivejava/chapter5/item33/Favorites.java b/src/main/java/effectivejava/chapter5/item33/Favorites.java similarity index 75% rename from src/effectivejava/chapter5/item33/Favorites.java rename to src/main/java/effectivejava/chapter5/item33/Favorites.java index 1d58204f..121b2bd4 100644 --- a/src/effectivejava/chapter5/item33/Favorites.java +++ b/src/main/java/effectivejava/chapter5/item33/Favorites.java @@ -1,23 +1,26 @@ package effectivejava.chapter5.item33; -import java.util.*; + +import java.util.HashMap; +import java.util.Map; // Typesafe heterogeneous container - Pages 142-145 public class Favorites { // Typesafe heterogeneous container pattern - implementation - private Map, Object> favorites = - new HashMap, Object>(); + private Map, Object> favorites = + new HashMap<>(); public void putFavorite(Class type, T instance) { - if (type == null) + if (type == null) { throw new NullPointerException("LifeCycle is null"); - favorites.put(type, instance); + } + // favorites.put(type, instance); + favorites.put(type, type.cast(instance)); } public T getFavorite(Class type) { return type.cast(favorites.get(type)); } - // Typesafe heterogeneous container pattern - client public static void main(String[] args) { Favorites f = new Favorites(); @@ -29,6 +32,6 @@ public static void main(String[] args) { int favoriteInteger = f.getFavorite(Integer.class); Class favoriteClass = f.getFavorite(Class.class); System.out.printf("%s %x %s%n", favoriteString, - favoriteInteger, favoriteClass.getName()); + favoriteInteger, favoriteClass.getName()); } } \ No newline at end of file diff --git a/src/effectivejava/chapter5/item33/PrintAnnotation.java b/src/main/java/effectivejava/chapter5/item33/PrintAnnotation.java similarity index 59% rename from src/effectivejava/chapter5/item33/PrintAnnotation.java rename to src/main/java/effectivejava/chapter5/item33/PrintAnnotation.java index 80134843..e8adebff 100644 --- a/src/effectivejava/chapter5/item33/PrintAnnotation.java +++ b/src/main/java/effectivejava/chapter5/item33/PrintAnnotation.java @@ -1,6 +1,7 @@ package effectivejava.chapter5.item33; -import java.lang.annotation.*; -import java.lang.reflect.*; + +import java.lang.annotation.Annotation; +import java.lang.reflect.AnnotatedElement; // Use of asSubclass to safely cast to a bounded type token - Page 146 public class PrintAnnotation { @@ -14,19 +15,23 @@ static Annotation getAnnotation(AnnotatedElement element, throw new IllegalArgumentException(ex); } return element.getAnnotation( - annotationType.asSubclass(Annotation.class)); + annotationType.asSubclass(Annotation.class)); } // Test program to print named annotation of named class public static void main(String[] args) throws Exception { + + args = new String[]{"effectivejava.chapter5.item33.mytest.MyClassA", + "effectivejava.chapter5.item33.mytest.MyAnnotation"}; + if (args.length != 2) { System.out.println( - "Usage: java PrintAnnotation "); + "Usage: java PrintAnnotation "); System.exit(1); } - String className = args[0]; - String annotationTypeName = args[1]; - Class klass = Class.forName(className); - System.out.println(getAnnotation(klass, annotationTypeName)); + Class klass = Class.forName(args[0]); + String annotationTypeName = args[1]; + Annotation annotation = getAnnotation(klass, annotationTypeName); + System.out.println(annotation.toString()); } } diff --git a/src/main/java/effectivejava/chapter5/item33/mytest/MyAnnotation.java b/src/main/java/effectivejava/chapter5/item33/mytest/MyAnnotation.java new file mode 100644 index 00000000..559d7078 --- /dev/null +++ b/src/main/java/effectivejava/chapter5/item33/mytest/MyAnnotation.java @@ -0,0 +1,24 @@ +package effectivejava.chapter5.item33.mytest; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * TestAnnotation + * + * @author huangfl + * @since 2018/8/18 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface MyAnnotation { + + String module(); + + String value(); + +} diff --git a/src/main/java/effectivejava/chapter5/item33/mytest/MyClassA.java b/src/main/java/effectivejava/chapter5/item33/mytest/MyClassA.java new file mode 100644 index 00000000..82160114 --- /dev/null +++ b/src/main/java/effectivejava/chapter5/item33/mytest/MyClassA.java @@ -0,0 +1,12 @@ +package effectivejava.chapter5.item33.mytest; + +/** + * MyClassA + * + * @author huangfl + * @since 2018/8/18 + */ +@MyAnnotation(value = "testA", module = "moduleA") +public interface MyClassA { + +} diff --git a/src/main/java/effectivejava/chapter5/item33/mytest/TestMain.java b/src/main/java/effectivejava/chapter5/item33/mytest/TestMain.java new file mode 100644 index 00000000..a70b6789 --- /dev/null +++ b/src/main/java/effectivejava/chapter5/item33/mytest/TestMain.java @@ -0,0 +1,20 @@ +package effectivejava.chapter5.item33.mytest; + +/** + * TestMain + * + * @author huangfl + * @since 2018/8/18 + */ +public class TestMain { + + public static void main(String[] args) throws Exception { + + Class aClass = Class.forName("effectivejava.chapter5.item33.mytest.MyClassA"); + Class aAnnotation = Class.forName("effectivejava.chapter5.item33.mytest.MyAnnotation"); + MyAnnotation myAnnotation = aClass.getAnnotation(MyAnnotation.class); + + System.out.println(myAnnotation.module()); + System.out.println(myAnnotation.value()); + } +} diff --git a/src/main/java/effectivejava/chapter6/item34/Operation.java b/src/main/java/effectivejava/chapter6/item34/Operation.java new file mode 100644 index 00000000..aeafc98c --- /dev/null +++ b/src/main/java/effectivejava/chapter6/item34/Operation.java @@ -0,0 +1,92 @@ +package effectivejava.chapter6.item34; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +// Enum type with constant-specific class bodies and data (Page 161) +public enum Operation { + // 加 + PLUS("+") { + @Override + public double apply(double x, double y) { + return x + y; + } + }, + // 减 + MINUS("-") { + @Override + public double apply(double x, double y) { + return x - y; + } + }, + // 乘 + TIMES("*") { + @Override + public double apply(double x, double y) { + return x * y; + } + }, + // 除 + DIVIDE("/") { + @Override + public double apply(double x, double y) { + return x / y; + } + }; + + private final String symbol; + + /** + * 枚举的构造方法,这样传入的symbol就和枚举常量关联了 + */ + Operation(String symbol) { + this.symbol = symbol; + } + + /** + * 覆盖toString方法 + */ + @Override + public String toString() { + return symbol; + } + + /** + * 抽象方法,新加入的枚举常量一定要实现该抽象方法,防止遗漏。 + */ + public abstract double apply(double x, double y); + + // Implementing a fromString method on an enum type +// private static final Map stringToEnum = +// Stream.of(values()).collect( +// toMap(Object::toString, e -> e)); + + private static final Map stringToEnum = new HashMap<>(); + + static { + for (Operation op : values()) { + stringToEnum.put(op.toString(), op); + } + } + + // Returns Operation for string, if any + public static Optional fromString(String symbol) { + return Optional.ofNullable(stringToEnum.get(symbol)); + } + + public static void main(String[] args) { + + args = new String[]{"2.2", "2.8"}; + + double x = Double.parseDouble(args[0]); + double y = Double.parseDouble(args[1]); + for (Operation op : Operation.values()) { + System.out.printf("%f %s %f = %f%n", + x, op, y, op.apply(x, y)); + } + + Operation operation = Operation.stringToEnum.get("+"); + System.out.println(operation); + } +} diff --git a/src/main/java/effectivejava/chapter6/item34/PayrollDay.java b/src/main/java/effectivejava/chapter6/item34/PayrollDay.java new file mode 100644 index 00000000..afd5cd4b --- /dev/null +++ b/src/main/java/effectivejava/chapter6/item34/PayrollDay.java @@ -0,0 +1,64 @@ +package effectivejava.chapter6.item34; + +/** + * The strategy enum pattern -- 策略枚举 + */ +public enum PayrollDay { + // 周一~周日 + MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, + SATURDAY(PayType.WEEKEND), SUNDAY(PayType.WEEKEND); + + private final PayType payType; + + PayrollDay(PayType payType) { + // 周末按照(PayType.WEEKEND)计算 + this.payType = payType; + } + + PayrollDay() { + // 默认按照工作日(PayType.WEEKDAY)计 + this(PayType.WEEKDAY); + } + + double pay(double minutesWorked, double payRate) { + return payType.pay(minutesWorked, payRate); + } + + // The strategy enum type + private enum PayType { + // 工作日超时8小时算加班 + WEEKDAY { + @Override + double overtimePay(double minsWorked, double payRate) { + return minsWorked <= MINS_PER_SHIFT ? 0 : + (minsWorked - MINS_PER_SHIFT) * payRate / 2; + } + }, + // 周末都算加班 + WEEKEND { + @Override + double overtimePay(double minsWorked, double payRate) { + // 加班按1.5倍 + return minsWorked * payRate / 2; + } + }; + + abstract double overtimePay(double mins, double payRate); + + // 正常工作8小时 + private static final double MINS_PER_SHIFT = 8; + + double pay(double minsWorked, double payRate) { + double basePay = minsWorked * payRate; + return basePay + overtimePay(minsWorked, payRate); + } + } + + public static void main(String[] args) { + double payMonday = PayrollDay.MONDAY.pay(9, 1); + System.out.println(payMonday); + + double paySaturday = PayrollDay.SATURDAY.pay(9, 1); + System.out.println(paySaturday); + } +} diff --git a/src/effectivejava/chapter6/item34/Planet.java b/src/main/java/effectivejava/chapter6/item34/Planet.java similarity index 68% rename from src/effectivejava/chapter6/item34/Planet.java rename to src/main/java/effectivejava/chapter6/item34/Planet.java index 833cf8c8..5ff7c438 100644 --- a/src/effectivejava/chapter6/item34/Planet.java +++ b/src/main/java/effectivejava/chapter6/item34/Planet.java @@ -2,13 +2,14 @@ // Enum type with data and behavior (157-158) public enum Planet { + // 行星 MERCURY(3.302e+23, 2.439e6), - VENUS (4.869e+24, 6.052e6), - EARTH (5.975e+24, 6.378e6), - MARS (6.419e+23, 3.393e6), + VENUS(4.869e+24, 6.052e6), + EARTH(5.975e+24, 6.378e6), + MARS(6.419e+23, 3.393e6), JUPITER(1.899e+27, 7.149e7), - SATURN (5.685e+26, 6.027e7), - URANUS (8.683e+25, 2.556e7), + SATURN(5.685e+26, 6.027e7), + URANUS(8.683e+25, 2.556e7), NEPTUNE(1.024e+26, 2.477e7); private final double mass; // In kilograms @@ -24,9 +25,17 @@ public enum Planet { surfaceGravity = G * mass / (radius * radius); } - public double mass() { return mass; } - public double radius() { return radius; } - public double surfaceGravity() { return surfaceGravity; } + public double mass() { + return mass; + } + + public double radius() { + return radius; + } + + public double surfaceGravity() { + return surfaceGravity; + } public double surfaceWeight(double mass) { return mass * surfaceGravity; // F = ma diff --git a/src/main/java/effectivejava/chapter6/item34/WeightTable.java b/src/main/java/effectivejava/chapter6/item34/WeightTable.java new file mode 100644 index 00000000..8300f509 --- /dev/null +++ b/src/main/java/effectivejava/chapter6/item34/WeightTable.java @@ -0,0 +1,16 @@ +package effectivejava.chapter6.item34; + +// Takes earth-weight and prints table of weights on all planets - Page 158 +public class WeightTable { + public static void main(String[] args) { + + args = new String[]{"10.0"}; + + double earthWeight = Double.parseDouble(args[0]); + double mass = earthWeight / Planet.EARTH.surfaceGravity(); + for (Planet p : Planet.values()) { + System.out.printf("Weight on %s is %f%n", + p, p.surfaceWeight(mass)); + } + } +} diff --git a/src/effectivejava/chapter6/item35/Ensemble.java b/src/main/java/effectivejava/chapter6/item35/Ensemble.java similarity index 100% rename from src/effectivejava/chapter6/item35/Ensemble.java rename to src/main/java/effectivejava/chapter6/item35/Ensemble.java diff --git a/src/effectivejava/chapter6/item36/Text.java b/src/main/java/effectivejava/chapter6/item36/Text.java similarity index 100% rename from src/effectivejava/chapter6/item36/Text.java rename to src/main/java/effectivejava/chapter6/item36/Text.java diff --git a/src/effectivejava/chapter6/item37/Phase.java b/src/main/java/effectivejava/chapter6/item37/Phase.java similarity index 87% rename from src/effectivejava/chapter6/item37/Phase.java rename to src/main/java/effectivejava/chapter6/item37/Phase.java index 7be869ec..0d4f0e14 100644 --- a/src/effectivejava/chapter6/item37/Phase.java +++ b/src/main/java/effectivejava/chapter6/item37/Phase.java @@ -1,18 +1,24 @@ package effectivejava.chapter6.item37; -import java.util.*; + +import java.util.EnumMap; +import java.util.Map; import java.util.stream.Stream; -import static java.util.stream.Collectors.*; +import static java.util.stream.Collectors.groupingBy; +import static java.util.stream.Collectors.toMap; // Using a nested EnumMap to associate data with enum pairs - (Pages 172-3) public enum Phase { + // phase SOLID, LIQUID, GAS; + public enum Transition { + // transition MELT(SOLID, LIQUID), FREEZE(LIQUID, SOLID), BOIL(LIQUID, GAS), CONDENSE(GAS, LIQUID), SUBLIME(SOLID, GAS), DEPOSIT(GAS, SOLID); - // Adding a new phase (Page 173) + // Adding a new phase (Page 173) // SOLID, LIQUID, GAS, PLASMA; // public enum Transition { // MELT(SOLID, LIQUID), FREEZE(LIQUID, SOLID), @@ -22,6 +28,7 @@ public enum Transition { private final Phase from; private final Phase to; + Transition(Phase from, Phase to) { this.from = from; this.to = to; @@ -33,6 +40,7 @@ public enum Transition { () -> new EnumMap<>(Phase.class), toMap(t -> t.to, t -> t, (x, y) -> y, () -> new EnumMap<>(Phase.class)))); + public static Transition from(Phase from, Phase to) { return m.get(from).get(to); } diff --git a/src/effectivejava/chapter6/item37/Plant.java b/src/main/java/effectivejava/chapter6/item37/Plant.java similarity index 55% rename from src/effectivejava/chapter6/item37/Plant.java rename to src/main/java/effectivejava/chapter6/item37/Plant.java index 0f4e5735..d87e3d3f 100644 --- a/src/effectivejava/chapter6/item37/Plant.java +++ b/src/main/java/effectivejava/chapter6/item37/Plant.java @@ -1,5 +1,11 @@ package effectivejava.chapter6.item37; -import java.util.*; + +import java.util.Arrays; +import java.util.EnumMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + import static java.util.stream.Collectors.groupingBy; import static java.util.stream.Collectors.toSet; @@ -7,7 +13,7 @@ // Simplistic class representing a plant - Page 169 class Plant { - enum LifeCycle { ANNUAL, PERENNIAL, BIENNIAL } + enum LifeCycle {ANNUAL, PERENNIAL, BIENNIAL} final String name; final LifeCycle lifeCycle; @@ -17,40 +23,45 @@ enum LifeCycle { ANNUAL, PERENNIAL, BIENNIAL } this.lifeCycle = lifeCycle; } - @Override public String toString() { + @Override + public String toString() { return name; } public static void main(String[] args) { Plant[] garden = { - new Plant("Basil", LifeCycle.ANNUAL), - new Plant("Carroway", LifeCycle.BIENNIAL), - new Plant("Dill", LifeCycle.ANNUAL), - new Plant("Lavendar", LifeCycle.PERENNIAL), - new Plant("Parsley", LifeCycle.BIENNIAL), - new Plant("Rosemary", LifeCycle.PERENNIAL) + new Plant("Basil", LifeCycle.ANNUAL), + new Plant("Carroway", LifeCycle.BIENNIAL), + new Plant("Dill", LifeCycle.ANNUAL), + new Plant("Lavendar", LifeCycle.PERENNIAL), + new Plant("Parsley", LifeCycle.BIENNIAL), + new Plant("Rosemary", LifeCycle.PERENNIAL) }; - // Using ordinal() to index into an array - DON'T DO THIS! (Page 170) + // 1.Using ordinal() to index into an array - DON'T DO THIS! (Page 170) Set[] plantsByLifeCycleArr = - (Set[]) new Set[Plant.LifeCycle.values().length]; - for (int i = 0; i < plantsByLifeCycleArr.length; i++) + (Set[]) new Set[LifeCycle.values().length]; + for (int i = 0; i < plantsByLifeCycleArr.length; i++) { plantsByLifeCycleArr[i] = new HashSet<>(); - for (Plant p : garden) + } + for (Plant p : garden) { plantsByLifeCycleArr[p.lifeCycle.ordinal()].add(p); + } // Print the results for (int i = 0; i < plantsByLifeCycleArr.length; i++) { System.out.printf("%s: %s%n", - Plant.LifeCycle.values()[i], plantsByLifeCycleArr[i]); + LifeCycle.values()[i], plantsByLifeCycleArr[i]); } - // Using an EnumMap to associate data with an enum (P. 170) - Map> plantsByLifeCycle = - new EnumMap<>(Plant.LifeCycle.class); - for (Plant.LifeCycle lc : Plant.LifeCycle.values()) + // 2.Using an EnumMap to associate data with an enum (P. 170) + Map> plantsByLifeCycle = + new EnumMap<>(LifeCycle.class); + for (LifeCycle lc : LifeCycle.values()) { plantsByLifeCycle.put(lc, new HashSet<>()); - for (Plant p : garden) + } + for (Plant p : garden) { plantsByLifeCycle.get(p.lifeCycle).add(p); + } System.out.println(plantsByLifeCycle); // Naive stream-based approach - unlikely to produce an EnumMap! (Page 171) diff --git a/src/main/java/effectivejava/chapter6/item38/BasicOperation.java b/src/main/java/effectivejava/chapter6/item38/BasicOperation.java new file mode 100644 index 00000000..bb88193e --- /dev/null +++ b/src/main/java/effectivejava/chapter6/item38/BasicOperation.java @@ -0,0 +1,46 @@ +package effectivejava.chapter6.item38; + +// Emulated extensible enum using an interface - Basic implementation - Page 174 +public enum BasicOperation implements Operation { + // + PLUS("+") { + @Override + public double apply(double x, double y) { + return x + y; + } + }, + MINUS("-") { + @Override + public double apply(double x, double y) { + return x - y; + } + }, + TIMES("*") { + @Override + public double apply(double x, double y) { + return x * y; + } + }, + DIVIDE("/") { + @Override + public double apply(double x, double y) { + return x / y; + } + }; + + private final String symbol; + + BasicOperation(String symbol) { + this.symbol = symbol; + } + + @Override + public String toString() { + return symbol; + } + + public static void main(String[] args) { + double result = BasicOperation.PLUS.apply(1.2, 2.8); + System.out.println(result); + } +} diff --git a/src/effectivejava/chapter6/item38/ExtendedOperation.java b/src/main/java/effectivejava/chapter6/item38/ExtendedOperation.java similarity index 62% rename from src/effectivejava/chapter6/item38/ExtendedOperation.java rename to src/main/java/effectivejava/chapter6/item38/ExtendedOperation.java index fa42fa96..bdafee87 100644 --- a/src/effectivejava/chapter6/item38/ExtendedOperation.java +++ b/src/main/java/effectivejava/chapter6/item38/ExtendedOperation.java @@ -1,49 +1,61 @@ package effectivejava.chapter6.item38; -import java.util.*; // Emulated extension enum - (Pages 175-7) public enum ExtendedOperation implements Operation { + // EXP("^") { + @Override public double apply(double x, double y) { return Math.pow(x, y); } }, REMAINDER("%") { + @Override public double apply(double x, double y) { return x % y; } }; private final String symbol; + ExtendedOperation(String symbol) { this.symbol = symbol; } - @Override public String toString() { + + @Override + public String toString() { return symbol; } - // WRITE DESCR *** -// public static void main(String[] args) { -// double x = Double.parseDouble(args[0]); -// double y = Double.parseDouble(args[1]); -// test(ExtendedOperation.class, x, y); -// } -// private static & Operation> void test( -// Class opEnumType, double x, double y) { -// for (Operation op : opEnumType.getEnumConstants()) -// System.out.printf("%f %s %f = %f%n", -// x, op, y, op.apply(x, y)); -// } - // WRITE DESCR *** public static void main(String[] args) { + + args = new String[]{"1.2", "3.4"}; + double x = Double.parseDouble(args[0]); double y = Double.parseDouble(args[1]); - test(Arrays.asList(ExtendedOperation.values()), x, y); + test(ExtendedOperation.class, x, y); } - private static void test(Collection opSet, - double x, double y) { - for (Operation op : opSet) + + private static & Operation> void test( + Class opEnumType, double x, double y) { + for (Operation op : opEnumType.getEnumConstants()) { System.out.printf("%f %s %f = %f%n", x, op, y, op.apply(x, y)); + } } + + // WRITE DESCR *** +// public static void main(String[] args) { +// double x = Double.parseDouble(args[0]); +// double y = Double.parseDouble(args[1]); +// test(Arrays.asList(ExtendedOperation.values()), x, y); +// } +// +// private static void test(Collection opSet, +// double x, double y) { +// for (Operation op : opSet) { +// System.out.printf("%f %s %f = %f%n", +// x, op, y, op.apply(x, y)); +// } +// } } diff --git a/src/effectivejava/chapter6/item38/Operation.java b/src/main/java/effectivejava/chapter6/item38/Operation.java similarity index 100% rename from src/effectivejava/chapter6/item38/Operation.java rename to src/main/java/effectivejava/chapter6/item38/Operation.java diff --git a/src/effectivejava/chapter6/item39/regularannotation/ExceptionTest.java b/src/main/java/effectivejava/chapter6/item39/regularannotation/ExceptionTest.java similarity index 77% rename from src/effectivejava/chapter6/item39/regularannotation/ExceptionTest.java rename to src/main/java/effectivejava/chapter6/item39/regularannotation/ExceptionTest.java index c05061b9..38037ea7 100644 --- a/src/effectivejava/chapter6/item39/regularannotation/ExceptionTest.java +++ b/src/main/java/effectivejava/chapter6/item39/regularannotation/ExceptionTest.java @@ -1,5 +1,9 @@ package effectivejava.chapter6.item39.regularannotation; -import java.lang.annotation.*; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; // Annotation type with an array parameter - Page 183 diff --git a/src/effectivejava/chapter6/item39/regularannotation/RunTests.java b/src/main/java/effectivejava/chapter6/item39/regularannotation/RunTests.java similarity index 84% rename from src/effectivejava/chapter6/item39/regularannotation/RunTests.java rename to src/main/java/effectivejava/chapter6/item39/regularannotation/RunTests.java index 96b7c832..3f1d34b1 100644 --- a/src/effectivejava/chapter6/item39/regularannotation/RunTests.java +++ b/src/main/java/effectivejava/chapter6/item39/regularannotation/RunTests.java @@ -1,9 +1,15 @@ package effectivejava.chapter6.item39.regularannotation; -import java.lang.reflect.*; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; // Program to process marker annotations - Page 171 public class RunTests { public static void main(String[] args) throws Exception { + +// args = new String[]{"effectivejava.chapter6.item39.regularannotation.Sample"}; + args = new String[]{"effectivejava.chapter6.item39.regularannotation.Sample2"}; + int tests = 0; int passed = 0; Class testClass = Class.forName(args[0]); @@ -20,7 +26,7 @@ public static void main(String[] args) throws Exception { System.out.println("Invalid @Test: " + m); } } - + if (m.isAnnotationPresent(ExceptionTest.class)) { tests++; try { @@ -37,8 +43,9 @@ public static void main(String[] args) throws Exception { break; } } - if (passed == oldPassed) + if (passed == oldPassed) { System.out.printf("Test %s failed: %s %n", m, exc); + } } } } diff --git a/src/main/java/effectivejava/chapter6/item39/regularannotation/Sample.java b/src/main/java/effectivejava/chapter6/item39/regularannotation/Sample.java new file mode 100644 index 00000000..df45dcac --- /dev/null +++ b/src/main/java/effectivejava/chapter6/item39/regularannotation/Sample.java @@ -0,0 +1,34 @@ +package effectivejava.chapter6.item39.regularannotation; + +// Program containing marker annotations - Page 170 +public class Sample { + @Test + public static void m1() { + } // Test should pass + + public static void m2() { + } + + @Test + public static void m3() { // Test should fail + throw new RuntimeException("Boom"); + } + + public static void m4() { + } + + public static void m6() { + } + + @Test + public static void m7() { // Test should fail + throw new RuntimeException("Crash"); + } + + public static void m8() { + } + + @Test + public void m5() { + } // INVALID USE: nonstatic method +} \ No newline at end of file diff --git a/src/effectivejava/chapter6/item39/regularannotation/Sample2.java b/src/main/java/effectivejava/chapter6/item39/regularannotation/Sample2.java similarity index 78% rename from src/effectivejava/chapter6/item39/regularannotation/Sample2.java rename to src/main/java/effectivejava/chapter6/item39/regularannotation/Sample2.java index 08fbea6f..099663d4 100644 --- a/src/effectivejava/chapter6/item39/regularannotation/Sample2.java +++ b/src/main/java/effectivejava/chapter6/item39/regularannotation/Sample2.java @@ -1,5 +1,7 @@ package effectivejava.chapter6.item39.regularannotation; -import java.util.*; + +import java.util.ArrayList; +import java.util.List; // Program containing annotations with a parameter - Page 172 public class Sample2 { @@ -8,17 +10,20 @@ public static void m1() { // Test should pass int i = 0; i = i / i; } + @ExceptionTest(ArithmeticException.class) public static void m2() { // Should fail (wrong exception) int[] a = new int[0]; int i = a[1]; } + @ExceptionTest(ArithmeticException.class) - public static void m3() { } // Should fail (no exception) + public static void m3() { + } // Should fail (no exception) // Code containing an annotation with an array parameter - @ExceptionTest({ IndexOutOfBoundsException.class, - NullPointerException.class }) + @ExceptionTest({IndexOutOfBoundsException.class, + NullPointerException.class}) public static void doublyBad() { List list = new ArrayList<>(); diff --git a/src/effectivejava/chapter6/item39/regularannotation/Test.java b/src/main/java/effectivejava/chapter6/item39/regularannotation/Test.java similarity index 65% rename from src/effectivejava/chapter6/item39/regularannotation/Test.java rename to src/main/java/effectivejava/chapter6/item39/regularannotation/Test.java index df46a97a..f1407e28 100644 --- a/src/effectivejava/chapter6/item39/regularannotation/Test.java +++ b/src/main/java/effectivejava/chapter6/item39/regularannotation/Test.java @@ -1,8 +1,11 @@ package effectivejava.chapter6.item39.regularannotation; -import java.lang.annotation.*; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; // Marker annotation type declaration - Page 180 -import java.lang.annotation.*; /** * Indicates that the annotated method is a test method. diff --git a/src/effectivejava/chapter6/item39/repeatableannotation/ExceptionTest.java b/src/main/java/effectivejava/chapter6/item39/repeatableannotation/ExceptionTest.java similarity index 100% rename from src/effectivejava/chapter6/item39/repeatableannotation/ExceptionTest.java rename to src/main/java/effectivejava/chapter6/item39/repeatableannotation/ExceptionTest.java diff --git a/src/effectivejava/chapter6/item39/repeatableannotation/ExceptionTestContainer.java b/src/main/java/effectivejava/chapter6/item39/repeatableannotation/ExceptionTestContainer.java similarity index 100% rename from src/effectivejava/chapter6/item39/repeatableannotation/ExceptionTestContainer.java rename to src/main/java/effectivejava/chapter6/item39/repeatableannotation/ExceptionTestContainer.java diff --git a/src/effectivejava/chapter6/item39/repeatableannotation/RunTests.java b/src/main/java/effectivejava/chapter6/item39/repeatableannotation/RunTests.java similarity index 100% rename from src/effectivejava/chapter6/item39/repeatableannotation/RunTests.java rename to src/main/java/effectivejava/chapter6/item39/repeatableannotation/RunTests.java diff --git a/src/effectivejava/chapter6/item39/repeatableannotation/Sample2.java b/src/main/java/effectivejava/chapter6/item39/repeatableannotation/Sample2.java similarity index 100% rename from src/effectivejava/chapter6/item39/repeatableannotation/Sample2.java rename to src/main/java/effectivejava/chapter6/item39/repeatableannotation/Sample2.java diff --git a/src/effectivejava/chapter6/item39/repeatableannotation/Test.java b/src/main/java/effectivejava/chapter6/item39/repeatableannotation/Test.java similarity index 100% rename from src/effectivejava/chapter6/item39/repeatableannotation/Test.java rename to src/main/java/effectivejava/chapter6/item39/repeatableannotation/Test.java diff --git a/src/main/java/effectivejava/chapter6/item40/Bigram.java b/src/main/java/effectivejava/chapter6/item40/Bigram.java new file mode 100644 index 00000000..a64ac895 --- /dev/null +++ b/src/main/java/effectivejava/chapter6/item40/Bigram.java @@ -0,0 +1,44 @@ +package effectivejava.chapter6.item40; + +import java.util.HashSet; +import java.util.Set; + +// Can you spot the bug? (Page 188) +public class Bigram { + private final char first; + private final char second; + + public Bigram(char first, char second) { + this.first = first; + this.second = second; + } + + // 没有覆盖equals(),重载了。 +// public boolean equals(Bigram b) { +// return b.first == first && b.second == second; +// } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Bigram)) { + return false; + } + Bigram bigram = (Bigram) obj; + return this.first == bigram.first && this.second == bigram.second; + } + + @Override + public int hashCode() { + return 31 * first + second; + } + + public static void main(String[] args) { + Set s = new HashSet<>(); + for (int i = 0; i < 10; i++) { + for (char ch = 'a'; ch <= 'z'; ch++) { + s.add(new Bigram(ch, ch)); + } + } + System.out.println(s.size()); + } +} diff --git a/src/effectivejava/chapter7/item42/Operation.java b/src/main/java/effectivejava/chapter7/item42/Operation.java similarity index 100% rename from src/effectivejava/chapter7/item42/Operation.java rename to src/main/java/effectivejava/chapter7/item42/Operation.java diff --git a/src/effectivejava/chapter7/item42/SortFourWays.java b/src/main/java/effectivejava/chapter7/item42/SortFourWays.java similarity index 98% rename from src/effectivejava/chapter7/item42/SortFourWays.java rename to src/main/java/effectivejava/chapter7/item42/SortFourWays.java index b41c9437..5f5266b0 100644 --- a/src/effectivejava/chapter7/item42/SortFourWays.java +++ b/src/main/java/effectivejava/chapter7/item42/SortFourWays.java @@ -14,6 +14,7 @@ public static void main(String[] args) { // Anonymous class instance as a function object - obsolete! Collections.sort(words, new Comparator() { + @Override public int compare(String s1, String s2) { return Integer.compare(s1.length(), s2.length()); } diff --git a/src/effectivejava/chapter7/item43/Freq.java b/src/main/java/effectivejava/chapter7/item43/Freq.java similarity index 100% rename from src/effectivejava/chapter7/item43/Freq.java rename to src/main/java/effectivejava/chapter7/item43/Freq.java diff --git a/src/effectivejava/chapter7/item45/Card.java b/src/main/java/effectivejava/chapter7/item45/Card.java similarity index 100% rename from src/effectivejava/chapter7/item45/Card.java rename to src/main/java/effectivejava/chapter7/item45/Card.java diff --git a/src/effectivejava/chapter7/item45/Freq.java b/src/main/java/effectivejava/chapter7/item45/Freq.java similarity index 100% rename from src/effectivejava/chapter7/item45/Freq.java rename to src/main/java/effectivejava/chapter7/item45/Freq.java diff --git a/src/effectivejava/chapter7/item45/MersennePrimes.java b/src/main/java/effectivejava/chapter7/item45/MersennePrimes.java similarity index 100% rename from src/effectivejava/chapter7/item45/MersennePrimes.java rename to src/main/java/effectivejava/chapter7/item45/MersennePrimes.java diff --git a/src/effectivejava/chapter7/item45/anagrams/HybridAnagrams.java b/src/main/java/effectivejava/chapter7/item45/anagrams/HybridAnagrams.java similarity index 100% rename from src/effectivejava/chapter7/item45/anagrams/HybridAnagrams.java rename to src/main/java/effectivejava/chapter7/item45/anagrams/HybridAnagrams.java diff --git a/src/effectivejava/chapter7/item45/anagrams/IterativeAnagrams.java b/src/main/java/effectivejava/chapter7/item45/anagrams/IterativeAnagrams.java similarity index 100% rename from src/effectivejava/chapter7/item45/anagrams/IterativeAnagrams.java rename to src/main/java/effectivejava/chapter7/item45/anagrams/IterativeAnagrams.java diff --git a/src/effectivejava/chapter7/item45/anagrams/StreamAnagrams.java b/src/main/java/effectivejava/chapter7/item45/anagrams/StreamAnagrams.java similarity index 100% rename from src/effectivejava/chapter7/item45/anagrams/StreamAnagrams.java rename to src/main/java/effectivejava/chapter7/item45/anagrams/StreamAnagrams.java diff --git a/src/effectivejava/chapter7/item47/Adapters.java b/src/main/java/effectivejava/chapter7/item47/Adapters.java similarity index 100% rename from src/effectivejava/chapter7/item47/Adapters.java rename to src/main/java/effectivejava/chapter7/item47/Adapters.java diff --git a/src/effectivejava/chapter7/item47/PowerSet.java b/src/main/java/effectivejava/chapter7/item47/PowerSet.java similarity index 100% rename from src/effectivejava/chapter7/item47/PowerSet.java rename to src/main/java/effectivejava/chapter7/item47/PowerSet.java diff --git a/src/effectivejava/chapter7/item47/SubLists.java b/src/main/java/effectivejava/chapter7/item47/SubLists.java similarity index 100% rename from src/effectivejava/chapter7/item47/SubLists.java rename to src/main/java/effectivejava/chapter7/item47/SubLists.java diff --git a/src/effectivejava/chapter7/item48/ParallelMersennePrimes.java b/src/main/java/effectivejava/chapter7/item48/ParallelMersennePrimes.java similarity index 100% rename from src/effectivejava/chapter7/item48/ParallelMersennePrimes.java rename to src/main/java/effectivejava/chapter7/item48/ParallelMersennePrimes.java diff --git a/src/effectivejava/chapter7/item48/ParallelPrimeCounting.java b/src/main/java/effectivejava/chapter7/item48/ParallelPrimeCounting.java similarity index 100% rename from src/effectivejava/chapter7/item48/ParallelPrimeCounting.java rename to src/main/java/effectivejava/chapter7/item48/ParallelPrimeCounting.java diff --git a/src/effectivejava/chapter8/item50/Attack.java b/src/main/java/effectivejava/chapter8/item50/Attack.java similarity index 100% rename from src/effectivejava/chapter8/item50/Attack.java rename to src/main/java/effectivejava/chapter8/item50/Attack.java diff --git a/src/main/java/effectivejava/chapter8/item50/Period.java b/src/main/java/effectivejava/chapter8/item50/Period.java new file mode 100644 index 00000000..83172ba2 --- /dev/null +++ b/src/main/java/effectivejava/chapter8/item50/Period.java @@ -0,0 +1,57 @@ +package effectivejava.chapter8.item50; + +import java.util.Date; + +// Broken "immutable" time period class - Page 231-3 +public final class Period { + private final Date start; + private final Date end; + + /** + * @param start the beginning of the period + * @param end the end of the period; must not precede start + * @throws IllegalArgumentException if start is after end + * @throws NullPointerException if start or end is null + */ +// public Period(Date start, Date end) { +// if (start.compareTo(end) > 0) { +// throw new IllegalArgumentException( +// start + " after " + end); +// } +// this.start = start; +// this.end = end; +// } +// +// public Date start() { +// return start; +// } +// public Date end() { +// return end; +// } + + @Override + public String toString() { + return start + " - " + end; + } + + // Repaired constructor - makes defensive copies of parameters + public Period(Date start, Date end) { + this.start = new Date(start.getTime()); + this.end = new Date(end.getTime()); + + if (this.start.compareTo(this.end) > 0) + throw new IllegalArgumentException( + this.start + " after " + this.end); + } + + // Repaired accessors - make defensive copies of internal fields (Page 233) + public Date start() { + return new Date(start.getTime()); + } + + public Date end() { + return new Date(end.getTime()); + } + + // Remainder omitted +} \ No newline at end of file diff --git a/src/effectivejava/chapter8/item52/Champagne.java b/src/main/java/effectivejava/chapter8/item52/Champagne.java similarity index 100% rename from src/effectivejava/chapter8/item52/Champagne.java rename to src/main/java/effectivejava/chapter8/item52/Champagne.java diff --git a/src/main/java/effectivejava/chapter8/item52/CollectionClassifier.java b/src/main/java/effectivejava/chapter8/item52/CollectionClassifier.java new file mode 100644 index 00000000..c3d52b43 --- /dev/null +++ b/src/main/java/effectivejava/chapter8/item52/CollectionClassifier.java @@ -0,0 +1,41 @@ +package effectivejava.chapter8.item52; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +// Broken! - What does this program print? (Page 238) +public class CollectionClassifier { +// public static String classify(Set s) { +// return "Set"; +// } +// +// public static String classify(List lst) { +// return "List"; +// } +// +// public static String classify(Collection c) { +// return "Unknown Collection"; +// } + + public static void main(String[] args) { + Collection[] collections = { + new HashSet(), + new ArrayList(), + new HashMap().values() + }; + + for (Collection c : collections) { + System.out.println(classify(c)); + } + } + // Repaired static classifier method. (Page 240) + public static String classify(Collection c) { + return c instanceof Set ? "Set" : + c instanceof List ? "List" : "Unknown Collection"; + } +} diff --git a/src/effectivejava/chapter8/item52/Overriding.java b/src/main/java/effectivejava/chapter8/item52/Overriding.java similarity index 86% rename from src/effectivejava/chapter8/item52/Overriding.java rename to src/main/java/effectivejava/chapter8/item52/Overriding.java index 7f5b2e69..e2b787ed 100644 --- a/src/effectivejava/chapter8/item52/Overriding.java +++ b/src/main/java/effectivejava/chapter8/item52/Overriding.java @@ -7,7 +7,8 @@ public static void main(String[] args) { List wineList = List.of( new Wine(), new SparklingWine(), new Champagne()); - for (Wine wine : wineList) + for (Wine wine : wineList) { System.out.println(wine.name()); + } } } diff --git a/src/effectivejava/chapter8/item52/SetList.java b/src/main/java/effectivejava/chapter8/item52/SetList.java similarity index 100% rename from src/effectivejava/chapter8/item52/SetList.java rename to src/main/java/effectivejava/chapter8/item52/SetList.java diff --git a/src/effectivejava/chapter8/item52/SparklingWine.java b/src/main/java/effectivejava/chapter8/item52/SparklingWine.java similarity index 100% rename from src/effectivejava/chapter8/item52/SparklingWine.java rename to src/main/java/effectivejava/chapter8/item52/SparklingWine.java diff --git a/src/effectivejava/chapter8/item52/Wine.java b/src/main/java/effectivejava/chapter8/item52/Wine.java similarity index 100% rename from src/effectivejava/chapter8/item52/Wine.java rename to src/main/java/effectivejava/chapter8/item52/Wine.java diff --git a/src/effectivejava/chapter8/item53/Varargs.java b/src/main/java/effectivejava/chapter8/item53/Varargs.java similarity index 89% rename from src/effectivejava/chapter8/item53/Varargs.java rename to src/main/java/effectivejava/chapter8/item53/Varargs.java index d427213d..0386b7aa 100644 --- a/src/effectivejava/chapter8/item53/Varargs.java +++ b/src/main/java/effectivejava/chapter8/item53/Varargs.java @@ -8,8 +8,9 @@ public class Varargs { // Simple use of varargs - Page 245 static int sum(int... args) { int sum = 0; - for (int arg : args) + for (int arg : args) { sum += arg; + } return sum; } @@ -32,13 +33,14 @@ static int sum2(int... args) { // The right way to use varargs to pass one or more arguments - Page 246 static int min(int firstArg, int... remainingArgs) { int min = firstArg; - for (int arg : remainingArgs) - if (arg < min) + for (int arg : remainingArgs) { + if (arg < min) { min = arg; + } + } return min; } - public static void main(String[] args) { System.out.println(sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)); System.out.println(min(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)); diff --git a/src/effectivejava/chapter8/item55/Max.java b/src/main/java/effectivejava/chapter8/item55/Max.java similarity index 91% rename from src/effectivejava/chapter8/item55/Max.java rename to src/main/java/effectivejava/chapter8/item55/Max.java index 42f6181e..f772c2b3 100644 --- a/src/effectivejava/chapter8/item55/Max.java +++ b/src/main/java/effectivejava/chapter8/item55/Max.java @@ -1,6 +1,10 @@ package effectivejava.chapter8.item55; -import java.util.*; +import java.util.Arrays; +import java.util.Collection; +import java.util.Comparator; +import java.util.List; +import java.util.Optional; // Optionals (P. 248) OK (Checked) public class Max { diff --git a/src/effectivejava/chapter8/item55/ParentPid.java b/src/main/java/effectivejava/chapter8/item55/ParentPid.java similarity index 85% rename from src/effectivejava/chapter8/item55/ParentPid.java rename to src/main/java/effectivejava/chapter8/item55/ParentPid.java index f2c9054a..f6d94144 100644 --- a/src/effectivejava/chapter8/item55/ParentPid.java +++ b/src/main/java/effectivejava/chapter8/item55/ParentPid.java @@ -12,6 +12,6 @@ public static void main(String[] args) { String.valueOf(parentProcess.get().pid()) : "N/A")); System.out.println("Parent PID: " + - ph.parent().map(h -> String.valueOf(h.pid())).orElse("N/A")); + ph.parent().map(h -> String.valueOf(h.pid())).orElse("N/A")); } } diff --git a/src/effectivejava/chapter9/item58/Card.java b/src/main/java/effectivejava/chapter9/item58/Card.java similarity index 68% rename from src/effectivejava/chapter9/item58/Card.java rename to src/main/java/effectivejava/chapter9/item58/Card.java index a982bd76..98a0ee87 100644 --- a/src/effectivejava/chapter9/item58/Card.java +++ b/src/main/java/effectivejava/chapter9/item58/Card.java @@ -1,30 +1,41 @@ package effectivejava.chapter9.item58; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; public class Card { private final Suit suit; private final Rank rank; // 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 } + enum Suit { + CLUB, DIAMOND, HEART, SPADE + } + + enum Rank { + ACE, DEUCE, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, + NINE, TEN, JACK, QUEEN, KING + } static Collection suits = Arrays.asList(Suit.values()); static Collection ranks = Arrays.asList(Rank.values()); - Card(Suit suit, Rank rank ) { + Card(Suit suit, Rank rank) { this.suit = suit; this.rank = rank; } public static void main(String[] args) { List deck = new ArrayList<>(); - - for (Iterator i = suits.iterator(); i.hasNext(); ) - for (Iterator j = ranks.iterator(); j.hasNext(); ) + + for (Iterator i = suits.iterator(); i.hasNext(); ) { + for (Iterator j = ranks.iterator(); j.hasNext(); ) { deck.add(new Card(i.next(), j.next())); + } + } // // Preferred idiom for nested iteration on collections and arrays // for (Suit suit : suits) diff --git a/src/effectivejava/chapter9/item58/DiceRolls.java b/src/main/java/effectivejava/chapter9/item58/DiceRolls.java similarity index 57% rename from src/effectivejava/chapter9/item58/DiceRolls.java rename to src/main/java/effectivejava/chapter9/item58/DiceRolls.java index 760084ee..6ff7770d 100644 --- a/src/effectivejava/chapter9/item58/DiceRolls.java +++ b/src/main/java/effectivejava/chapter9/item58/DiceRolls.java @@ -1,22 +1,29 @@ package effectivejava.chapter9.item58; -import java.util.*; + +import java.util.Collection; +import java.util.EnumSet; +import java.util.Iterator; // Same bug as NestIteration.java (but different symptom)!! - Page 213 public class DiceRolls { - enum Face { ONE, TWO, THREE, FOUR, FIVE, SIX } + enum Face {ONE, TWO, THREE, FOUR, FIVE, SIX} public static void main(String[] args) { // Same bug, different symptom! Collection faces = EnumSet.allOf(Face.class); - for (Iterator i = faces.iterator(); i.hasNext(); ) - for (Iterator j = faces.iterator(); j.hasNext(); ) - System.out.println(i.next() + " " + j.next()); + for (Face face : faces) { + for (Iterator j = faces.iterator(); j.hasNext(); ) { + System.out.println(face + " " + j.next()); + } + } System.out.println("***************************"); - for (Face f1 : faces) - for (Face f2 : faces) + for (Face f1 : faces) { + for (Face f2 : faces) { System.out.println(f1 + " " + f2); + } + } } } diff --git a/src/effectivejava/chapter9/item59/Curl.java b/src/main/java/effectivejava/chapter9/item59/Curl.java similarity index 87% rename from src/effectivejava/chapter9/item59/Curl.java rename to src/main/java/effectivejava/chapter9/item59/Curl.java index 6bbea7ff..fba5d5e1 100644 --- a/src/effectivejava/chapter9/item59/Curl.java +++ b/src/main/java/effectivejava/chapter9/item59/Curl.java @@ -7,6 +7,8 @@ // Printing the contents of a URL with transferTo, added in Java 9 (Page 269) public class Curl { public static void main(String[] args) throws IOException { + + args = new String[] {"http://www.baidu.com"}; try (InputStream in = new URL(args[0]).openStream()) { in.transferTo(System.out); } diff --git a/src/effectivejava/chapter9/item59/RandomBug.java b/src/main/java/effectivejava/chapter9/item59/RandomBug.java similarity index 77% rename from src/effectivejava/chapter9/item59/RandomBug.java rename to src/main/java/effectivejava/chapter9/item59/RandomBug.java index 966659d7..cb095215 100644 --- a/src/effectivejava/chapter9/item59/RandomBug.java +++ b/src/main/java/effectivejava/chapter9/item59/RandomBug.java @@ -1,5 +1,6 @@ package effectivejava.chapter9.item59; -import java.util.*; + +import java.util.Random; // Random number generation is hard! - Page 215 public class RandomBug { @@ -13,9 +14,11 @@ static int random(int n) { public static void main(String[] args) { int n = 2 * (Integer.MAX_VALUE / 3); int low = 0; - for (int i = 0; i < 1000000; i++) - if (random(n) < n/2) + for (int i = 0; i < 1000000; i++) { + if (random(n) < n / 2) { low++; + } + } System.out.println(low); } } diff --git a/src/effectivejava/chapter9/item60/BigDecimalChange.java b/src/main/java/effectivejava/chapter9/item60/BigDecimalChange.java similarity index 79% rename from src/effectivejava/chapter9/item60/BigDecimalChange.java rename to src/main/java/effectivejava/chapter9/item60/BigDecimalChange.java index cfff6af1..8562977e 100644 --- a/src/effectivejava/chapter9/item60/BigDecimalChange.java +++ b/src/main/java/effectivejava/chapter9/item60/BigDecimalChange.java @@ -8,9 +8,7 @@ public static void main(String[] args) { int itemsBought = 0; BigDecimal funds = new BigDecimal("1.00"); - for (BigDecimal price = TEN_CENTS; - funds.compareTo(price) >= 0; - price = price.add(TEN_CENTS)) { + for (BigDecimal price = TEN_CENTS; funds.compareTo(price) >= 0; price = price.add(TEN_CENTS)) { funds = funds.subtract(price); itemsBought++; } diff --git a/src/effectivejava/chapter9/item60/Change.java b/src/main/java/effectivejava/chapter9/item60/Change.java similarity index 100% rename from src/effectivejava/chapter9/item60/Change.java rename to src/main/java/effectivejava/chapter9/item60/Change.java diff --git a/src/effectivejava/chapter9/item60/IntChange.java b/src/main/java/effectivejava/chapter9/item60/IntChange.java similarity index 100% rename from src/effectivejava/chapter9/item60/IntChange.java rename to src/main/java/effectivejava/chapter9/item60/IntChange.java diff --git a/src/main/java/effectivejava/chapter9/item61/BrokenComparator.java b/src/main/java/effectivejava/chapter9/item61/BrokenComparator.java new file mode 100644 index 00000000..291125b4 --- /dev/null +++ b/src/main/java/effectivejava/chapter9/item61/BrokenComparator.java @@ -0,0 +1,21 @@ +package effectivejava.chapter9.item61; + +import java.util.Comparator; + +// Broken comparator - can you spot the flaw? - Page 273 +public class BrokenComparator { + public static void main(String[] args) { + + Comparator naturalOrder = + (i, j) -> (i < j) ? -1 : (i == j ? 0 : 1); + + // Fixed Comparator - Page 274 +// Comparator naturalOrder = (iBoxed, jBoxed) -> { +// int i = iBoxed, j = jBoxed; // Auto-unboxing +// return i < j ? -1 : (i == j ? 0 : 1); +// }; + + int result = naturalOrder.compare(new Integer(42), new Integer(42)); + System.out.println(result); + } +} diff --git a/src/effectivejava/chapter9/item61/Unbelievable.java b/src/main/java/effectivejava/chapter9/item61/Unbelievable.java similarity index 72% rename from src/effectivejava/chapter9/item61/Unbelievable.java rename to src/main/java/effectivejava/chapter9/item61/Unbelievable.java index 0e0803e0..98103cb7 100644 --- a/src/effectivejava/chapter9/item61/Unbelievable.java +++ b/src/main/java/effectivejava/chapter9/item61/Unbelievable.java @@ -2,10 +2,12 @@ // What does this program do? - Page 274 public class Unbelievable { - static Integer i; + // static Integer i; + static int i; public static void main(String[] args) { - if (i == 42) + if (i == 42) { System.out.println("Unbelievable"); + } } } \ No newline at end of file diff --git a/src/effectivejava/chapter9/item65/ReflectiveInstantiation.java b/src/main/java/effectivejava/chapter9/item65/ReflectiveInstantiation.java similarity index 100% rename from src/effectivejava/chapter9/item65/ReflectiveInstantiation.java rename to src/main/java/effectivejava/chapter9/item65/ReflectiveInstantiation.java diff --git a/src/main/resources/log4j.properties b/src/main/resources/log4j.properties new file mode 100644 index 00000000..19420b0c --- /dev/null +++ b/src/main/resources/log4j.properties @@ -0,0 +1,12 @@ +#设置日志记录到控制台的方式 +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.err +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n +#设置日志记录到文件的方式 +log4j.appender.file=org.apache.log4j.FileAppender +log4j.appender.file.File=bookExample.log +log4j.appender.file.layout=org.apache.log4j.PatternLayout +log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n +#日志输出的级别(error > warn> info> debug> trace),以及配置记录方案 +log4j.rootLogger=info, stdout, file \ No newline at end of file diff --git a/src/main/src.txt b/src/main/src.txt new file mode 100644 index 00000000..274c0052 --- /dev/null +++ b/src/main/src.txt @@ -0,0 +1 @@ +1234 \ No newline at end of file