Starting in JDK 9 build 54, compiler support for private interface methods have been resurrected. This was one feature that was planned for Java 8 and did not make the final cut. It is now part of JEP 213. The primary motivation for this proposal is to enable code sharing between non abstract methods in an interface.

Interface evolution was always a tricky problem to solve in earlier versions of Java. You either need to maintain multiple versions of APIs which creates a technical debt over time or brute force your clients to accommodate new methods which breaks binary compatibility. The need to enhance an interface needed support in interface themselves instead of resorting to other options. This was fulfilled by default methods in interfaces in Java 8. Taking this further, private methods come in handy when we have a reusable block of code that default methods could benefit from. Latest Intellij 14.1 builds started to support JDK 9, so lets code an interface!.

An interface now can contain these:

– constants
– method signatures
– nested types
– default methods (since 1.8)
– static methods (since 1.8)
– private methods (since 1.9)
– private static methods (since 1.9)

Some of the restrictions of private methods include:
– private methods must contain method body
– combination of modifiers not allowed : abstract and private
– private methods in an interface does not disqualify it from being a @FunctionalInterface
– annotations types cannot declare private methods
– name clash not permitted

– cannot reduce visibility of private methods

Possibly Related Posts:


Two years ago, I blogged about parallel for each construct using a very early version of lambda prototype compiler. At that time, Data Parallelism was already available in C# TPL, but Java designers were hard at work in bringing this idiom to Java.

Lambda expressions support in Java 8 is here for everyone to give it a spin. Functional touch to Collections library makes it a breeze to program in Java. you get this one-liner using Java 8 Stream API.

There are more such one-liners you can think of using parallel constructs in Java 8. Here is another teaser, send an email blast to all customers.

Streams API brings several of the LINQ as well as PLINQ awesomeness to Java Collections library. Here is an adhoc query over a collection using the new Streams API.

Check it out here for more one-liners. You may want to checkout this article that compares LINQ with Java Streams API. While, there are constraints with the Java Streams proposal, it hits the right balance and there is a pedagogical value to it as well, keeping majority Java developers happy.

Enjoy!

Possibly Related Posts:


Java 8 adds support for bulk data operations (JEP 107) in the Collections library. It is unlikely every forms of bulk data operations will be added to the retrofitted Collections framework, but the language designers are making every possible effort in accommodating general use cases of “filter/map/reduce for Java”. Libraries should make use of parallelization on multi-core platforms in order to perform massive parallelizable operations and this means literally kicking-in your cores to its fullest potential. This area of OpenJDK is undergoing heavy changes, it is possible these APIs are changed or improved before milestone 6 when JDK 8 is officially feature complete. But, they are stable enough to give it a spin today. You can grab the lambda build from here. I have been using the latest Intellij 12 preview for my hands on with the new features in Java 8. It actually supports most of the new Java 8 languauge features and intellisense rocks.

The Streams proposal is well thought of and brings the much sought after functional power to Java and you won’t regret upgrading from Java 6 -> Java 8, if you are still hanging around with Java 6 in that time frame. This one is just a preview of what is coming in Java 8.

Let us implement a method to check if a keyword list exists in a tweet. Here is one way to implement it in plain old Java.

Now, that I am taking the Functional programming course, I would like to compare it with Scala, the mature functional language on the JVM. In Scala, this can be implemented as one liners and there are couple different ways to do this, one using exists and other using the foldLeft function, although exists is my favorite as it is clean and less cryptic.

I can understand why functional programmers are more obsessed with “small is beautiful” theme and hate outright verbosity. Now that all dust has settled with Java’s once uncertain future and stalled innovation, its new steward Oracle is betting on to bring back its lost glory in round 2 and you see that happening with Java 8. Finally, the language brings freshness to Java camp in offering functional constructs to Java and make functional programming in Java a breeze. Here is a teaser:

Isn’t nice to have a one liners in Java too? Java is close, but could reduce some noise as you have to call stream() on the Collection which might seem unnecessary. Stream interface supports a fold operation very similar to Scala’s foldLeft function and implements using a similar approach as of Scala.

Now, let us take this example further, filter tweets matching keywords. This was inspired by Week 3 assignment from the “Functional Programming Principles in Scala” course which btw I am enjoying it so far. Again, you can see Java makes it a cut. I am trying to keep it not being a spoiler.


In this example, you notice that you have to use stream() as well as into() operations to get the result of stream processing. I believe this is a limitation with the iteration 2 Streams implementation which was referred as “the bun problem” that we have to live with.

Streams in Java 8 is making implementing bulk operations a no brainer. While it involves some effort in learning the new concepts, it opens up a new dimension to library developers. Thanks to JSR 335 which brings Java up to speed with other cool languages out there in the planet.

For fun, I want to toss in a new exists() API to the Stream interface so I could use it to filter on my keywords list. This can be done with the help of extension methods, another new concept in Java 8.


Basically, I am delegating the implementation to anyMatch() for simplicity as both reveal the same purpose. Here is a custom List implementation that exposes this API on the collection. This is a primitive implementation, which btw I am trying to keep this updated with the recent library changes. I hope there is a better way to do this, but the point is, it enables developers to extend the Streams framework and fill in special cases.

exists() variant of the code is shown below.


There are several new concepts in the library that requires functional mindset to fully benefit from it. You can switch these Streams to use a parallel version, by using parallel() instead of stream() on the Collection. Stream operations are classified as lazy and eager based on their implementation.
I hope to uncover some of these new concepts in the coming months. I wish function types made into Java 8, but that is different story for another day. Enjoy functional programming in Java!

I have covered Lambdas in the past and this excellent JavaZone talk by Angelika Langer should bring you up to speed with the current state of affairs with Lambdas in Java 8. You can also find Maurice Naftalin’s LambdaFAQ useful.

Lambdas in Java 8 from JavaZone on Vimeo.

Update (10/20/2012) : Updated samples to use method reference and built with the latest Lambda build 61. Clarified the bun-problem with streams proposal.
Update (11/20/2012) : Updated MyList implementation to compile with the latest API changes and much cleaner implementation.
Update (2/3/2013) : Updated code to compile with the latest lambda build 75.
Update (6/15/2013) : Updated code to compile with the latest lambda build 94.

Possibly Related Posts:


Almost a year later since publishing the original Lambda proposal, JSR 335 EG has finally decided to adopt C# style syntax for Java 8 Lambda expressions. Brian has outlined the formal model for the new C# style syntax in his mail to lambda-dev:

lambda = ArgList Arrow Body
ArgList = Identifier
| “(” Identifier [ “,” Identifier ]* “)”
| “(” Type Identifier [ “,” Type Identifier ]* “)”
Body = Expression
| “{” [ Statement “;” ]+ “}”

Last week, Maurizio has pushed an updated compiler implementation that aligns with this new C# style syntax. I basically converted the Lambda examples used in my original post which I wrote an year ago when the initial straw-man syntax was prototyped. This post is essentially a take2, that illustrates Lambda expressions with the new C# style syntax and covers the latest developments in Lambda community. Honestly speaking, I enjoyed using the new syntax as part of this exercise. Enjoy!

Lambdas are available in the form of anonymous inner classes in Java. Anonymous inner classes are a form of nested classes that has no name and exhibits the following behavior as detailed in JLS 15.9.5.

  • An anonymous class is never abstract
  • An anonymous class is always an inner class; it is never static
  • An anonymous class is always implicitly final

One common use of anonymous inner classes is to create function objects in Java on the fly. [Refer Item 21 in Effective Java 2nd Edition pg 103]

Let us look at sorting an array of strings based on its length using an anonymous Comparator instance.

        String[] teams = {"Violet", "Indigo", "Blue", "Green", "Yellow", "Orange", "Red"};
        Arrays.sort(teams, new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                return s1.length() - s2.length();
            }
        });

To create process objects, such as Runnable, Thread, or TimerTask instances.

        final ExecutorService executor = Executors.newCachedThreadPool();
        executor.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("I am Runnable");
            }
        });

Anonymous classes have many limitations as outlined in Item 22 in Effective Java 2nd Edition [pg 108]. With Lambda expressions, you should be able to rewrite these samples more concisely eliminating the bulky syntax that comes with anonymous inner classes :

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Sample1 {

  public static void main(String... args) {
    final ExecutorService executor = Executors.newCachedThreadPool();
    // assignment context
    Runnable task = () -> System.out.println("I am Runnable"); //take 1
    executor.submit(task);

    // method invocation context
    executor.submit(() -> {System.out.println("I am Runnable");}); //take 2
    executor.shutdown();
  }
}

Array sorting using a comparator with Lambda expressions is a one liner:

import java.util.Arrays;
import java.util.Comparator;

public class Sample2 {
	public static void main(String... args) {
		String[] teams = {"Violet", "Indigo", "Blue", "Green", "Yellow", "Orange", "Red"};
		final Comparator<String> c = (s1, s2) -> s1.length() - s2.length();
		Arrays.sort(teams, c); //take 1
		Arrays.sort(teams, (s1, s2) -> s1.length() - s2.length()); //take 2
	}
}

So, what next? Let us do some hands-on with these Lambdas and explore what Lambdas has to offer for Java developers. I setup the new prototype on my Windows environment following Remi’s instructions. It was fairly straight forward (all you need is Mercurial Client, Apache Ant, and JDK 7).

Here is a simple build script (build.bat) I used in Windows, that you can place in the “make” sub-directory under “langtools” :

ant -Dboot.java.home=C:\jdk1.7.0 clean build

This would create classes.jar under “dist\lib” sub-directory. You need to place this jar in your classpath when using the prototype.

You can use the following batch scripts for compiling and running your Lambda examples (tested with the JDK 7 GA release).

javac.bat

@echo off
C:\jdk1.7.0\bin\java.exe -cp classes.jar com.sun.tools.javac.Main %1

java.bat

@echo off
C:\jdk1.7.0\bin\java.exe -cp classes.jar;. %1

It is required to include classes.jar in the classpath due to runtime dependencies that are not available in the binary build. To make sure if you are running the prototype compiler, the output should show “internal” tag:

C:\jdk8-lambdas\samples>javac.bat -version
javac 1.7.0-internal

Let us look at a simple example:

public class SimpleLambda {
  interface HelloWorld {
    void greet();
  }

  {
    HelloWorld greeting = () -> System.out.println("Hello World!");//nilary Lambda expression
    greeting.greet();
  }

  public static void main(String... args) {
    new SimpleLambda();
  }
}

To compile this example:

javac.bat SimpleLambda.java

To run this example:

java.bat SimpleLambda

Voila, you ran your first lambda example successfully if you see “Hello World!” output.

Let us look at another example which uses parameterized types in this case.

public class Sample3 {
  interface Squarer<X, Y> {
    Y square(X x);
  }

  public static void main(String... args) {
    Squarer<Integer, Integer> s = (x) -> x * x;// 1-ary Lambda expression
    System.out.println(s.square(5));
  }
}

In both these examples, you notice a pattern commonly referred to as single abstract method (SAM), defined using an interface with exactly one abstract method. This is a structural property identified by the compiler and it does not take into account methods inherited from java.lang.Object (as in java.util.Comparator).

For example, Runnable, Callable, etc belongs to this category of SAM types that can be converted in the context of assignment as shown below.

final Runnable task = () -> System.out.println(“I am Runnable”);

In this code, “task” is an Runnable instance, while the lambda expression () -> … is not. Only after conversion, the target type becomes an instance of that SAM type.

Syntax – The Holy Grail of Lambda

A lambda expression is written as a parameter list, followed by the -> token, followed by an expression or a statement block. In case of single line Lambda expression, return keyword can be omitted. Block of statements are surrounded with {} and if you need to return a result, you need to specify the return keyword.

Note ‘thin’ arrow is still used (instead of ‘fat’ (=>) arrow as used in C#). This is still under discussion. I personally like ‘thin’ arrow and ‘fat’ arrow does not really help visually.

Lambdas in Java exhibit the following behavior :

  • An interface with exactly one abstract method is referred to as an functional interface (fka SAM types).
  • Lambdas are not instances of classes.
  • Lambdas can only be converted to SAM interfaces.
  • SAM types are instances of classes.
  • Lambdas are lexically scoped.

Lambda definition (excerpt from draft)

A lambda expression e is convertible-to a SAM type S if an anonymous inner class that is a subtype of S and that declares a method with the same name as S’s abstract method and a signature and return type corresponding to the lambda expressions signature and return type would be considered assignment-compatible with S.

The return type and exception types of a lambda expression are inferred by the compiler; the parameter types may be explicitly specified or they may be inferred from the assignment context.

The type of a formal parameter can be omitted, in which case the compiler will infer a type from the target type of the lambda conversion. Let us see couple examples where the types are inferred by the compiler.

public class Sample4 {

  enum Decision {
    APPROVE, DECLINE, APPROVE_REFER
  }

  interface DecisionService {
    Decision getRiskDecision(Applicant applicant);
  }

  class Applicant {
    private int score;

    public Applicant(int score) {
      this.score = score;
    }

    public int getScore() {
      return score;
    }
  }

  public void test() {
    DecisionService cs = (a) -> {
    if (a.getScore() > 700) {
      return Decision.APPROVE;
    } else if (a.getScore() > 600 && a.getScore() < 650) {
      return Decision.APPROVE_REFER;
    } else {
      return Decision.DECLINE;
    }};
    Decision decision = cs.getRiskDecision(new Applicant(800));
    System.out.println(decision.toString());
  }

  public static void main(String... args) {
    new Sample4().test();
  }
}

In line #24 above, the type of the formal parameter Applicant is inferred by the compiler.

public class Sample5 {

  class Payment {
    private int amount;

    Payment(int amount) {
      this.amount = amount;
    }

    public int getAmount() {
      return amount;
    }
  }

  interface PaymentProcessor {
    void process(Payment pmt);
  }

  public void test() {
    invokeProcessor((pmt) -> log("Processed # " + pmt.getAmount() + " at " + new Date()));
  }

  void invokeProcessor(PaymentProcessor processor) {
    processor.process(new Payment(42));
  }

  void log(String message) {
    System.out.println(message);
  }

  public static void main(String... args) {
    new Sample5().test();
  }
}

In line #20, the type of the formal parameter Payment is inferred by the compiler.

Here is the definition of SAM and non-SAM types as explained in one of the Lambda test case.

SAM types:
1. An interface that has a single abstract method
2. Having more than one distinct methods, but only one is “real”, the others are overriden public methods in Object – example:

Comparator<T>

3. Having more than one methods due to inheritance, but they have the same signature
4. Having more than one methods due to inheritance, but one of them has a subsignature of all other methods

    a) parameter types compatible
    b) return type substitutable
    c) thrown type not conflicting with the thrown clause of any other method
    d) mixed up

5. Type-dependent SAM types

non-SAM types:
6. An interface that has a single abstract method, which is also public method in Object
7. Having more than one methods due to inheritance, and none of them has a subsignature of all other methods

What has changed since then in the Lambda community?

Well, the first thing that happened in the past year was the formation of expert groups; JSR 335 for Lambda support in Java 8 and JSR 337 umbrella JSR for Java 8. Two polls were conducted in June on lambda-dev mailing list and the results mostly favored BGGA style syntax. Choosing the syntax that C# and Scala broadly share is a wise move by the JSR 335 EG. Did any one catch up with the replacement term for SAM? It is called “functional interface”, although SAM is widely popular among lambdaphiles.

Virtual extension methods approach was revised since the original strawman proposal. Brian explains this beautifully from conception to implementation in this paper Interface evolution via virtual extension methods. Virtual extension methods will be implemented as a VM feature, which makes it transparent like any other method invocation for non-Java languages. The following JVMLS talks explain the latest developments in virtual extension methods and lambda implementation strategies. I strongly encourage to watch them as it is the only source of information for people outside the JSR 335 Expert Group.


[Photo credit: http://www.lumaxart.com/]

Possibly Related Posts:


The improved varargs warnings, part of the Coin proposal finally made into the latest JDK 7 build. I believe build 123 is special as this milestone marks the completion of all the planned JSR 334 features (the head side of the Coin) scheduled for implementation in Java SE 7. So, Coin minting done? I think so. Let us get the final dose of Project Coin.

I would like to list out some key points that are worth refreshing when discussing varargs:

  • Generics are implemented by erasure and hence non-reifiable and enforces element types only at compile time.
  • Arrays are reified, which makes them enforce element types at runtime.
  • Arrays are covariant, while parameterized types are invariant.
  • Varargs are implemented as an array of objects and can hold only reifiable types.
  • Arrays when mixed with parameterized types are generally the source of unchecked warnings emitted by the compiler.

In essence, Generics and arrays (including varargs) do not play well together [Item 25: Prefer lists to arrays in Effective Java 2nd Edition Pg 119]. Whenever you invoke a varargs method, an array is created to hold the varargs parameters. If the element type of this array is not reifiable, it is likely to generate a compiler warning. On the other hand, it is not permitted to create an array whose component type is a concrete parameterized type, because it is not type safe.

Here is a simple example that shows generic array creation.

// Generic array creation is illegal - won't compile
List<List<String>> numbersInThreeLanguages = Arrays.asList(new List<String>[]{Arrays.asList("Un", "Deux", "Trois"), Arrays.asList("Uno", "Dos", "Tres"), Arrays.asList("One", "Two", "Three")});

The legal code would look like, but this would generate an unchecked warning:

//[unchecked] unchecked generic array creation for varargs parameter of type List<String>[]
    List<List<String>> numbersInThreeLanguages = Arrays.asList(Arrays.asList("Un", "Deux", "Trois"),
            Arrays.asList("Uno", "Dos", "Tres"), Arrays.asList("One", "Two", "Three"));

The warning can be suppressed at the call site as this is considered a safe invocation:

    @SuppressWarnings(value = "unchecked")
    List<List<String>> numbersInThreeLanguages = Arrays.asList(Arrays.asList("Un", "Deux", "Trois"),
            Arrays.asList("Uno", "Dos", "Tres"), Arrays.asList("One", "Two", "Three"));

These unchecked warnings issued when invoking varargs methods that are tagged as candidates for inducing heap pollution are considered harmless. Some of the widely used helper methods in JDK library produce such warnings which are useless and requires the client code to explicitly suppress them at the call site, if you hate them.

  • public static List Arrays.asList(T… a)
  • public static boolean Collections.addAll(Collection c, T… elements)
  • public static > EnumSet EnumSet.of(E first, E… rest)

The Coin varargs improvement adds a new @Documented annotation type, java.lang.SafeVararags, that can be used at the declaration site to suppress unchecked warnings for certain varargs invocations which are considered safe such as the ones listed above.

When the JDK libraries are retrofitted to take advantage of this new annotation type, client code can safely remove any SuppressWarnings annotation from the call site. For example, Arrays.asList() would carry this special annotation that reduces these warnings at the call site.

  @SafeVarargs
  public static <T> List<T> asList(T... a) {
    return new ArrayList<T>(a);
  }

In addition to this annotation type, a new mandatory compiler warning “Possible heap pollution from parameterized vararg type : {0}” is generated on declaration sites of problematic varargs methods that are able to induce contributory heap pollution. To illustrate this, let us look at Alex Miller’s generics puzzler code below.

//[unchecked] Possible heap pollution from parameterized vararg type T[]
  public static <T> T[] mergeArrays2(T[]... arrays) {
      List<T> result = new ArrayList<T>();

      for(T[] array : arrays) {
          for(T item : array) {
              result.add(item);
          }
      }
      // BROKEN: This generates a compiler warning about checking against an erased type
      return (T[])result.toArray();
  }

This code would cause a ClassCastException at runtime and the warning generated by the compiler is indeed legitimate, so this is a case where the warning should never be suppressed and should be fixed. I believe there are couple different ways to solve this puzzle (details in Alex’s blog comments), but the recommended approach is to prefer collections to arrays when designing APIs (as in Puzzle #3 in the recent installment of Java Puzzlers from Josh Bloch and Bob Lee).

The solution outlined below requires the caller to provide a hint on the return type, which is kind of ugly, but works.

  @SafeVarargs
  static <T, U extends T> T[] mergeArrays(T[] returnType, U[]... arrays) {
    Class<?> componentType = returnType.getClass().getComponentType();
    // Determine total length
    int length = 0;
    for (T[] a : arrays) {
      length += a.length;
    }
    @SuppressWarnings(value = "unchecked")
    T[] result = (T[]) Array.newInstance(componentType, length);
    int j = 0;
    for (T[] anArray : arrays) {
      for (T element : anArray) {
        result[j++] = element;
      }
    }
    return result;
  }

If you notice, the use of @SafeVarargs annotation at the declaration site is valid since we have fixed the underlying problem of creating type safe array. The unsafe casting at line#10 when reflectively creating an array instance is harmless, so we can suppress that unchecked warning too.

The client code that invokes this method using a String array and an Integer array is shown below:

    String[] s1 = new String[]{"one", "two", "three"};
    String[] s2 = new String[]{"four", "five", "six"};
    String[] s3 = new String[]{"seven", "eight", "nine"};
    String[] sHint = new String[]{};
    String[] sMerged = mergeArrays(sHint, s1, s2, s3);
    System.out.println(Arrays.toString(sMerged));
//Output: [one, two, three, four, five, six, seven, eight, nine]
    Integer[] i1 = new Integer[]{1, 2, 3};
    Integer[] i2 = new Integer[]{4, 5, 6};
    Integer[] i3 = new Integer[]{7, 8, 9};
    Integer[] iHint = new Integer[]{};
    Integer[] iMerged = mergeArrays(iHint, i1, i2, i3);
    System.out.println(Arrays.toString(iMerged));
//Output: [1, 2, 3, 4, 5, 6, 7, 8, 9]

@SafeVarargs Applicability

This annotation type is applicable to Constructor and Method types only as defined by the Target meta-annotation. Here is the specification copied from the javadoc of @SafeVarargs which clearly outlines its scope and requirements in detail.

In addition to the usage restrictions imposed by its @Target meta-annotation, compilers are required to implement additional usage restrictions on this annotation type; it is a compile-time error if a method or constructor declaration is annotated with a @SafeVarargs annotation, and either:

  • the declaration is a fixed-arity method or constructor
  • the declaration is a variable-arity method that is neither static nor final.

Compilers are encouraged to issue warnings when this annotation type is applied to a method or constructor declaration where:

  • The variable-arity parameter has a reifiable element type, which includes primitive types, Object, and String. (The unchecked warnings this annotation type suppresses already do not occur for a reifiable element type.)
  • The body of the method or constructor declaration performs potentially unsafe operations, such as an assignment to an element of the variable-arity parameter’s array that generates an unchecked warning.

Another important thing Joe clarified regarding overriding on coin-dev: “As documented in its specification, the SafeVarargs annotation is only applicable to static methods, final instance methods, and constructors; therefore, overriding does not occur. Annotation inheritance only works on classes (not methods, interfaces, or constructors) so without changing annotation inheritance, a SafeVarargs-style annotation cannot be passed through general instance methods in classes or through interfaces.”

Conclusion

I think the Coin chapter for Java 7 has come to an end. Now, what is pending is the dogfooding, which has already begun as JDK libraries are getting a dose of Coin in form of Diamond finishings. IDEs are gearing up support for these new language features. Both, NetBeans 7 Beta and IntellijIDEA 10 has a decent support for some of the Project Coin features. The ride with Project Coin has been an exciting one so far. Hope you all enjoyed exploring these cool new Java 7 features with me; why wait, mint yours today 🙂

Possibly Related Posts:


Last November, Mark Reinhold announced that Closures will be added to the Java language and six months later we had an initial prototype based on the Straw-Man proposal and last month’s update was considered a significant progress for the language in years. As mentioned in Mark’s post, “Working with parallel arrays in Java, unfortunately, requires lots of boilerplate code to solve even simple problems. Closures can eliminate that boilerplate.” In my earlier post, I discussed how Lambda expressions make Aggregate operations a breeze to work with in Java. But, we still lack parallel looping constructs such as parallel for, foreach APIs that would take advantage of the multi-core machines we have today.

In this next Lambda adventure, I will be revisiting the Parallel ForEach example discussed by Howard in his “New Control Structures for Java” post, where he explains the use of anonymous inner classes to map a function that executes in parallel and retains the order of the original map, handles exceptions and implements continue operation. Here is the anonymous inner class version of the code:

The program produces the below output:

{1=H, 2=e, 3=l, 4=l, 5=o}

Now, that we have a working Lambda prototype, this code could be modified to take advantage of Lambda expressions. Let us enable the Lambda finder option in the compiler that identifies potential candidates for converting an anonymous inner class instance to an Lambda expression. Here is the updated javac.bat used to run with the latest prototype compiler.

@echo off
C:\jdk1.7.0\bin\java.exe -cp classes.jar com.sun.tools.javac.Main -XDidentifyLambdaCandidate=true %1

Compiling Parallel.java with this hidden compiler option identifies 2 candidates for Lambda expressions.

C:\JDK7\lambda\samples&gt;javac.bat Parallel.java
Parallel.java:16: Note: This anonymous inner class creation can be turned into a lambda expression.
            return new Callable&lt;O&gt;() {
                                     ^
Parallel.java:70: Note: This anonymous inner class creation can be turned into a lambda expression.
        final ForEach&lt;Character, Integer, Character&gt; trim = new ForEach&lt;Character, Integer, Character&gt;() {
C:\JDK7\lambda\samples&gt;

Let us quickly refactor Howard’s code using Lambda expressions and here is my take.

This version does not significantly change from its anonymous counterpart, it reduces at most 10 lines of code. But, it introduces two important concepts in addition to use of Lambda expressions. Lines 6 and 13 uses the new exception transparency mechanism and Line 62 shows how lexical scoping makes Lambda expressions different from anonymous inner classes.

Exception Transparency

Exception transparency is a new feature proposed as part of the umbrella Lambda proposal. While this feature is not required to support Lambda expressions, it is useful in library implementations that require abstraction over generic exceptions. Java Generics does a decent job at abstracting over method return types and argument types, leaving abstraction over types of checked exceptions in limbo. This makes it difficult for libraries to support generic exception types in APIs. The two extreme cases where libraries usually model their exception types are :

In case of Runnable, the run() method throws nothing.

public interface Runnable {
    public abstract void run();
}

In case of Callable, the call() method throws everything.

public interface Callable<V> {
    V call() throws Exception;
}

As more and more libraries would take advantage of executing Lambda expressions as a block of code, the inability to generify thrown exception types makes this proposal a compelling use case.

A throws type parameter is a generic type parameter that is introduced with the keyword throws; throws type parameters implicitly have an upper bound of Exception (though any upper bound that is a subtype of Throwable may be explicitly specified) and can correspond to zero or more actual types that are subtypes of the upper bound.

With this support in the language, we should be able to abstract generic exception types:

	interface Block<throws E> {
		public void execute() throws E;
	}

Lexical scoping

Unlike anonymous inner classes, lambda expressions are lexically scoped. This means that code inside the Lambda body sees only what is available immediately outside the lambda expression. For instance, access to names from inherited classes/interfaces is not allowed as seen in Line #62 of our example above.

I wanted to briefly touch upon these concepts that are relevant to our discussion. Please refer to the proposal for more details.

.NET world

Let us look at how modern languages support Parallelism in their libraries. Here is an closest example using C# Task Parallel Library (TPL) (from Patterns of Parallel Programming Guide).

But this is just an attempt if someone wanted to write their own parallel foreach construct using existing C# APIs. But, this is not required. In C#, parallel constructs are available for a while now. Using the Parallel.ForEach construct in TPL, iterating all the Test records of a Student and calculate the GPA would look something like:

Fair enough, this construct is concise and abstracts all the machinery from the Client code. Are we close enough to get a similar construct in Java? I think so, we do have parallel collections library that supports parallelism using Fork-Join framework today. It looks like Doug Lea has recently revealed his plans for developing new library components for parallel operations on aggregates (collections and arrays) for JDK8 (based on proposed language support for lambdas). I believe this effort would produce these constructs in Java.

For the sake of fun, I compiled the extry166y sources with the compiler option “-XDidentifyLambdaCandidate=true”, it identified 168 candidates that can be turned into a lambda expression. Less code means more fun and you see that for real.

Update (6/11/2011) : Updated the Parallel class (Lambda version) to compile with the latest lambda prototype compiler. Abstract classes with single abstract method are no longer considered valid SAM types as per the revised rules.

Possibly Related Posts:


One of the primary uses of Lambda expressions is to implement aggregate operations that can often be parallelized using multi-core processors we have today. The computation over bulk data structures is an area where Lambda expressions provide much needed support where part of the computation is caller defined. Doug Lea’s JSR166y Concurrency interest group exactly brings these rich set of Collections that supports parallel operations to perform bulk computation over data in the Java platform.

Let us look at an aggregate operations example using a ParallelArray, that maintains a ForkJoinPool and an array in order to provide parallel aggregate operations. The jsr166y package is already included in Java 7 as part of the ForkJoin framework. The extra166y package that contains Collections supporting parallel operations is not part of the JDK yet, but you should be able to use them today as an add-on library.

import extra166y.Ops;
import extra166y.ParallelArray;
import extra166y.ParallelDoubleArray;

public class AggregateOpsExample {

    ParallelArray<Student> students;

    public AggregateOpsExample() {
        jsr166y.ForkJoinPool fjPool = new jsr166y.ForkJoinPool();
        // Create a "fictional" Student array
        Student s1 = new Student("S1", 2010, 85, 5);
        Student s2 = new Student("S2", 2010, 91, 4);
        Student s3 = new Student("S3", 2010, 95, 3);
        Student[] data = new Student[]{s1, s2, s3};
        students = ParallelArray.createFromCopy(new Student[]{s1, s2, s3}, fjPool);
    }

    public Student getStudent(int index) {
        return students.get(index);
    }

    public double getMaxSeniorGpa() {
        return students.withFilter(isSenior)
        			   .withMapping(gpaField)
        			   .max();
    }

    public ParallelDoubleArray.SummaryStatistics getSummaryStatistics() {
        return students.withFilter(isSenior)
	                   .withMapping(gpaField)
        	           .summary();
    }

    // helpers:
    static final class IsSenior implements Ops.Predicate<Student> {
        public boolean op(Student s) {
            return s.credits > 90;
        }
    }

    static final IsSenior isSenior = new IsSenior();

    static final class GpaField implements Ops.ObjectToDouble<Student> {
        public double op(Student s) {
            return s.gpa;
        }
    }

    static final GpaField gpaField = new GpaField();

    public static void main(String[] args) {
        AggregateOpsExample test = new AggregateOpsExample();
        double bestGpa = test.getMaxSeniorGpa();
        System.out.println("Best GPA : " + bestGpa);
        ParallelDoubleArray.SummaryStatistics summary = test.getSummaryStatistics();
        System.out.println("Last Best Student: " + test.getStudent(summary.indexOfMin()).name);
        System.out.println("Average GPA in class of 2010 : " + summary.average());
    }

    public class Student {
        String name;
        int graduationYear;
        int credits;
        double gpa;

        public Student(String name, int graduationYear, int credits, double gpa) {
            this.name = name;
            this.graduationYear = graduationYear;
            this.credits = credits;
            this.gpa = gpa;
        }
    }
}

In Line#10, a ForkJoinPool is created with parallelism equal to Runtime.availableProcessors(), in my case 2. Lines 24-26 and 30-32 perform aggregate operations on Students array. These operations take advantage of multi-core processors than the traditional sequential approach we used to filter and map a collection. By introducing Lambda expressions in the client code, you can remove much of the boilerplate in lines 36-50 in our code.

Let us build upon the above example to time these aggregate operations and erase some of the boilerplate using Lambda expressions.

import extra166y.Ops;
import extra166y.ParallelArray;
import extra166y.ParallelDoubleArray;

public class TimedAggregateOps {

	ParallelArray<Student> students;

	public TimedAggregateOps() {
		jsr166y.ForkJoinPool fjPool = new jsr166y.ForkJoinPool();
        // Create a "fictional" Student array
		Student s1 = new Student("S1", 2010, 85, 5);
		Student s2 = new Student("S2", 2010, 91, 4);
		Student s3 = new Student("S3", 2010, 95, 3);
		Student[] data = new Student[]{s1, s2, s3};
		students = ParallelArray.createFromCopy(new Student[]{s1, s2, s3}, fjPool);
	}

	interface Block {
		public void execute();
	}

	static void time(boolean maxGpa, Block block) throws Exception {
		long startTime = System.nanoTime();
		boolean success = true;
		try {
			block.execute();
		} catch (final Throwable ex) {
			success = false;
			throw ex;
		} finally {
			recordTiming(maxGpa, System.nanoTime() - startTime, success);
		}
	}

	static void recordTiming(boolean maxGpa, long nanoseconds,  boolean succeeded) {
		if (maxGpa) {
			System.out.println("maxGpa took " + nanoseconds + "ns and operation " + (succeeded ? "succeeded." : "failed."));
		} else {
			System.out.println("avgGpa took " + nanoseconds + "ns and operation " + (succeeded ? "succeeded." : "failed."));
		}
	}

    static final Ops.Predicate<Student> isSenior = #{s -> s.credits > 90};
    static final Ops.ObjectToDouble<Student> gpaField = #{s -> s.gpa};

    public void findMaxSeniorGpa() {
        double maxGpa = students.withFilter(isSenior)
        						.withMapping(gpaField)
        						.max();
        System.out.println("Maximum GPA : " + maxGpa);
    }

    public void findAverageGpa() {
        ParallelDoubleArray.SummaryStatistics summary = students.withFilter(isSenior)
                												.withMapping(gpaField)
                												.summary();
		double avgGpa = summary.average();
		System.out.println("Average GPA : " + avgGpa);
    }

	void test(boolean maxGpa) throws Exception {
		try {
			time(maxGpa, #{
				if (maxGpa)
					findMaxSeniorGpa();
				else
					findAverageGpa();
			});
		} catch (final Throwable t) {
			throw t;
		}
	}

	public static void main(String[] args) throws Exception {
		TimedAggregateOps tao = new TimedAggregateOps();
		tao.test(true);
		tao.test(false);
	}
}

The client code that consumes this parallel Collections library has become more concise and removes much of the boilerplate with the use of Lambda expressions. Lines 36-50 in the earlier example is reduced to Lines 44-45 in this example. When these libraries take advantage of Lambda expressions, implementations would become powerful and more efficient. For example, much of the today’s verbose APIs such as map, reduce, filter defined in ParallelArray class would benefit from executing block of code using Lambda expressions. I recommend watching Closures Cookbook JavaOne 2008 presentation from Neal Gafter.

You can run this example using the prototype compiler that supports Lambda expressions. The batch scripts used in my original post should be updated to include JSR166y libraries in classpath, which you could download from JSR-166 maintenance website.

javac.bat

@echo off
C:\jdk1.7.0\bin\java.exe -cp classes.jar;jsr166y.jar;extra166y.jar com.sun.tools.javac.Main %1

java.bat

@echo off
C:\jdk1.7.0\bin\java.exe -cp classes.jar;.;jsr166y.jar;extra166y.jar %1

Possibly Related Posts:


Recently, Brian Goetz published modified draft of the Lambda proposal. This draft is mature in terms of the direction where Lambda is heading for in the Java world and introduces some breaking changes from earlier draft to align with this direction. While there are few things that need to be sorted out, this draft is simple to understand, unlike the earlier proposals we have seen. Last week, Maurizio pushed an updated prototype that aligns with this new draft.

Lambdas (originally knows as Closures) are available in the form of anonymous inner classes in Java. Anonymous inner classes are a form of nested classes that has no name and exhibits the following behavior as detailed in JLS 15.9.5.

  • An anonymous class is never abstract
  • An anonymous class is always an inner class; it is never static
  • An anonymous class is always implicitly final

One common use of anonymous inner classes is to create function objects in Java on the fly. [Refer Item 21 in Effective Java 2nd Edition pg 103]

Let us look at sorting an array of strings based on its length using an anonymous Comparator instance.

        String[] teams = {"Violet", "Indigo", "Blue", "Green", "Yellow", "Orange", "Red"};
        Arrays.sort(teams, new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                return s1.length() - s2.length();
            }
        });

To create process objects, such as Runnable, Thread, or TimerTask instances.

        final ExecutorService executor = Executors.newCachedThreadPool();
        executor.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("Processing a short-lived asynchronous task.");
            }
        });

Anonymous classes have many limitations as outlined in Item 22 in Effective Java 2nd Edition [pg 108]. With Lambda expressions, you should be able to rewrite these samples more concisely eliminating the bulky syntax that comes with anonymous inner classes :

        final ExecutorService executor = Executors.newCachedThreadPool();
        // assignment context
        Runnable task = #{ System.out.println("Processing a short-lived asynchronous task.") }; //take1
        executor.submit(task);
        // cast target context
        task = (Runnable)#{System.out.println("Processing a short-lived asynchronous task.")}; //take 2
        executor.submit(task); 
        // method invocation context
        executor.submit((Runnable)#{System.out.println("Processing a short-lived asynchronous task.")}); //take 3

Array sorting using a comparator with Lambda expressions is a one liner:

	String[] teams = {"Violet", "Indigo", "Blue", "Green", "Yellow", "Orange", "Red"};
	final Comparator<String> c = #{s1, s2 -> s1.length() - s2.length()};
	Arrays.sort(teams, c); //take1
	Arrays.sort(teams, #{s1, s2 -> s1.length() - s2.length()}); //take 2

So, what next? Let us do some hands-on with these Lambdas and explore what Lambdas has to offer for Java developers. I setup the new prototype on my Windows environment following Remi’s instructions. It was fairly straight forward (all you need is Mercurial Client, Apache Ant, and latest JDK 7 build).

Here is a simple build script (build.bat) I used in Windows, that you can place in the “make” sub-directory under “langtools” :

ant -Dboot.java.home=C:\jdk1.7.0 clean build

This would create classes.jar under “dist\lib” sub-directory. You need to place this jar in your classpath when using the prototype.

You can use the following batch scripts for compiling and running your Lambda examples. I tested with the recent JDK 7 build (b115).

javac.bat

@echo off
C:\jdk1.7.0\bin\java.exe -cp classes.jar com.sun.tools.javac.Main %1

java.bat

@echo off
C:\jdk1.7.0\bin\java.exe -cp classes.jar;. %1

It is required to include classes.jar in the classpath due to runtime dependencies that are not available in the binary build. To make sure if you are running the prototype compiler, the output should show “internal” tag:

C:\JDK7\lambda\samples>javac.bat -version
javac 1.7.0-internal

Let us look at a simple example:

public class SimpleLambda {
	abstract class HelloWorld {
		abstract void greet();
	}
	{
		HelloWorld greeting = #{ System.out.println("Hello World!") };//nilary Lambda expression
		greeting.greet();
	}
	public static void main(String[] args) {
		new SimpleLambda();
	}
}

To compile this example:

javac.bat SimpleLambda.java

To run this example:

java.bat SimpleLambda

Voila, you ran your first lambda example successfully if you see “Hello World!” output.

Let us look at another example which uses parameterized types in this case.

	interface Squarer<X, Y> {
		Y square(X x);
	}
	{
		Squarer<Integer, Integer> s = #{ Integer x -> x * x };// 1-ary Lambda expression
		System.out.println(s.square(5));
	}

In both these examples, you notice a pattern commonly referred to as single abstract method (SAM), defined using an interface or an abstract class with exactly one abstract method. This is a structural property identified by the compiler and it does not take into account methods inherited from java.lang.Object (as in java.util.Comparator).

For example, Runnable, Callable, etc belongs to this category of SAM types that can be converted in the context of assignment as shown below.

final Runnable task = #{ System.out.println(“Processing a short-lived asynchronous task.”) };

In this code, “task” is an Runnable instance, while the lambda expression #{…} is not. Only after conversion, the target type becomes an instance of that SAM type.

Syntax – The Holy Grail of Lambda


Lambda expressions begin with ‘#’ special character and an arrow token ‘->’ is used to separate the formal parameters from the body of the Lambda. In case of single line Lambda expression, return keyword and trailing semicolon can be omitted. For nilary Lambda expression, the arrow token can be omitted.

Lambdas in Java exhibit the following behavior :

  • An interface, or abstract class, with exactly one abstract method are referred to as a SAM types.
  • Lambdas are not instances of classes.
  • Lambdas are converted to SAM types.
  • SAM types are instances of classes.
  • Lambdas are lexically scoped.

Lambda definition (excerpt from draft)

A lambda expression e is convertible-to a SAM type S if an anonymous inner class that is a subtype of S and that declares a method with the same name as S’s abstract method and a signature and return type corresponding to the lambda expressions signature and return type would be considered assignment-compatible with S.

The return type and exception types of a lambda expression are inferred by the compiler; the parameter types may be explicitly specified or they may be inferred from the assignment context.

The type of a formal parameter can be omitted, in which case the compiler will infer a type from the target type of the lambda conversion. Let us see couple examples where the types are inferred by the compiler.

	enum Decision {
	    APPROVE, DECLINE, APPROVE_REFER
	}

	abstract class DecisionService {
	    abstract Decision getRiskDecision(Applicant applicant);
	}

	class Applicant {
		private int score;
		public Applicant(int score) {
			this.score = score;
		}
		public int getScore() {
			return score;
		}
	}

	public void test() {
		DecisionService cs = #{ a ->
								if (a.getScore() > 700) {
									return Decision.APPROVE;
								} else if (a.getScore() > 600 && a.getScore() < 650) {
									return Decision.APPROVE_REFER;
								} else {
									return Decision.DECLINE;
								}
							};
		Decision decision = cs.getRiskDecision(new Applicant(800));
		System.out.println(decision.toString());
	}

In line #20 above, the type of the formal parameter Applicant is inferred by the compiler.

	class Payment {
		private int amount;
		Payment(int amount) {
			this.amount = amount;
		}
		public int getAmount() {
			return amount;
		}
	}
	interface PaymentProcessor {
		void process(Payment pmt);
	}
	{
		invokeProcessor(#{pmt -> log("Processed # " + pmt.getAmount() + " at " + new Date())});
	}
	void invokeProcessor(PaymentProcessor processor) {
		processor.process(new Payment(42));
	}

In line #14, the type of the formal parameter Payment is inferred by the compiler.

Extension Methods

One of the significant benefits of Lambdas is that it enables the development of more powerful libraries with less code and more efficiency. To enhance the core libraries to take advantage of these powerful language features without compromising backward compatibility, the concept of public defender methods was introduced. This proposal suggests adding virtual extension methods to existing interfaces allowing the use of new language features to enhance the capabilities of core libraries.

While, extension methods by itself is more useful and when combined with Lambdas, they can be powerful. The traditional way of sorting a collection.

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

With Lambdas, this can be expressed more concisely (this works with the prototype).

Collections.sort(people, #{ x, y -> x.getLastName().compareTo(y.getLastName()) });

And this still leaves room for improvement where virtual extension methods come to rescue. When core libraries are enhanced to take advantage of Lambda expressions, this can be made less verbose.

people.sortBy(#Person.getLastName);

Virtual extension methods are declared using the ‘extension’ keyword.

public interface List<T> extends Collection<T> {
	// .... The existing List methods 
  	extension void sort() default Collections.sort;
}

When Collections library is enhanced to support extensions methods, we should be able to use many of the Collections APIs directly in a collection:

List.sort();
//instead of
Collections.sort(List);

Some of these minor improvements are most sought after and makes Java less verbose and one less class to deal with.

Conclusion

I haven’t touched upon other fundamental concepts such as Exception transparency, Method references and Lexical Scoping. I will be covering them once I do some hands-on with these concepts. The prototype is still evolving around these areas and has made some good progress in catching up with this new draft. As we know, Lambdas are scheduled to go in Java 8 (in late 2012), almost six years after Closures were originally proposed in 2006. I believe there are plans to make binary builds available for all platforms, so the hassle of building from the source would no longer be required.

[Photo credit: http://www.lumaxart.com/]

Update (10/25/2010) : Omitted the use of optional trailing semicolon and return keyword in single line Lambda expressions.

Update (6/11/2011) : The definition of SAM types have changed since this post was originally written. Here is the latest definition.

SAM types:
1. An interface that has a single abstract method
2. Having more than one distinct methods, but only one is “real”, the others are overridden public methods in Object – example:

Comparator<T>

3. Having more than one methods due to inheritance, but they have the same signature
4. Having more than one methods due to inheritance, but one of them has a sub-signature of all other methods

    a) parameter types compatible
    b) return type substitutable
    c) thrown type not conflicting with the thrown clause of any other method
    d) mixed up

5. Type-dependent SAM types

non-SAM types:
6. An interface that has a single abstract method, which is also public method in Object
7. Having more than one methods due to inheritance, and none of them has a sub-signature of all other methods

With these new rules, some of the examples won’t compile. Abstract classes with single abstract method are no longer considered valid SAM types. Switching to an interface should fix these examples.

Possibly Related Posts:


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:


Try-with-resources (originally known as Automatic Resource Management) is one of the Project Coin proposals that made its way into recent JDK 7 builds. Traditionally, developers had to manually terminate any resources (Files, Database connections, etc) they use in their applications and sometimes it was painful to keep track of those things and failing to do so may have serious problems such as resource leaks which could potentially lead to application failures that are hard to debug and triage. The burden of managing resources is no more a developer’s headache as this will be natively supported in Java 7.

C# has “using” blocks and C++ destructors served a similar purpose. This is a more sought after language feature for years and Joshua Bloch brings this to real for Java developers with some syntax sugaring. While this construct looks alien to Java, I believe this is something we have to accept and move forward as this solves common programming errors. IDEs can fill this space to support intelligent code completion for ARM constructs and make it easy for developer adoption. The other disadvantage outlined in the proposal is increased coupling between the language specification and libraries. To support this feature, a class must implement a designated interface AutoCloseable to make it eligible for automatic resource management.

Let us look at the example used in the ARM proposal, copying a file involving two resources.

    public void copy(String src, String dest) throws IOException {
        InputStream in = new FileInputStream(src);
        try {
            OutputStream out = new FileOutputStream(dest);
            try {
                byte[] buf = new byte[8192];
                int n;
                while ((n = in.read(buf)) >= 0)
                    out.write(buf, 0, n);
            } finally {
                out.close();
            }
        } finally {
            in.close();
        }
    }

With the new try-with-resources construct, we should be able to rewrite the above code with much simplicity:

    public void copy(String src, String dest) throws IOException {
        try(InputStream in = new FileInputStream(src);
            OutputStream out = new FileOutputStream(dest)){
            byte[] buf = new byte[8192];
            int n;
            while ((n = in.read(buf)) >= 0)
                out.write(buf, 0, n);
        }
    }

The bloated code we use these days will become more crisp with fewer lines of code, while continuing to maintain readability.

Java APIs that involve dealing with resources are mostly retrofitted to support this new AutoCloseable interface. This feature brings heap of benefits to the JDBC world where this may prove very useful when managing database connections and its subsidiaries.

Here is the traditional way of programming in JDBC where the user has to manage JDBC resources such as ResultSet, Statement and Connection.

        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            conn = DriverManager.getConnection("jdbc:h2:mem:test", "sa", "");
            stmt = conn.createStatement();
            rs = stmt.executeQuery("SELECT * FROM INFORMATION_SCHEMA.USERS");
            while (rs.next()) {
                System.out.println(rs.getString(1));
            }
        } catch (SQLException e) {
            // handle exception
        } finally {
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                }
                rs = null;
            }
            if (stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException e) {
                }
                stmt = null;
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                }
                conn = null;
            }

        }

You guessed it right, there is so much boilerplate code that is involved here. Here is the same code with our try-with-resources construct.

        try(Connection conn = DriverManager.getConnection("jdbc:h2:mem:test", "sa", "");
            Statement stmt = conn.createStatement();
            ResultSet rs = stmt.executeQuery("SELECT * FROM INFORMATION_SCHEMA.USERS")) {// no trailing semicolon in the last line of the block containing automatic resource definition
            while (rs.next()) {
                System.out.println(rs.getString(1));
            }
        } catch (SQLException e) {
            // handle exception
        }

Wow, it is compact and powerful. JDBC support for the new try-with-resources construct will be part of JDBC 4.1 specification and the implementation is available in the recent JDK 7 build 112.

In these try-with-resources examples, an exception thrown during the lifetime of a try-with-resources statement receives priority over an exception thrown by an automatically generated close invocation. The proposal addresses automatic retention of those suppressed exceptions which are associated with the primary exception thrown during the try-with-resources statement.

The following methods are added to java.lang.Throwable to support extraction of these suppressed exceptions.

    public synchronized void addSuppressedException(Throwable exception);

    public synchronized Throwable[] getSuppressedExceptions();

You may want to go through the recent JavaOne presentation which details Project Coin features that are included in Java 7, slated for release in mid 2011.

Do you think Project Coin will become a crown jewel of Java 7, since Lambda expressions and Project Jigsaw are no longer the main contenders? In the coming days, I will be exploring many other language features that are included in Java 7 and help you decide the crown jewel of Java 7.

Keep watching this space for more Java 7 delicacies 🙂

Possibly Related Posts: