Friday, September 2, 2016

Did You Know: It is optional to declare a throws clause in Java

I ran into an interesting aspect of Java the other day that I was heretofore unaware of. I asked my very first question on Stack Overflow about it as I was surprised I was able to Remove a Java checked exception while overriding an interface method.

Turns out the answer as to why this is allowed is quite simple. Take java.lang.Appendable as the example which defines three methods, all of which throws IOException. Since I had overridden each of these methods in MyInterface, I can remove throws IOException from each method in MyInterface because a MyInterfaceImpl will then never throw an IOException. Duh!

Here is what the calling code looks like in this newly discovered scenario:

 MyInterface mine = new MyInterfaceImpl();
 Appendable a = mine;

 // No need to try-catch for IOException when using MyInterface
 mine.append("Foo");

 // However, still need to try-catch when using Appendable
 try {
    a.append("Bar");
 } catch (IOExcpetion e) {}

Apparently, it is also optional to throw checked exceptions while directly implementing interfaces. This doesn't seem quite as useful, though, unless the calling code always references the concrete class.

I'm now thinking of where I might be able to put this golden nugget to good use (java.sql package anyone?).

Monday, August 29, 2016

Reverse Lookup of Java Enum Values

I defined an enum with a structure similar to the following code:

public enum EnumWithIntValue {  
     ZERO(0),  
     ONE(1),  
     TWO(2),  
     THREE(3),  
     FOUR(4),  
     FIVE(5);

     private final int intValue;

     private EnumWithIntValue(final int intValue) {  
          this.intValue = intValue;  
     }

     public final int getValue() {  
          return this.intValue;  
     }  
}  

I then wanted to do a reverse lookup where I pass in a primitive int value and return the corresponding enum value. This was readily accomplished by adding the following static method to EnumWithIntValue:

public static final EnumWithIntValue valueOf(final int intValueParam) {
     for (EnumWithIntValue intValueEnum : values()) {
          if (intValueEnum.intValue == intValueParam) {
               return intValueEnum;
          }
     }

     throw new IllegalArgumentException("Invalid int value parameter " + intValueParam);
}

Hold up. What on Earth does values() do? If you look at the java.lang.Enum code from the JDK it does not exist. But according to the Enum Types section of the Java Tutorials:

The compiler automatically adds some special methods when it creates an enum. For example, they have a static values method that returns an array containing all of the values of the enum in the order they are declared. This method is commonly used in combination with the for-each construct to iterate over the values of an enum type.

Ok all of that makes sense (sort of). However, what does values() do every time it is called? Or to put it another way, is values() giving me a reference to the same array each time it is called or is it cloning the encapsulated array and giving me a copy each time? Let's find out:

public static void main(final String[] args) {
     EnumWithIntValue[] array = values();

     System.out.println(array);

     array = values();

     System.out.println(array);
}

Well lookie here:

[Labc.test.EnumWithIntValue;@322ba3e4
[Labc.test.EnumWithIntValue;@4f14e777

Great, so each call to values() is obviously cloning the encapsulated array which is no good from a performance perspective. Of course the JDK is more worried about giving away the internal array reference which can lead to the possibility of someone altering said array which is also a big no-no. But for the purpose of my valueOf() method, that array is only used within my enum.

Therefore, let's cache the array inside the enum declaration and then update the valueOf() method to use the cached instance instead:

     // Declare the enum cache as a private constant
     private static final EnumWithIntValue[] enumValueArray = EnumWithIntValue.values();

     // Then update the values() call inside valueOf() to reference the enum cache instead
     for (EnumWithIntValue intValueEnum : enumValueArray) {
          ...
     }

And voila! A reverse enum lookup that performs as well as it looks!