Newer posts are loading.
You are at the newest post.
Click here to check if anything new just came in.

September 02 2011

A look at Java 7's new features

There are a number of features in Java 7 that will please developers. Things such as strings in switch statements, multi-catch exception handling, try-with-resource statements, the new File System API, extensions of the JVM, support for dynamically-typed languages, the fork and join framework for task parallelism, and a few others will certainly be embraced by the community.

Below I outline the features and provide examples where appropriate. A zip file containing code snippets used in this post can be downloaded here.

Language enhancements

Java 7 includes a few new language features via Project Coin. These features are quite handy for a developer.

Diamond Operator

You may have noted on many occasions your IDE complaining of types when working with Generics. For example, if we have to declare a map of trades using Generics, we write the code as follows:

Map<String, List<Trade>> trades = new TreeMap<String, List<Trade>> ();

The not-so-nice thing about this declaration is that we must declare the types on both the sides, although the right-hand side seems a bit redundant. Can the compiler infer the types by looking at the left-hand-side declaration? Not unless you're using Java 7. In 7, it's written like this:

Map<String, List<Trade>> trades = new TreeMap <> ();

How cool is that? You don't have to type the whole list of types for the instantiation. Instead you use the <> symbol, which is called diamond operator. Note that while not declaring the diamond operator is legal, as trades = new TreeMap (), it will make the compiler generate a couple of type-safety warnings.

Using strings in switch statements

Switch statements work either with primitive types or enumerated types. Java 7 introduced another type that we can use in Switch statements: the String type.

Say we have a requirement to process a Trade based on its status. Until now we used to do this by using if-else statements.

private void processTrade(Trade t) {

String status = t.getStatus();

if (status.equalsIgnoreCase(NEW)) {

newTrade(t);

} else if (status.equalsIgnoreCase(EXECUTE)) {

executeTrade(t);

} else if (status.equalsIgnoreCase(PENDING)) {

pendingTrade(t);

}

}

This method of working on strings is crude. In Java 7, we can improve the program by utilizing the enhanced Switch statement, which takes a String type as an argument.

 public void processTrade(Trade t) {

String status = t.getStatus();

switch (status) {

case NEW:

newTrade(t);

break;

case EXECUTE:

executeTrade(t);

break;

case PENDING:

pendingTrade(t);

break;

default:

break;

}

}



In the above program, the status field is always compared against the case label by using the String.equals() method.

Automatic resource management

Resources such as Connections, Files, Input/OutStreams, etc. should be closed manually by the developer by writing bog-standard code. Usually we use a try-finally block to close the respective resources. See the current practice of creating a resource, using it and finally closing it:

    
public void oldTry() {

try {

fos = new FileOutputStream("movies.txt");

dos = new DataOutputStream(fos);

dos.writeUTF("Java 7 Block Buster");

} catch (IOException e) {

e.printStackTrace();

} finally {

try {

fos.close();

dos.close();

} catch (IOException e) {

// log the exception

}

}

}



However, Java 7 has introduced another cool feature to manage the resources automatically. It is simple in operation, too. All we have to do is declare the resources in the try as follows:

try(resources_to_be_cleant){

// your code

}

The above method with the old try can finally can be re-written using this new feature as shown below:

      public void newTry() {

try (FileOutputStream fos = new FileOutputStream("movies.txt");

DataOutputStream dos = new DataOutputStream(fos)) {

dos.writeUTF("Java 7 Block Buster");

} catch (IOException e) {

// log the exception

}

}

The above code also represents another aspect of this feature: working with multiple resources. The FileOutputStream and DataOutputStream resources are enclosed in the try statement one after the other, each one separated by a semicolon (;) separator. We do not have to nullify or close the streams manually, as they are closed automatically once the control exists the try block.

Behind the scenes, the resources that should be auto closed must implement java.lang.AutoCloseable interface.

Any resource that implements AutoCloseble interface can be a candidate for automatic resource management. The AutoCloseable is the parent of java.io.Closeable interface and has just one method close() that would be called by the JVM when the control comes out of the try block.

Numeric literals with underscores

Numerical literals are definitely eye strainers. I am sure you would start counting the zeroes like me if you've been given a number with, say, ten zeros. It's quite error prone and cumbersome to identify a literal if it's a million or a billion unless you count the places from right to left. Not anymore. Java 7 introduced underscores in identifying the places. For example, you can declare 1000 as shown below:

int thousand =  1_000;

or 1000000 (one million) as follows

int million  =  1_000_000

Note that binary literals are also introduced in this release too — for example "0b1" — so developers don't have to convert them to hexadecimals any more.

Improved exception handling

There are a couple of improvements in the exception handling area. Java 7 introduced multi-catch functionality to catch multiple exception types using a single catch block.

Let's say you have a method that throws three exceptions. In the current state, you would deal them individually as shown in below:

   public void oldMultiCatch() {

try {

methodThatThrowsThreeExceptions();

} catch (ExceptionOne e) {

// log and deal with ExceptionOne

} catch (ExceptionTwo e) {

// log and deal with ExceptionTwo

} catch (ExceptionThree e) {

// log and deal with ExceptionThree

}

}



Catching an endless number of exceptions one after the other in a catch block looks cluttered. And I have seen code that catches a dozen exceptions, too. This is incredibly inefficient and error prone. Java 7 has brought in a new language change to address this ugly duckling. See the improved version of the method oldMultiCatch method below:

      public void newMultiCatch() {

try {

methodThatThrowsThreeExceptions();

} catch (ExceptionOne | ExceptionTwo | ExceptionThree e) {

// log and deal with all Exceptions

}

}

The multiple exceptions are caught in one catch block by using a '|' operator. This way, you do not have to write dozens of exception catches. However, if you have bunch of exceptions that belong to different types, then you could use "multi multi-catch" blocks too. The following snippet illustrates this:

public void newMultiMultiCatch() {

try {

methodThatThrowsThreeExceptions();

} catch (ExceptionOne e) {

// log and deal with ExceptionOne

} catch (ExceptionTwo | ExceptionThree e) {

// log and deal with ExceptionTwo and ExceptionThree

}

}



In the above case, the ExceptionTwo and ExceptionThree belong to a different hierarchy, so you would want to handle them differently but with a single catch block.

New file system API (NIO 2.0)

Those who worked with Java IO may still remember the headaches that framework caused. It was never easy to work seamlessly across operating systems or multi-file systems. There were methods such as delete or rename that behaved unexpected in most cases. Working with symbolic links was another issue. In an essence, the API needed an overhaul.

With the intention of solving the above problems with Java IO, Java 7 introduced an overhauled and in many cases new API.

The NIO 2.0 has come forward with many enhancements. It's also introduced new classes to ease the life of a developer when working with multiple file systems.

Working with Path

A new java.nio.file package consists of classes and interfaces such as Path, Paths, FileSystem, FileSystems and others.

A Path is simply a reference to a file path. It is the equivalent (and with more features) to java.io.File. The following snippet shows how to obtain a path reference to the "temp" folder:

public void pathInfo() {

Path path = Paths.get("c:\\Temp\\temp");

System.out.println("Number of Nodes:" + path.getNameCount());

System.out.println("File Name:" + path.getFileName());

System.out.println("File Root:" + path.getRoot());

System.out.println("File Parent:" + path.getParent());

}

The console output would be:

Number of Nodes:2

File Name:temp.txt

File Root:c:\

File Parent:c:\Temp

Deleting a file or directory is as simple as invoking a delete method on Files (note the plural) class. The Files class exposes two delete methods, one that throws NoSuchFileException and the other that does not.

The following delete method invocation throws NoSuchFileException, so you have to handle it:

Files.delete(path);

Where as Files.deleteIfExists(path) does not throw exception (as expected) if the file/directory does not exist.

You can use other utility methods such as Files.copy(..) and Files.move(..) to act on a file system efficiently. Similarly, use the createSymbolicLink(..) method to create symbolic links using your code.


File change notifications

One of my favorite improvements in the JDK 7 release is the addition of File Change Notifications. This has been a long-awaited feature that's finally carved into NIO 2.0. The WatchService API lets you receive notification events upon changes to the subject (directory or file).

The steps involved in implementing the API are:

  • Create a WatchService. This service consists of a queue to hold WatchKeys
  • Register the directory/file you wish to monitor with this WatchService
  • While registering, specify the types of events you wish to receive (create, modify or delete events)
  • You have to start an infinite loop to listen to events
  • When an event occurs, a WatchKey is placed into the queue
  • Consume the WatchKey and invoke queries on it

Let's follow this via an example. We create a DirPolice Java program whose responsibility is to police a particular directory. The steps are provided below:

1. Creating a WatchService object:

WatchService  watchService = FileSystems.getDefault().newWatchService();

2. Obtain a path reference to your watchable directory. I suggest you parameterize this directory so you don't hard code the file name.

path = Paths.get("C:\\Temp\\temp\\");

3. The next step is to register the directory with the WatchService for all types of events:

dirToWatch.register(watchService, ENTRY_CREATE, ENTRY_MODIFY,

ENTRY_DELETE);

These are java.nio.file.StandardWatchEventKinds event types

4. Initiate the infinite loop and start taking the events:

while(true)

{

WatchKey key = watchService.take(); // this would return you keys

}

5. Run through the events on the key:

for (WatchEvent<?> event : key.pollEvents()) {

Kind<?> kind = event.kind();

System.out.println("Event on " + event.context().toString() + " is " + kind);

}

For example, if you modify or delete the temp directory, you would see statement as shown below on the console respectively:

Event on temp is ENTRY_MODIFY

Event on temp is ENTRY_DELETE

The relevant methods of the DirPolice source code are posted below (download the full source code):

/**

* This initiates the police

*/

private void init() {

path = Paths.get("C:\\Temp\\temp\\");

try {

watchService = FileSystems.getDefault().newWatchService();

path.register(watchService, ENTRY_CREATE, ENTRY_DELETE,

ENTRY_MODIFY);

} catch (IOException e) {

System.out.println("IOException"+ e.getMessage());

}

}

/**

* The police will start making rounds

*/

private void doRounds() {

WatchKey key = null;

while(true) {

try {

key = watchService.take();

for (WatchEvent<?> event : key.pollEvents()) {

Kind<?> kind = event.kind();

System.out.println("Event on " + event.context().toString() + " is " + kind);

}

} catch (InterruptedException e) {

System.out.println("InterruptedException: "+e.getMessage());

}

boolean reset = key.reset();

if(!reset)

break;

}

}

Fork and Join

The effective use of parallel cores in a Java program has always been a challenge. There were few home-grown frameworks that would distribute the work across multiple cores and then join them to return the result set. Java 7 has incorporated this feature as a Fork and Join framework.

Basically the Fork-Join breaks the task at hand into mini-tasks until the mini-task is simple enough that it can be solved without further breakups. It's like a divide-and-conquer algorithm. One important concept to note in this framework is that ideally no worker thread is idle. They implement a work-stealing algorithm in that idle workers "steal" the work from those workers who are busy.

The core classes supporting the Fork-Join mechanism are ForkJoinPool and ForkJoinTask. The ForkJoinPool is basically a specialized implementation of ExecutorService implementing the work-stealing algorithm we talked about above.

We create an instance of ForkJoinPool by providing the target parallelism level — the number of processors as shown below:

ForkJoinPool pool = new ForkJoinPool(numberOfProcessors)

Where numberOfProcessors = Runtime.getRunTime().availableProcessors();

However, the default ForkJoinPool instantiation would set the parallelism level equal to the same number obtained as above.

The problem that needs to be solved is coded in a ForkJoinTask. However, there are two implementations of this class out of the box: the RecursiveAction and RecursiveTask. The only difference between these two classes is that the former one does not return a value while the latter returns an object of specified type.

Here's how to create a RecursiveAction or RecursiveTask class that represents your requirement problem (I use the RecursiveAction class):

public class MyBigProblemTask extends RecursiveAction {

@Override

protected void compute() {

. . . // your problem invocation goes here

}

}

You have to override the compute method where in you need to provide the computing functionality. Now, provide this ForkJoinTask to the Executor by calling invoke method on the ForkJoinPool:

pool.invoke(task);

Supporting dynamism

Java is a statically typed language — the type checking of the variables, methods and return values is performed at compile time. The JVM executes this strongly-typed bytecode at runtime without having to worry about finding the type information.

There's another breed of typed languages — the dynamically typed languages. Ruby, Python and Clojure are in this category. The type information is unresolved until runtime in these languages. This is not possible in Java as it would not have any necessary type information.

There is an increasing pressure on Java folks improvise running the dynamic languages efficiently. Although it is possible to run these languages on a JVM (using Reflection), it's not without constraints and restrictions.

In Java 7, a new feature called invokedynamic was introduced. This makes VM changes to incorporate non-Java language requirements. A new package, java.lang.invoke, consisting of classes such as MethodHandle, CallSite and others, has been created to extend the support of dynamic languages.

Wrapping up

As we've covered, Java 7 has a few bells and whistles that should put smiles on developers' faces, and the open-source collaboration and support for dynamic languages via JVM extensions should also be well received by those outside the Java community.



Related:


July 07 2011

Seven reasons you should use Java again

O'Reilly is celebrating the release of Java 7, and our inaugural OSCON Java conference: July 25-27 in Portland, Ore.

Java's back, baby. Of course, lots of us never stopped using Java in the first place, or perhaps we weren't allowed to. But where platform selection was elective, especially among startups and web developers, alternative platforms have offered more agility and expressiveness over the last 10 years. The likes of PHP and Ruby on Rails enable developers to do a whole lot more with less.

Times change, and 16 years on, this ain't your father's Java. Here's seven reasons you should take another look at Java.

1. You can actually hire engineers

Not to be sniffed at when your Node.js Ninjas and Rails Rockstars get headhunted into the latest impossibly well-funded startup.

2. IDEs take the pain away

Eclipse and NetBeans are astonishingly powerful tools, and can mask some of the admitted horror that is Java API soup. Bend like a reed, admit you can't know everything, and float downstream on the good ship autocomplete.

3. Language support

You don't have to write Java to use Java. You can get all the benefits of the portable JVM runtime but scribble away in the familiar environs of Ruby or Python. It can be faster too. And that's not to mention the newer languages aimed at modern programming such as Scala, Groovy or Clojure.

OSCON Java 2011
To celebrate the release of Java 7, the first 77 people registering today for OSCON Java with code JAVA7 will get the pass at a discounted price of $700 (applicable to OSCON Java package only).

Register now with code JAVA7

4. Android

Who can resist the little green robot? Google made a sensible choice when they chose the Java language to power what's becoming the world's dominant mobile phone platform. So, maybe Oracle has a billion-dollar beef with this, but programmers — new and seasoned alike — are picking up Java as mobile becomes the future of consumer software.

5. Everybody else does

Java's ecosystem is a goldmine. Pretty much everything you want to do, there's a library for it. Actually, there's probably an Apache project for it. Very often the lowest impedance way to speak to the rest of the world is via a Java API.

6. It changes slowly

We're celebrating the release of Java 7 right now. It's been two years in the making, and frankly, there's not a whole lot that's changed for most people. If you can take your finger off the refresh button at Hacker News for more than an hour, any software that lives longer than a year becomes a real pain to maintain when the underlying platform keeps changing. Yes, looking at you, Rails.

7. You'll end up using it anyway

At a certain point you'll need performance, predictability and a ready supply of engineers. Scaling, deploying and programming to the cloud are places where Java excels. Twitter found this out, and will be talking about it at OSCON Java.


There's still time left to register for OSCON Java. See you in Portland, 25-27 July!



Related:


A rough guide to JVM languages

O'Reilly is celebrating the release of Java 7, and our inaugural OSCON Java conference: July 25-27 in Portland, Ore.

The possibility of using alternative languages on the JVM has always been an appealing side story to Java. Jython and JRuby were early pioneers in implementing a dynamic language on top of a statically typed VM. Now that Java 7 directly includes support in the JVM for dynamic languages, the coexistence is official.

Pick any of the languages here and you can expect the support of the robust JVM threading and garbage collection, plus access to a broad array of application libraries.

Up and coming

Scala

The pragmatist among JVM languages, Scala is a general-purpose programming language. It was conceived and is generally viewed as a "better Java," and of all alternative JVM languages has the best acceptance in an enterprise setting.

Scala combines the familiar feel of object-oriented Java with strong language support for concurrency, XML and functional programming features: many of the tools that contemporary complex and scalable systems require. Scala also takes a lot of the awkwardness out of Java code, through features such as type inference and traits.

object HelloWorld {
    def main(args: Array[String]) {
      println("Hello, World!")
    }
  }

Scala-related content at OSCON Java:

OSCON Java 2011
To celebrate the release of Java 7, the first 77 people registering today for OSCON Java with code JAVA7 will get the pass at a discounted price of $700 (applicable to OSCON Java package only).

Register now with code JAVA7

Clojure

Clojure is a functional programming language based on Lisp. Through careful design, Clojure is simpler to read and use than Lisp, and it interacts cleanly with the Java world. Its functional nature makes programs very concise and composable.

In common with Scala, Clojure is designed with concurrency in mind. Its variables are immutable, and the use of software transactional memory and agents help manage shared mutable state in a more sustainable way than locking.

The experience of Clojure's inventor Rich Hickey is reason enough alone to give it a whirl. I once happily spent an hour listening to him describe the design and implementation of sequences in the language.

A "Lisp that could," Clojure is finding increasing (and surprising, to most observers) traction and acceptance. One contributing factor to this is an advanced build and package management infrastructure in leiningen and Clojars. Salesforce-owned hosted platform provider Heroku recently added Clojure as its third supported environment, following Ruby and Node/JavaScript.

A small but important omission from the Clojure ecosystem is a port of the book The Little Schemer.

(println "Hello, World!")

Clojure-related content at OSCON Java:



Tried and tested


Groovy

A mashup of ideas from Python, Ruby and Smalltalk, Groovy gained early traction in the world of JVM languages, reaching its stable release in December 2007. Having been around a while, Groovy strongly acknowledges the Java world into which it was born, and is a good choice for Java developers wishing to use a more agile and dynamic language.

One of Groovy's jewels is Grails, a high-productivity web development environment inspired by Ruby on Rails. The Groovy world has also spawned Gradle, a modern project automation system for Java and JVM languages, providing an alternative to the established Ant and Maven projects.

println "Hello, World!"

Groovy-related content at OSCON Java:

Rhino

Another veteran of the JVM language scene, Rhino is an implementation of the JavaScript programming language in Java. Part of the Mozilla project, it is typically used by developers to add user scriptability to their applications using JavaScript, though it is also used in situations where a system is predominantly implemented in JavaScript.

First released in 1999, Rhino has been around the block a few times. As a JavaScript engine, it is facing increasing competition from the C++-based V8, but retains the immense advantage of Java interoperability.

print('Hello, World!');

Remastered classics

Jython

A port of the Python language to the JVM, Jython offers some advantages over and above using Python, including Java's multi-threading and the ability to statically compile into Java classes. As a Python terse object-oriented language, programmers can quickly prototype in Jython, creating hybrid Java-Jython systems. Jython also offers developers an alternative to Rhino's JavaScript for embedding scriptability in their applications.

Jython also lets web developers bring popular Django web application framework into a Java setting.

print "Hello, World!"

JRuby

The Java implementation of Ruby is no second-class citizen. JRuby has been recorded as better performing than Ruby 1.8, and strives for C-Ruby compatibility. Users of JRuby can benefit from using the Ruby on Rails web framework, or add Ruby scriptability to their applications.

One appealing aspect of building a system in JRuby or Jython is that it gives developers the option of reimplementing performance-critical code in Java without having to switch platforms as a project matures. Twitter's migration from Ruby to the JVM is a case in point.

puts "Hello, World!"

JRuby-related content at OSCON Java:

The Wild West

The JVM remains a fertile ground for language experimentation, as several of the languages featured in OSCON's Emerging Languages track demonstrate, including Seph and Gosu. As a platform, the JVM bootstraps language inventors and experimenters today much as lex and yacc did two decades ago. At OSCON Java, aspiring language creators should pop along to Charles Nutter's JVM Bytecode for Dummies.


There's still time left to register for OSCON Java. See you in Portland, 25-27 July!



Related:


Seven Java projects that changed the world

O'Reilly is celebrating the release of Java 7, and our inaugural OSCON Java conference: July 25-27 in Portland, Ore.

Java's open source ecosystem is strong and healthy, one of the primary reasons for our creation of OSCON Java. Over the last decade, several projects have traveled beyond mere adoption and had effects dominating the Java world, into software development in general, and some even further into the daily lives of users.

JUnit

Ported to Java by Kent Beck and Erich Gamma from Beck's work in unit testing in Smalltalk, JUnit has been largely responsible for popularizing test-driven development over the last decade. Many implementations have been created, in .NET, C, Python, Perl and just about every language in popular use.

Eclipse

As Java and its APIs matured in the early 2000s, the Eclipse IDE provided a way for programmers to be productive and negotiate the growing Java ecosystem. Eclipse was also the first major project to use the SWT UI toolkit, providing important competition to Sun's Swing and showing that Java programs can provide a rich native interface. Eclipse has evolved toward a goal of being a universal IDE, and it now provides a rich foundation for platform vendors to integrate with.

Spring

The Spring Framework has played an important role in enabling Java developers to be productive, managing a balance between simplicity and features. Spring gives Java developers a set of services providing commonly used application functionality such as data access and transaction management. As a competitor to Sun's Enterprise Java Beans system, Spring enabled an alternative and simpler path for Java applications, as well as ensuring a healthy competition of ideas in the way Java applications are constructed.

OSCON Java 2011
To celebrate the release of Java 7, the first 77 people registering today for OSCON Java with code JAVA7 will get the pass at a discounted price of $700 (applicable to OSCON Java package only).

Register now with code JAVA7



Solr


The Solr server, and the Lucene search engine it encapsulates, has been for many years a simple and practical solution to providing search capabilities to web and enterprise applications. Solr's genius is in providing HTTP access to the powerful and fast Lucene search library, enabling it to become a part of any system, regardless of whether it is implemented in Java or not. More than any other project, Solr has ensured that good search is a checkbox item for modern web applications.

Hudson and Jenkins

Originally developed as Hudson, and now also as Jenkins, this continuous integration tool is a key part of a Java development setup. Jenkins provides automated build and testing of a software project, continuing in the footsteps of JUnit in enabling agile development on the Java platform. While both Hudson and Jenkins persist for now as forks of each other, it doesn't detract from the work of Kohsuke Kawaguchi in creating a world-class continuous integration platform and so enhancing the quality of much Java development.

Hadoop

This Java implementation of the famous MapReduce model is the powerhouse that has enabled most "big data" systems. By lowering the cost of extracting value from large data sets, Hadoop has made practical the personalization and advertising businesses of Facebook and Yahoo, and many other companies. In the same way that Linux enabled large websites to be built on cheap hardware, Hadoop enables large-scale distributed computing by handling failure at the software level. Both Hadoop and the above-mentioned Lucene are the product of the work of Doug Cutting.

Android

Controversy is never that far from Java, whether the custodian be Sun or Oracle. Google's choice to use Java as the programming language for its massively popular Android mobile operating system has led to a renewed interest in the language from whole new communities of software developers. Android programs undergo a further step to convert JVM bytecode to Dalvik bytecode — Dalvik being a virtual machine optimized for mobile devices. Google has been able to leverage Eclipse to provide software developers with a mature development environment for creating Android applications.

Oracle and Google are currently engaged in a lawsuit over a claim that Android infringes on multiple patents held by Oracle. The results of that suit notwithstanding, Android has done much to recruit developers and perpetuate the use of Java in client-side software development.


There's still time left to register for OSCON Java. See you in Portland, 25-27 July!



Related:


Older posts are this way If this message doesn't go away, click anywhere on the page to continue loading posts.
Could not load more posts
Maybe Soup is currently being updated? I'll try again automatically in a few seconds...
Just a second, loading more posts...
You've reached the end.

Don't be the product, buy the product!

Schweinderl