Effective Java (2nd Edition)

Author: Joshua Bloch
4.4
All Stack Overflow 213
This Year Stack Overflow 16
This Month Stack Overflow 1

Effective Java (2nd Edition)

4.4

Review Date:

Comments

by Jon Skeet   2019-01-13

I usually go with something like the implementation given in Josh Bloch's fabulous Effective Java. It's fast and creates a pretty good hash which is unlikely to cause collisions. Pick two different prime numbers, e.g. 17 and 23, and do:

public override int GetHashCode()
{
    unchecked // Overflow is fine, just wrap
    {
        int hash = 17;
        // Suitable nullity checks etc, of course :)
        hash = hash * 23 + field1.GetHashCode();
        hash = hash * 23 + field2.GetHashCode();
        hash = hash * 23 + field3.GetHashCode();
        return hash;
    }
}

As noted in comments, you may find it's better to pick a large prime to multiply by instead. Apparently 486187739 is good... and although most examples I've seen with small numbers tend to use primes, there are at least similar algorithms where non-prime numbers are often used. In the not-quite-FNV example later, for example, I've used numbers which apparently work well - but the initial value isn't a prime. (The multiplication constant is prime though. I don't know quite how important that is.)

This is better than the common practice of XORing hashcodes for two main reasons. Suppose we have a type with two int fields:

XorHash(x, x) == XorHash(y, y) == 0 for all x, y
XorHash(x, y) == XorHash(y, x) for all x, y

By the way, the earlier algorithm is the one currently used by the C# compiler for anonymous types.

This page gives quite a few options. I think for most cases the above is "good enough" and it's incredibly easy to remember and get right. The FNV alternative is similarly simple, but uses different constants and XOR instead of ADD as a combining operation. It looks something like the code below, but the normal FNV algorithm operates on individual bytes, so this would require modifying to perform one iteration per byte, instead of per 32-bit hash value. FNV is also designed for variable lengths of data, whereas the way we're using it here is always for the same number of field values. Comments on this answer suggest that the code here doesn't actually work as well (in the sample case tested) as the addition approach above.

// Note: Not quite FNV!
public override int GetHashCode()
{
    unchecked // Overflow is fine, just wrap
    {
        int hash = (int) 2166136261;
        // Suitable nullity checks etc, of course :)
        hash = (hash * 16777619) ^ field1.GetHashCode();
        hash = (hash * 16777619) ^ field2.GetHashCode();
        hash = (hash * 16777619) ^ field3.GetHashCode();
        return hash;
    }
}

Note that one thing to be aware of is that ideally you should prevent your equality-sensitive (and thus hashcode-sensitive) state from changing after adding it to a collection that depends on the hash code.

As per the documentation:

You can override GetHashCode for immutable reference types. In general, for mutable reference types, you should override GetHashCode only if:

  • You can compute the hash code from fields that are not mutable; or
  • You can ensure that the hash code of a mutable object does not change while the object is contained in a collection that relies on its hash code.
by anonymous   2019-01-13

It is a common naming convention used for static factory methods.

Joshua Bloch mentions the following about the pattern and associated naming conventions in Effective Java (2nd Edition), Item 1: Consider static factory methods instead of constructors (emphasis added):

... (a) disadvantage of static factory methods is that they are not readily distinguishable from other static methods. They do not stand out in API documentation in the way that constructors do, so it can be difficult to figure out how to instantiate a class that provides static factory methods instead of constructors. The Javadoc tool may someday draw attention to static factory methods. In the meantime, you can reduce this disadvantage by drawing attention to static factories in class or interface comments, and by adhering to common naming conventions. Here are some common names for static factory methods:

  • valueOf—Returns an instance that has, loosely speaking, the same value as its parameters. Such static factories are effectively type-conversion methods.

  • of—A concise alternative to valueOf, popularized by EnumSet (Item 32).

...

So, as others have pointed out, "of" means the English word "of", and is not an abbreviation. But one of the reasons for using this convention is to make it easier to find out if a class provides a factory method because static factories don't show in a separate section in the JavaDocs (compared to constructors).

An added benefit, in my opinion, with using concisely and desciptively named static factories, is that it makes the code read like prose, which isn't the case if it's littered with new constructor calls.

by anonymous   2019-01-13

On the left hand side you're declaring the type of the variable, lst. Since lst's type is List you can only access methods of a List, even if the object lst points to is really a LinkedList. There's an inherent tradeoff between declaring a variable of a concrete type like LinkedList (access to more methods / behavior) vs. a more abstract interface (safer, better compartmentalized code).

This is a big topic, and there isn't one simple answer for when to do one vs. the other (though there's lots of advice out there about it!) - you'll need to figure out which is appropriate for your use case.

Effective Java - Item 52: Refer to objects by their interfaces is a pretty canonical citation for this issue, and as the title implies suggest preferring List rather than LinkedList.

by anonymous   2019-01-13

only let classes implement Serializable that have to be passed by value over the network.

Your professor is suggesting you minimize your use of Serializable to areas where it's strictly needed.

This is because serialization is a strong candidate for leaking implementation. Implementing Serializable shows intent of serialization (even if the object is never actually serialized), which imposes the idea that developers should take caution when modifying those classes to avoid breaking software.


Joshua Bloch covers this in his book Effective Java.

The moment you serialize an object, the class that it was instantiated from can no longer be modified without special treatment. If you modify the class, the binary representation will no longer match the objects already serialized. Thus deserialization of any objects serialized before modifying the class will fail.

If a type implements Serializable, it has the potential to be serialized. If an instance of that type was serialized, you may break code by modifying it's implementation.

Since there's no easy way of knowing for sure that an instance of a serializable type has been serialized (albeit you may not intend for objects to be serialized), developers take strong caution when modifying implementations of those types.


- This could be avoided by properly versioning your serializable types, but due to the potential of versioning a type that had no contract change (with no compile time error handling support to notify you), it's best to keep explicit versioning minimal to avoid adding excess complexity to your design.

by anonymous   2019-01-13

In Joshua Bloch's Effective Java, Item 5: "Avoid creating unnecessary objects", he posts the following code example:

public static void main(String[] args) {
    Long sum = 0L; // uses Long, not long
    for (long i = 0; i <= Integer.MAX_VALUE; i++) {
        sum += i;
    }
    System.out.println(sum);
}

and it takes 43 seconds to run. Taking the Long into the primitive brings it down to 6.8 seconds... If that's any indication why we use primitives.

The lack of native value equality is also a concern (.equals() is fairly verbose compared to ==)

for biziclop:

class Biziclop {

    public static void main(String[] args) {
        System.out.println(new Integer(5) == new Integer(5));
        System.out.println(new Integer(500) == new Integer(500));

        System.out.println(Integer.valueOf(5) == Integer.valueOf(5));
        System.out.println(Integer.valueOf(500) == Integer.valueOf(500));
    }
}

Results in:

false
false
true
false

EDIT Why does (3) return true and (4) return false?

Because they are two different objects. The 256 integers closest to zero [-128; 127] are cached by the JVM, so they return the same object for those. Beyond that range, though, they aren't cached, so a new object is created. To make things more complicated, the JLS demands that at least 256 flyweights be cached. JVM implementers may add more if they desire, meaning this could run on a system where the nearest 1024 are cached and all of them return true... #awkward

by anonymous   2019-01-13

It is very true.

Because setters are always public methods. And if you class is not final then there is issue of alien method call. Which is not thread safe i.e. it is known as escaping of this reference. So from a constructor if you are calling a method it should be final or private. Else safe initialization of object will not happen which causes many bugs in real systems.

Apart from the above we should never call public method from the constructor because if the class is intended for inheritance than Constructors must not invoke overridable methods, directly or indirectly.

If you violate this rule, program failure will result. The superclass constructor runs before the subclass constructor, so the overriding method in the subclass will be invoked before the subclass constructor has run. If the overriding method depends on any initialization performed by the subclass constructor, the method will not behave as expected.

source.

by cletus   2019-01-13

You're not trying to implement Joshua Bloch's typesafe hetereogeneous container pattern are you? Basically:

public class Favorites {
  private Map<Class<?>, Object> favorites =
    new HashMap<Class<?>, Object>();

  public <T> void setFavorite(Class<T> klass, T thing) {
    favorites.put(klass, thing);
  }

  public <T> T getFavorite(Class<T> klass) {
    return klass.cast(favorites.get(klass));
  }

  public static void main(String[] args) {
    Favorites f = new Favorites();
    f.setFavorite(String.class, "Java");
    f.setFavorite(Integer.class, 0xcafebabe);
    String s = f.getFavorite(String.class);
    int i = f.getFavorite(Integer.class);
  }
}

From Effective Java (2nd edition) and this presentation.

by anonymous   2018-03-19

I would say both NumberFormatException and MyBusinessException are useful but in different cases.

They usually appear at different levels of class hierarchy: for example NumberFormatException is a lower-level exception and you might not want to expose it at a higher level (e.g. user interface) if the user of it has no power to recover from it. In this case it is more elegant to just throw MyBusinessException and display an informative message that explains for example that something in a previous step was badly supplied or some internal processing error occurred and he/she needs to restart the process.

On the other hand, if your function is used at an intermediate-level (e.g. API) and the developer has the means to recover from the exceptional behavior, NumberFormatException is more useful, as it can be dealt with programmatically and the flow of the application might continue with minimal interruption (e.g. supply a default valid number). Alternatively, this can indicate a flaw/bug in the code that should be fixed.

For details about how to follow best practice in using exceptions, read Item 61 - Throw exceptions appropriate to the abstraction from Effective Java by Joshua Bloch.

by anonymous   2018-03-19

The book Effective Java gives two more reasons for "memory leaks":

  • Once you put object reference in Cache and forget that it's there. The reference remains in cache long before becoming irrelevant. Solution is to represent cache as a WeakHashMap
  • in an API where clients register callbacks and don't re-register them explicitly. Solution is to store only weak references to them.
by anonymous   2017-08-20

The best approach is Long.valueOf(str) as it relies on Long.valueOf(long) which uses an internal cache making it more efficient since it will reuse if needed the cached instances of Long going from -128 to 127 included.

Returns a Long instance representing the specified long value. If a new Long instance is not required, this method should generally be used in preference to the constructor Long(long), as this method is likely to yield significantly better space and time performance by caching frequently requested values. Note that unlike the corresponding method in the Integer class, this method is not required to cache values within a particular range.

Generally speaking, it is a good practice to use the static factory method valueOf(str) of a wrapper class like Integer, Boolean, Long, ... since most of them reuse instances whenever it is possible making them potentially more efficient in term of memory footprint than the corresponding parse methods or constructors.


Excerpt from Effective Java Item 1 written by Joshua Bloch:

You can often avoid creating unnecessary objects by using static factory methods (Item 1) in preference to constructors on immutable classes that provide both. For example, the static factory method Boolean.valueOf(String) is almost always preferable to the constructor Boolean(String). The constructor creates a new object each time it’s called, while the static factory method is never required to do so and won’t in practice.