Some facts I did not know about Java

11 December 2015

I found out about some helpful and some surprising properties of Java 6 today. Did you know that to this day, Java has Go To statements? Here are some facts about the language I was not aware of.

1. % can output negative numbers

The % operator calculates the remainder of the division, which does not necessarily have to be in [0, n-1].
int positive = 23 % 7; // will be 2
int negative = -17 % 7; // will be -3

2. Java's Garbage collection finds isolated circular references

Java's GC starts from the garbage collection root. Every object that it does not reach from there is considered garbage. The main types of GC roots are (see yourkit.com):
  • Classes - they are never unloaded by the GC. Thus, their static fields cannot be unloaded either.
  • Threads - which are alive
  • Stack - local variables and method parameters
  • Used Monitors - objects used as a monitor for synchronization
  • Objects for JVM purposes

3. Static initialization blocks

public static final HashSet<String> set = new HashSet();
static {
  set.add("a");
}
This is possible. Static initialization blocks are used for initializations that cannot be done in one line. If we remove the static keyword before the block, the code would be called every time that an object of the class is constructed (source). By making it static we ensure that the block only gets executed upon the first construction.

4. Interfaces can initialize static constants as well

You probably already knew that this is possible in an interface:
static final int ID = 1234;
But did you know that you can also define a static final Hashset and populate it with values in the interface? While the compiler will give you an error for the code we used in the section above ("The interface cannot define an initializer."), there is a workaround:
public interface SomeInterface {
  static final HashSet<String> set = new HashSet<String>();
  static final Instantiator li = new Instantiator();

  static class Instantiator {
    static {
      set.add("b");
    }
  }
}
This workaround should be used only with very good reason in my opinion.

5. The correct use of volatile

If you already learned about parallel programming in Java, you probably know the synchronized keyword. But what about volatile ? Brian Goetz calls it the "Lite-version" of synchronized. Synchronized statements provide two features: mutual exclusion and visibility. The former guarantees that only one thread at a time has a certain lock. This may give him sole access to a variable, be it reading or writing. Visibility ensures that after the lock is released, the next thread works with the up-to-date versions of all locked variables. Volatile variables only provide visibility. Therefore, they should not be used in cases where
  • the writes to the volatile variable depend on its current value or
  • the volatile variable is used in a condition together with other variables.
They can, however, be used for notifying a thread from another thread by changing the value of a volatile variable. The benefits of using a volatile variable are simplicity and performance. Volatile reads are about as fast as non-volatile reads. Volatile and synchronized can also be combined to provide fast read and safe increase operations.

6. Labelling loops for break and continue

This feature should be used only with very good reason in my opinion. Here is how it would work:
int a = 5;
outerloop:
while (true) {
  // "continue outerloop" instead of "break outerloop" would jump here.
  while (a > 0) {
    a--;
    break outerloop;
  }
}
// the break jumps to this point, where a is 4.

7. The difference between inner and static nested classes

Inner classes are nested classes without the static keyword. They belong to an instance of the outer class and can therefore access the members of the instance. They cannot define static variables. In contrast, "a static nested class is behaviorally a top-level class that has been nested in another top-level class for packaging convenience" (from the Oracle Docs).
public class Outer {
  public void foo() { }

  class Inner {
    static int i = 1; // COMPILER ERROR
    // i needs to be final or an instance variable.

    void bar(){
      foo();
    }
  }

  static class StaticNested {
    static int i = 1;

    void bar(){
      foo(); // COMPILER ERROR
      // foo needs to be accessed via an instance of Outer.
    }
  }
}
That is it. I hope you enjoyed my list. How many of those facts did you already know?

Like what you read?

I don't use Google Analytics or Disqus because they require cookies. I would still like to know which posts are popular, so if you liked this post you can let me know here on the right.

You can also leave a comment if you have a GitHub account. The "Sign in" button will store the GitHub API token in a cookie.