MPS making friends with JDK 8
One of the useful new features of MPS 3.2 will be its compatibility with JDK 8. Not only you will be able to run MPS on JDK 8, but MPS will also correctly handle new Java 8 syntax enhancements and let you make use of them. Read on to find out some tips.
Configuration
A new configuration tab in the preferences window, called Java Compiler, has appeared. It currently only holds a single setting – “Project bytecode version”.
This setting defines the bytecode version of all Java classes compiled by MPS. These classes include classes generated from language’s aspects, classes of the runtime solutions, classes of the sandbox solutions, etc.
By default, the bytecode version is set to “JDK Default”. This means that the version of the compiled classes will be equal to the version of Java, which MPS is running under. E.g. if you run MPS under JDK 1.8 and “JDK Default” is selected, the bytecode version will be 1.8.
The other options for project bytecode version are 1.6, 1.7 and 1.8.
Note that if you compile languages to the 1.8 version, then if you try to run MPS with JDK, the version of which is earlier than 1.8, those languages won’t be loaded.
Build scripts
Also, don’t forget to set java compliance level in the build scripts of your project. It should be the same as the project bytecode version.
Using java classes compiled with JDK 1.8
In the MPS modules pool you can find the JDK solution, which holds the classes of the running Java. So when you start MPS under JDK 1.8, the latest Java Platform classes will be available in the JDK solution.
You can also use any external Java classes, compiled under JDK 1.8 by adding them as Java stubs.
Since version 1.8, Java interfaces can contain default and static methods. At present, MPS does not support creating them in your BaseLanguage code, but you can call static and default methods defined in external Java classes, e.g classes of the Java Platform.
Static interface method call
In the example, we sort a list with the Comparator.reverseOrder(). Comparator is an interface from java.util, and reverseOrder() is its static method, which was introduced in Java 1.8.
Default interface methods
Java 8 introduced also default methods. These are methods implemented directly in the interface. You can read about default methods here: http://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html
These methods can be called just like the usual instance methods. Sometimes, however, you need to call the default method directly from an interface that your class is implementing. E.g in case of multiple inheritance when a class implements several interfaces, each containing a default method with the same signature.
public interface A { public default void foo() { System.out.println("A"); } } public interface B { public default void foo() { System.out.println("B"); } }
In that case foo() can be called explicitly on one of the interfaces via a SuperInterfaceMethodCall construction, which is newly located in the jetbrains.mps.baseLanguage.jdk8 language.
Using Java platform API
Java 8 introduced lambda expressions, of which you can learn more here: http://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html
MPS 3.2 doesn’t yet have a language that would be generated into lambda-expressions. Instead, it has its own closure language, which is compatible with the new Java API!
Here’s the example of an interaction with the new JDK 8 Collections API:
The forEach() method is the new default method of java.lang.Iterable. It takes a Consumer interface as a parameter. Consumer is a functional interface as it only has one method. In Java 8 it would be possible to pass a lambda expression to forEach(). In MPS you can pass the MPS closure. A closure knows the type of the parameter taken by forEach() while generating and it will be generated exactly to the correct instance of the Consumer.
Develop with pleasure!
-JetBrains MPS Team