Rest of Project Coin explored, advantage Java 7

Project Coin includes the following proposals that will make into Java 7.

Binary literals and underscores in literals

Strings in switch

– Simplified Varargs Method Invocation

– Improved Type Inference for Generic Instance Creation (Diamond)

– Improved Exception Handling for Java

– try-with-resources (ARM)

I have briefly touched upon try-with-resources construct in my earlier post. ARM was implemented in July and JDBC APIs were recently retrofitted to support these changes. In this installment, I will give you an overview of other Coin proposals.

Binary literals and underscores in literals

This feature is again we are trying to catch up with languages such as Ruby and Python where this is already supported.

You need to prefix the literal with 0b or 0B. Now, we can define binary literals in our code as show below.

[java]
int maxInteger = 0b01111111111111111111111111111111;// Integer.toBinaryString(2147483647)
byte nybbles = 0b00100101;// Math.pow(2, 5)+Math.pow(2, 2)+Math.pow(2, 0) = 37
[/java]

Now, this can be better represented visually using underscores, which is addressed in the supplementary proposal:

[java]
int maxInteger = 0b0111_1111_1111_1111_1111_1111_1111_1111;// Integer.toBinaryString(2147483647)
byte nybbles = 0b0010_0101;// Math.pow(2, 5)+Math.pow(2, 2)+Math.pow(2, 0) = 37
[/java]

Some more common usage of this feature,

[java]
int phoneNumber = 123_456_7890;
long creditCardNumber = 1234_5678_9012_3456L;
int socialSecurityNumber = 999_99_9999;
int hexEquivalentOfIntegerMAX = 0x7f_ff_ff_ff;// Integer.toHexString(2147483647)
int hexBytes = 0xFF_EC_DE_5E;// Integer.toHexString(-1253794)
int hexWords = 0xFFEC_DE5E;// Integer.toHexString(-1253794)
long maxLong = 0x7fff_ffff_ffff_ffffL;// Long.toHexString(9223372036854775807L)
int weirdBitfields = 0b000_10_101;// Integer.toBinaryString(21)

System.out.println("The value 10100001 in decimal is " + 0B10100001);// 161
[/java]

More advanced example (from the proposal), do you see the happy face in bitmap?

[java]
// Binary literals can be used to make a bitmap more readable:
public static final short[] HAPPY_FACE = {
(short)0b0000011111100000,
(short)0b0000100000010000,
(short)0b0001000000001000,
(short)0b0010000000000100,
(short)0b0100000000000010,
(short)0b1000011001100001,
(short)0b1000011001100001,
(short)0b1000000000000001,
(short)0b1000000000000001,
(short)0b1001000000001001,
(short)0b1000100000010001,
(short)0b0100011111100010,
(short)0b0010000000000100,
(short)0b0001000000001000,
(short)0b0000100000010000,
(short)0b0000011111100000
};

[/java]

This feature was implemented more than a year ago.

Strings in switch

We are familiar with the purpose of switch and what types are allowed in them.

A simple example from the Joe Darcy’s JavaOne Coin presentation:

[java highlight=”3″]
GregorianCalendar c = new GregorianCalendar();
int monthNameToDays(String s, int year) {
switch (s) {
case "April":
case "June":
case "September":
case "November":
return 30;
case "January":
case "March":
case "May":
case "July":
case "August":
case "December":
return 31;
case "February":
int days = 28;
days += c.isLeapYear(year) ? 1 : 0;
return days;
default:
return -1;
}
}
[/java]

Here is a more complex one with nested switch :

[java highlight=”16,18,39″]
public class SwitchTest {
private static class Member {
int id;
String type;
String category;

private Member(int id, String type, String category) {
this.id = id;
this.type = type;
this.category = category;
}
}

public static int getMemberFee(Member member) {
int fee = 50;
switch (member.type) {
case "BUSINESS":
switch (member.category) {
case "LICENSED":
case "GOVERNMENT":
case "FARMERS":
case "RANCHERS":
break;

case "NON_PROFIT":
fee = 25;
}
case "GOLD_STAR":
break;
case "EXECUTIVE":
fee = 100;
break;
}
return fee;
}

public static int getMemberDiscount(Member member) {
int discount = 5;
switch (member.type) {
case "BUSINESS":
discount = 10;
//fall through
case "GOLD_STAR":
break;
case "EXECUTIVE":
discount = 15;
break;
}
return discount;
}

public static void main(String… args) {
Member member = new Member(1234_5678_90, "BUSINESS", "NON_PROFIT");
System.out.println("$" + SwitchTest.getMemberFee(member) + " fee for " + member.category);
System.out.println(SwitchTest.getMemberDiscount(member) + "% discount for " + member.category);
}
}
[/java]

This feature was implemented almost a year ago.

Simplified Varargs Method Invocation

Before going into the details of this proposal, I would like to provide some background so it helps to understand the problem better. One of the well known restrictions introduced by Generics is its inability to create generic arrays. For example, the following code would not compile in Java:

[java highlight=”4″]
public static List<String>[] mergeLists() {
List<String> a = Arrays.asList("one", "two", "three");
List<String> b = Arrays.asList("four", "five", "six");
return new List<String>[]{a, b}; // compile-time error: generic array creation
}
[/java]

For instance, let us compile the above code using Java 6 compiler using the printflat hidden option
[java highlight=”1″ light=”true”]
javac -d /tmp -XD-printflat MergeLists.java
[/java]

The generated file in /tmp would look something like:

[java highlight=”4″]
public static List[] mergeLists() {
List a = Arrays.asList(new String[]{"one", "two", "three"});// type information is lost here
List b = Arrays.asList(new String[]{"four", "five", "six"});// type information is lost here
return List[] {a, b};// added for completion, this is illegal.
}
[/java]

As a consequence of Generics, type information is erased after compilation, making it unavailable at run time. So, types such as E, List, and List are called non-reifiable types [JLS 4.7]. Varargs are implemented as an array of objects and can hold only reifiable types.

When a programmer tries to invoke a varargs method with non-reifiable varargs type, the compiler currently generates an “unchecked” warning. This proposal moves the warning from the call site to the method declaration.

[java highlight=”5″]
static List<List<String>> listOfListOfStrings() {
List<String> a = new ArrayList<String>(), b = new ArrayList<String>(), c = new ArrayList<String>();

// Warning: [unchecked] unchecked generic array creation for varargs parameter of type List<String>[]
return Arrays.asList(a, b, c);
}
[/java]

It looks like a new annotation is being planned to support this at the declaration and varargs warnings will be revised. Callers may be able to remove @SuppressWarnings(“unchecked”) from their code once this is supported by the compiler. This support is not yet available as of build b114.

Improved Type Inference for Generic Instance Creation (Diamond)

This one is much easier of all the Coin proposals, at least in terms of simplicity and eliminates much of the Generics verbosity. Generics enforced type redundancy during declaration. For example, the traditional way (>=1.5) of declaring a Generic type is shown below.

[java highlight=”2,9,10″]
static class Library<E> {
Set<Method> methods = new HashSet<Method>();

Library(Set<Method> methods) {
this.methods = methods;
}
}

Set<Method> methods = new HashSet<Method>();
Library<Set<Method>> library = new Library<Set<Method>>(methods);
[/java]

Now, with this language support, the declaration can be simplified as shown below:

[java highlight=”2,9,10″]
static class Library<E> {
Set<Method> methods = new HashSet<>(); // saves typing

Library(Set<Method> methods) {
this.methods = methods;
}
}

Set<Method> methods = new HashSet<>(); // saves typing
Library<Set<Method>> library = new Library<>(methods); // saves typing
[/java]

While libraries such as Guava have attempted similar support for this, language level sugar is more intuitive than alternatives. This feature was implemented more than a year ago.

Improved Exception Handling for Java

Prior to Java 7, it was very cumbersome to catch multiple exception types leading to boilerplate code. This proposal addresses this concern by catching multiple exception types with a single catch clause and improves checking for rethrown exceptions.

Here is a simple class we will be using to test reflection:

[java]
public class CoinByReflection {
public int code = 10_10_2010;

public void printTheme() {
System.out.println("Making things programmers do everyday easier.");
}
}
[/java]

This pattern is noticed when working with reflective operations where we may need to handle different types of exceptions.

[java]
public void multicatch() throws ClassNotFoundException, InstantiationException, NoSuchMethodException, NoSuchFieldException, IllegalAccessException, InvocationTargetException {
try {
Class clazz = Class.forName("CoinByReflection");
Object instance = clazz.newInstance();
Field field = clazz.getField("code");
int code = field.getInt(instance);
System.out.println(code);
Method method = clazz.getMethod("printTheme");
method.invoke(instance);
} catch (ClassNotFoundException cnfe) {
log(cnfe);
throw cnfe;
} catch (InstantiationException ie) {
log(ie);
throw ie;
} catch (NoSuchMethodException nsme) {
log(nsme);
throw nsme;
} catch (NoSuchFieldException nsfe) {
log(nsfe);
throw nsfe;
} catch (IllegalAccessException iae) {
log(iae);
throw iae;
} catch (InvocationTargetException ite) {
log(ite);
throw ite;
}
}
[/java]

With this proposal, we should be able to simplify the exception handling when performing reflection with single catch.

[java highlight=”10″]
public void singlecatch() throws ClassNotFoundException, InstantiationException, NoSuchMethodException, NoSuchFieldException, IllegalAccessException, InvocationTargetException {
try {
Class clazz = Class.forName("CoinByReflection");
Object instance = clazz.newInstance();
Field field = clazz.getField("code");
int code = field.getInt(instance);
System.out.println(code);
Method method = clazz.getMethod("printTheme");
method.invoke(instance);
} catch (final ClassNotFoundException|
InstantiationException |
NoSuchMethodException |
NoSuchFieldException |
IllegalAccessException |
InvocationTargetException
e){
log(e);
throw e;
}
}
[/java]

ReflectiveOperationException, a new common super class of exceptions thrown by reflective operations was introduced to simplify this further. You can catch this exception and precisely rethrow one of the exceptions defined in the method signature.

[java highlight=”10″]
public void singlecatch() throws ClassNotFoundException, InstantiationException, NoSuchMethodException, NoSuchFieldException, IllegalAccessException, InvocationTargetException {
try {
Class clazz = Class.forName("CoinByReflection");
Object instance = clazz.newInstance();
Field field = clazz.getField("code2");
int code = field.getInt(instance);
System.out.println(code);
Method method = clazz.getMethod("printTheme");
method.invoke(instance);
} catch (final ReflectiveOperationException e){
log(e);
throw e;
}
}
[/java]

This feature was implemented in May.

Conclusion

With more than 80% of the Coin features implemented and “ready” for battle test, it is evident from the fact that these features live up to its expectations:

Making things programmers do everyday easier.

[as quoted from JavaOne Coin presentation]. Now that we have a definitive plan for Java 7, IDEs should start supporting these features as mid-2011 is not very far and play a vital role in accelerating adoption of these new syntaxes. It looks like Coin 2 will include other interesting proposals such as Collection literals, Multi-line strings, Large arrays, etc, possibly for Java 8?

Recently, NetBeans announced that it will support JDK 7 language features in its forthcoming 7.0 release and Eclipse plans to include Java 7 support in its next release 3.7 (Indigo). Intellij 9 has some support for Java 7, and I hope Intellij X brings the rest.

11 thoughts on “Rest of Project Coin explored, advantage Java 7

  1. Nice concise writeup of Project Coin.
    Are there any parts of Project Coin which you did not cover?
    What was the rationale behind mentioning when the proposal was implemented?

    Like

  2. Hi Vineet,

    Thanks for your feedback. I believe I have covered all the Coin proposals considered for Java 7. May be a one or two minor improvements could be reconsidered due to the new release date (such as Collections literals). But, I am not certain though.

    Honestly, many of the key features proposed for Java 7 is “already” implemented, in some cases they are available for more than a year or so (JSR 203, Fork/Join framework, JSR 292 are some good examples). What is really missing is the tooling support for these new language features and they are critical for developer adoption.

    I am *very* positive that Java 7 will be shipped in mid-2011 as I can see these features for real and now is the time to try our these features and report any bugs.

    In my future installments, I will be covering some of these new features/APIs in detail.

    -Arul

    Like

  3. Arul,

    Nice post. I have been following coin since its inception, and was excited to see its progression. And who doesn’t love a “healthy” debate between Neal Gafter and Reinier Zwitserloot 🙂 I am very glad that multi-catch got a second life– as I believe it was cut from the original proposed list, but re-introduced when lambdas got picked back up.

    I don’t know if you follow the lambda dev list, but there are exciting things happening there as well. Just today a new commit went into murcurial with some updated lambda semantics (lexically scoped ‘this’). I really like the lambda and lambda conversion (for SAMs, method handles, etc.) semantics that are being put into this JSR. Its unfortunate that its so late in the game.

    Steve

    Like

    1. Hi Steve,

      Thanks for your comment and nice to hear from you.

      I do follow lambda-dev and yes I enjoy the discussions over there. The updated proposal is more precise and I am excited to try out the new prototype in the coming days. I wish Lambda was made available as an experimental feature (enabled using -XX:+UnlockExperimentalVMOptions) in Java 7, like we had the G1 Garbage Collector in Java 6u14.

      Developing in Java will become more fun when we no longer need to write this form of code.
      [java]
      Collections.sort(people, new Comparator<Person>() {
      public int compare(Person x, Person y) {
      return x.getLastName().compareTo(y.getLastName());
      }
      });
      [/java]

      And, with Lambda, I couldn’t agree more :

      [java highlight=”1″]
      people.sortBy(#Person.getLastName);
      [/java]

      -Arul

      Like

  4. How about undef that works with stack variables and is only a compiler time feature? Often times in a test case I want to undef things like closed connections so I accidentally do not use them later in the method.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s