-4

When I learn guava,I found some code like this in com.google.common.hash.Hashing class:

public static HashFunction crc32c() {
    return Crc32cHolder.CRC_32_C;
}

private static final class Crc32cHolder {
    static final HashFunction CRC_32_C = new Crc32cHashFunction();
}

I want to know, why do not write like below, Is this merely the author's habit? or for other purpose?

public static HashFunction crc32c() {
    return new Crc32cHashFunction()
}
Jun
  • 5
  • 2

1 Answers1

1

Your alternative suggestion

public static HashFunction crc32c() {
    return new Crc32cHashFunction()
}

would create a new Crc32cHashFunction instance each time crc32c() is called. If there is no specific need for a new instance to be returned by each call, it is more efficient to return the same instance in each call.

Using the static final variable

static final HashFunction CRC_32_C = new Crc32cHashFunction();

is one way to achieve a single instance.

As to why the HashFunction instance is a member of the nested class Crc32cHolder (as opposed to being a member of the outer class), the motivation is probably lazy evaluation - only at the first time the crc32c() method is called, the Crc32cHolder class would be initialized and the Crc32cHashFunction instance would be created. Thus, if that method is never called, the Crc32cHashFunction would never be created (assuming there is no other access to the Crc32cHolder class).

Eran
  • 387,369
  • 54
  • 702
  • 768
  • And the lazy loading works because `crc32c` (and presumably the whole class it is contained in) only talks about the abstract `HashFunction` in their signature, so that the concrete `Crc32cHashFunction` class (and its instance holder class) does not need to be resolved unless anyone actually calls that method. – Thilo Sep 03 '17 at 10:28
  • Do you know why the singleton is not just a static field on `Crc32cHashFunction`, though? What does the extra holder indirection bring to the table? – Thilo Sep 03 '17 at 10:30
  • 1
    @Thilo I don't know the use case here (and I don't have time to dig into that code), but perhaps they don't want that static field to be initialized when `Crc32cHashFunction` class is first accessed. I don't know what other code may be using `Crc32cHashFunction` - perhaps such other code doesn't use that single instance (i.e. there are use cases in which `Crc32cHashFunction` class is initialized but you don't want to initialize that static variable). – Eran Sep 03 '17 at 10:36
  • @Thilo See how [loading from classes may be slow](https://stackoverflow.com/q/13143401/581205) (there was a bug causing it to be extremely slow, but even without it, it takes some non-negligible time) and [how it can be postponed](https://github.com/google/guava/blob/master/guava/src/com/google/common/base/CharMatcher.java#L255) (for compatibility reasons, the legacy constants causing the loading are still there). – maaartinus Sep 03 '17 at 11:47