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.

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

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

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

Some more common usage of this feature,

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

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

// 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
};

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:

    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;
        }
    }

Here is a more complex one with nested switch :

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);
    }
}

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:

    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
    }

For instance, let us compile the above code using Java 6 compiler using the printflat hidden option

javac -d /tmp -XD-printflat MergeLists.java

The generated file in /tmp would look something like:

    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.
    }

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.

    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);
    }

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.

    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);

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

    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

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:

public class CoinByReflection {
    public int code = 10_10_2010;

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

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

    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;
        }
    }

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

    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;
        }
    }

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.

    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;
        }
    }

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.

Possibly Related Posts:


8 Responses to “Rest of Project Coin explored, advantage Java 7”

  • vineetb

    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?

  • Arul

    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

  • Steve Ash

    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

    • aruld

      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.

      Collections.sort(people, new Comparator<Person>() {
          public int compare(Person x, Person y) {
              return x.getLastName().compareTo(y.getLastName());
          }
      });
      

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

      people.sortBy(#Person.getLastName);
      

      -Arul

  • Edward Capriolo

    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.

    • Arul

      Hi Edward,

      Good point. I am not sure if they would be made available in a similar fashion though.

      -Arul

Trackbacks/Pingbacks

  1.  What is coming up in JDK 7 ? | Free practice test , mock test, driving test, interview questions
  2.  Nouveautes java 7… «
  3.  Blogging at the speed of thought » Annotation type to reduce varargs warnings available in b123, Java 7 Coin minting done?