Effective Java (3rd Edition)

Author: Joshua Bloch
4.0
This Year Stack Overflow 3
This Month Reddit 2

About This Book

The Definitive Guide to Java Platform Best Practices—Updated for Java 9

Java has changed dramatically since the previous edition of Effective Java was published shortly after the release of Java 6. This Jolt award-winning classic has now been thoroughly updated to take full advantage of the latest language and library features. The support in modern Java for multiple paradigms increases the need for specific best-practices advice, and this book delivers.

As in previous editions, each chapter of Effective Java, Third Edition, consists of several “items,” each presented in the form of a short, stand-alone essay that provides specific advice, insight into Java platform subtleties, and updated code examples. The comprehensive descriptions and explanations for each item illuminate what to do, what not to do, and why.

The third edition covers language and library features added in Java 7, 8, and 9, including the functional programming constructs that were added to its object-oriented roots. Many new items have been added, including a chapter devoted to lambdas and streams.

New coverage includes

  • Functional interfaces, lambda expressions, method references, and streams
  • Default and static methods in interfaces
  • Type inference, including the diamond operator for generic types
  • The @SafeVarargs annotation
  • The try-with-resources statement
  • New library features such as the Optional<T> interface, java.time, and the convenience factory methods for collections

Comments

by slagathor2094   2019-07-21

* https://www.amazon.com/Effective-Java-Joshua-Bloch/dp/0134685997/ref=sr_1_1?keywords=effective+java&qid=1556330445&s=gateway&sr=8-1

by OffbeatDrizzle   2019-07-21

Yeah, or if not just play around on your own with it for a weekend, it's pretty simple to pick up.

Something else I'd add to that list is dependency injection (which again might be covered under MVC-frameworks if they tell you about Spring).

Also, this is a useful tool for getting to grips with design patterns, and I can't recommend this book enough

by anonymous   2019-01-13

Try to follow SOLID principles, from your code focus on Dependency Inversion Principle: Try to depend on abstractions (for example interface Database) and not your current implementation of Database.

I suppose that you should have some enums as unit type for Unit, I suppose you have different kind of Units. I suppose Unit should be abstract or even an interface because always you should have an specific unit (soldier, tank, ...), each kind of Unit should implement some kind of interface with actions (methods) as move, attack. Is not the same to move a soldier than to move a tank.

FileOfUnits.game as other configuration values that you will have I would use a configuration.properties file

Do not forget to test, TDD will do your classes easier to test and you will understand what you want to do before than implementing It.

Use some Control Version and commit/push with useful comments, will be easier to see why you have done some changes, in some days you will not remember why you have written these lines.

I recommend you to read and check in the following order the books: Effective Java and Clean Code

by anonymous   2019-01-13

The comments on the question are right: if you only access value within the synchronized method, then you don't need it to be volatile as well. However, in some cases, you may be able to improve performance with double-checked locking.

public final class Lazy<T> {

  private final Supplier<? extends T> initializer;
  private volatile T value;

  public Lazy(Supplier<? extends T> initializer) {
    this.initializer = initializer;
  }

  public T get() {
    T result = this.value;
    if (result == null) {
      synchronized (this) {
        result = this.value;
        if (result == null) {
          this.value = result = this.initializer.get();
        }
      }
    }
    return result;
  }

}

This code is based on some examples shown in Effective Java and Java Concurrency in Practice. Note that this code checks twice to see if result is null, once outside the synchronized block, and once inside. The advantage to this is that you won't need to synchronize if the value already exists. Note that with this strategy, value must be volatile because it is being accessed outside of the synchronized block.

by anonymous   2019-01-13

Rectification on the checked answer:

The ResultSet is not a data mapper, from whose link we can easily figure out that the concept data mapper was coined in the context of enterprise application architecture in 2003. Whereas the ResultSet already existed in the late 1990s. One can search for the keyword "since", by means of which one can infer that the earliest version when new features were added is since 1.2(in 1998. Refer to Java version history), meaning most of the old features such as those getters are already in this class before 1998

Class list of JDK 1.1.8 is here, where there is already ResultSet

Moreover, from the aspect of DriverManager, Connection and Driver, JDBC is not only an application of static factory method but more precisely a standard application of service provider framework, a design pattern introduced in Item 1: consider static factory methods instead of constructors in the book Effective Java:

  • Connection is the service interface
  • DriverManager.registerDriver is the provider registration API
  • DriverManager.getConnection is the service access API
  • java.sql.Driver is the service provider interface
by anonymous   2019-01-13

It's up to your use-case, as you have already implied. Making your components immutable brings many advantages such as better encapsulation, thread safety, avoiding having invalid state etc.. Of course, in this way you implement a performance hit. But someone with great experience wrote a chapter about this, which I can only recommend:

Effective Java -

Item 50: Make defensive copies when needed.

There he recommends:

You must program defensively, with the assumption that clients of your class will do their best to destroy its invariants.

and also:

In summary, if a class has mutable components that it gets from or returns to its clients, the class must defensively copy these components. If the cost of copy would be prohibitive and the class trusts its clients not to modify the components inappropriately, then the defensive copy may be replaced by documentation outlining the client's responsibility not to modify the affected components.

by anonymous   2019-01-13

What is a better approach in case of consistency?

  1. Make all child constructors private.
  2. Introduce static factory methods.

    ListBubbleSort.withList(List<E> list)
    ListBubbleSort.withComparator(Comparator<E> comparator)
    
  3. Make a call to a proper super constructor. Don't pass any nulls.

    public static <E> ListBubbleSort withList(List<E> list) {
        return new ListBubbleSort(list);
    }
    
    private ListBubbleSort(List<E>) {
        super(list);
    }
    
    protected ListSortierer(List<E>) {
        // initialise only the list field
        this.origin = list;
    }
    
  4. Don't use Optional as a field.

    this.original = Optional.ofNullable(li);

  5. Consider the Builder Pattern if you have 3+ parameters.

Handle missing values in the abstract superclass or in the subclass?

A constructor is supposed to provide initial values. You aren't passing initial values, you are just indicating their absence.

By default, null is the initial value for reference types. So, there is no need to reassign a field if the value for it hasn't been given.

Does it make a difference regarding instantiation or is it just a matter of opinion?

Readability, maintenance.


I would recommend reading Effective Java by Joshua Bloch:

Creating and Destroying Objects

  • Item 1: Consider static factory methods instead of constructors
  • Item 2: Consider a builder when faced with many constructor parameters
by anonymous   2019-01-13

Item 10: Obey the general contract when overriding equals

According to Effective Java, Overriding the equals method seems simple, but there are many ways to get it wrong, and consequences can be dire. The easiest way to avoid problems is not to override the equals method, in which case each instance of the class is equal only to itself. This is the right thing to do if any of the following conditions apply:

  • Each instance of the class is inherently unique. This is true for classes such as Thread that represent active entities rather than values. The equals implementation provided by Object has exactly the right behavior for these classes.

  • There is no need for the class to provide a “logical equality” test. For example, java.util.regex.Pattern could have overridden equals to check whether two Pattern instances represented exactly the same regular expression, but the designers didn’t think that clients would need or want this functionality. Under these circumstances, the equals implementation inherited from Object is ideal.

  • A superclass has already overridden equals, and the superclass behavior is appropriate for this class. For example, most Set implementations inherit their equals implementation from AbstractSet, List implementations from AbstractList, and Map implementations from AbstractMap.

  • The class is private or package-private, and you are certain that its equals method will never be invoked. If you are extremely risk-averse, you can override the equals method to ensure that it isn’t invoked accidentally:

The equals method implements an equivalence relation. It has these properties:

  • Reflexive: For any non-null reference value x, x.equals(x) must return true.

  • Symmetric: For any non-null reference values x and y, x.equals(y) must return true if and only if y.equals(x) returns true.

  • Transitive: For any non-null reference values x, y, z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) must return true.

  • Consistent: For any non-null reference values x and y, multiple invocations of x.equals(y) must consistently return true or consistently return false, provided no information used in equals comparisons is modified.

  • For any non-null reference value x, x.equals(null) must return false.

Here’s a recipe for a high-quality equals method:

  1. Use the == operator to check if the argument is a reference to this object. If so, return true. This is just a performance optimization but one that is worth doing if the comparison is potentially expensive.

  2. Use the instanceof operator to check if the argument has the correct type. If not, return false. Typically, the correct type is the class in which the method occurs. Occasionally, it is some interface implemented by this class. Use an interface if the class implements an interface that refines the equals contract to permit comparisons across classes that implement the interface. Collection interfaces such as Set, List, Map, and Map.Entry have this property.

  3. Cast the argument to the correct type. Because this cast was preceded by an instanceof test, it is guaranteed to succeed.

  4. For each “significant” field in the class, check if that field of the argument matches the corresponding field of this object. If all these tests succeed, return true; otherwise, return false. If the type in Step 2 is an interface, you must access the argument’s fields via interface methods; if the type is a class, you may be able to access the fields directly, depending on their accessibility.

  5. For primitive fields whose type is not float or double, use the == operator for comparisons; for object reference fields, call the equals method recursively; for float fields, use the static Float.compare(float, float) method; and for double fields, use Double.compare(double, double). The special treatment of float and double fields is made necessary by the existence of Float.NaN, -0.0f and the analogous double values; While you could compare float and double fields with the static methods Float.equals and Double.equals, this would entail autoboxing on every comparison, which would have poor performance. For array fields, apply these guidelines to each element. If every element in an array field is significant, use one of the Arrays.equals methods.

  6. Some object reference fields may legitimately contain null. To avoid the possibility of a NullPointerException, check such fields for equality using the static method Objects.equals(Object, Object).

    // Class with a typical equals method
    
    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");
    
        }
    
        private static short rangeCheck(int val, int max, String arg) {
    
            if (val < 0 || val > max)
    
               throw new IllegalArgumentException(arg + ": " + val);
    
            return (short) val;
    
        }
    
        @Override public boolean equals(Object o) {
            if (o == this)
                return true;
            if (!(o instanceof PhoneNumber))
                return false;
            PhoneNumber pn = (PhoneNumber)o;
            return pn.lineNum == lineNum && pn.prefix == prefix
                    && pn.areaCode == areaCode;
        }
        ... // Remainder omitted
    
    }
    
by Styrofoam--Boots   2018-11-10

Effective Java by Joshua Bloch

Written by someone who worked directly on the language's development. :)

by Mothulor   2018-11-10

Out of all the Java books I've read over the past 20 years, these probably stuck with me the most:

Edit: Apparently there's a second edition of the refactoring book: [https://toptalkedbooks.com/amzn/0134757599)

by mr_grieves   2018-11-10

Be hungry for and appreciative of feedback.

Get code reviews early and often.

Make small changes with accompanying unit tests.

Favor readability over clever tricks.

Work your way through Effective Java: https://toptalkedbooks.com/amzn/0134685997

Work your way through Concurrency In Practice: https://toptalkedbooks.com/amzn/0321349601

Have fun and keep learning! :)

by anonymous   2018-05-09

I don't think there is.

That said, you should think twice before throwing a checked exception. The standard usage for checked exceptions is to signal abnormal conditions that are out of the caller's control, such as:

  • trying to open a non-existent file
  • trying to use a failed/dropped network connection

The rationale being that if the caller can prevent the abnormal condition, it shouldn't be forced to handle it.

You can find more info in the classic Effective Java book (the 3rd edition just came out, btw), especially Item 71 ("Avoid unnecessary use of checked exceptions").

by anonymous   2018-03-19

It's rather a design matter and depends on your architecture.

If you have classes with static factory methods, why should you add unnecessary constructors breaking the design just to fit a DI framework?

It's inflexible, thus Spring supports both ways.


Excerpt from Joshua Bloch “Effective Java”:

Item 1: Consider static factory methods instead of constructors.

Static factory methods advantages:

  • They have names.
  • They are not required to create a new object each time they are invoked.
  • They can return an object of any subtype of their return type.
  • They reduce verbosity of creating parameterized type instances.

Static factory methods disadvantages:

  • When providing only static factory methods, classes without public or protected constructors cannot be subclassed.
  • They are not readily distinguishable from other static methods
by anonymous   2018-03-19
? extends HasWord

means "A class/interface that extends HasWord." In other words, HasWord itself or any of its children... basically anything that would work with instanceof HasWord plus null.

In more technical terms, ? extends HasWord is a bounded wildcard, covered in Item 31 of Effective Java 3rd Edition, starting on page 139. The same chapter from the 2nd Edition is available online as a PDF; the part on bounded wildcards is Item 28 starting on page 134.

Update: PDF link was updated since Oracle removed it a while back. It now points to the copy hosted by the Queen Mary University of London's School of Electronic Engineering and Computer Science.

Update 2: Lets go into a bit more detail as to why you'd want to use wildcards.

If you declare a method whose signature expect you to pass in List<HasWord>, then the only thing you can pass in is a List<HasWord>.

However, if said signature was List<? extends HasWord> then you could pass in a List<ChildOfHasWord> instead.

Note that there is a subtle difference between List<? extends HasWord> and List<? super HasWord>. As Joshua Bloch put it: PECS = producer-extends, consumer-super.

What this means is that if you are passing in a collection that your method pulls data out from (i.e. the collection is producing elements for your method to use), you should use extends. If you're passing in a collection that your method adds data to (i.e. the collection is consuming elements your method creates), it should use super.

This may sound confusing. However, you can see it in List's sort command (which is just a shortcut to the two-arg version of Collections.sort). Instead of taking a Comparator<T>, it actually takes a Comparator<? super T>. In this case, the Comparator is consuming the elements of the List in order to reorder the List itself.

by anonymous   2018-03-19

Writing wrapper classes for every single parameter, just to ensure that someone doesn't make confusion about the order of parameters sounds pretty extreme, and it is cumbersome to use.

If clientCode or dataVersion can fit into smaller datatypes such as byte or short, you can use that for distinction. If some of these values have a specified value range (e.g. from 1 to 100.000), use a compile-time check within a method and throw an exception if the supplied value doesn't fit (which can happen in case when the caller misplaced parameters).

In case that you add more int parameters, your concern becomes more justified. In that case write only a single wrapper class that will hold all parameters:

public class Input {
    private int clientCode;
    private int version;
    //other parameters
    ..
    // getters and setters
}

By using explicit getters and setters, you are forcing caller to take care about the supplied values. Bonus - you can add default values to some of the parameters, if needed. Method signature is now int generateId(Input input).

This is a good practice documented in Joshua Bloch's Effective Java.

by m0ck   2017-12-11
Effective Java, 3rd edition is coming 28th of December!

https://www.amazon.co.uk/Effective-Java-Joshua-Bloch/dp/0134...

by anonymous   2017-11-20
You'll learn more about the concept from this Wikipedia article: https://en.wikipedia.org/wiki/Immutable_object and from reading [Effective Java](https://www.amazon.com/Effective-Java-3rd-Joshua-Bloch/dp/0134685997/)