8 facts I did not know about Java

11 December 2015
coding
I found out some helpful and some surprising properties of Java 6. Did you know that to this day, Java has Go To statements? Here are eight facts about the language I was not aware of. Would you have known all of them?

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 classes are not possible per se

I did a lot of C# programming in the last months, so I was surprised to find out that you cannot define a public static class Customer in Java. This will result in a compiler error. Nevertheless, you can imitate C#'s static classes (read the MSDN article about their purpose). By making a class final and making all its constructors private , no one will be able to subclass it or create an object of it outside of the class. In fact, java.lang.Math does exactly this.

4. 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 was constructed (reference). By making it static, we ensure, that it only gets called on the first construction.

5. 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? However, the compiler will give you an error for the code we used in the section above: "The interface cannot define an initializer." The book gives the following 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");
    }
  }
}

6. 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 reading or writing 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 for 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.

7. Labelling loops for break and continue

int a = 5;
outerloop:
while (true) {
  // "continue outerloop" would jump to here
  while (a > 0) {
    a--;
    break outerloop;
  }
}
// the break jumps to this point, where a is 4.

8. 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 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 a instance of Outer
    }
  }
}
That is it. I hope you enjoyed my list. How many of those facts did you already know?

Comments