Java 8 has been around for nearly 3 years now, and a lot of frameworks are adopting it as a baseline such as Spring 5. However we aren’t all taking advantage of the new features, such as Lamdba expressions, Streams and Optional.
On 25th February 2017, Trisha Gee will be giving her acclaimed ‘Refactoring to Java 8’ talk at Voxxed Days CERN. She will be showing us why we should adopt Java 8 features, and how to go about refactoring existing code to take advantage of them. To give us an idea of what to expect, we asked Trisha what her motivations are, and her experiences of refactoring to Java 8.
Why is it important to refactor to Java 8, rather than wait for Java 9?
I think Java 9 is a more interesting release than most developers realise, but Java 8 is the Big One for developers. The introduction of lambda expressions and the streams API is a big change in paradigm for Java developers, and it’s going to take a bit of getting used to, especially if you’ve been doing Java for a long time and haven’t had much exposure to other languages.
I think using the new features via refactoring existing code that you understand (and is covered via tests!!) is a good way to practice these new idioms. Java 9 comes with even more methods on the streams API, and some changes for collections, which I think will be easier to understand and use if you’ve already had practice with Java 8.
In your experiences, what is the most useful feature in Java 8? What feature do you find yourself using the most, or getting the most benefit from refactoring to?
I do like the Streams API now I’ve been using it for a bit – it does reduce boilerplate and force you to think about what you’re trying to do, not how to iterate to achieve it. But actually it’s the new methods on collections that I think are the most interesting, and reduce cognitive load for developers. For example, removeIf from Collection and computeIfAbsent on Map. These methods just make life easier and take away a lot of common code that just isn’t needed.
What is the most abused feature of Java 8?
My pain point is Optional. I don’t know if it’s abused as such (yet!), but I was working on a codebase that uses “null” throughout the code, and I wanted to eliminate null-checks and be much clearer about what can and cannot be null. I’ve tried to apply this refactoring on multiple occasions, and I just can’t do it in a way that gives clearer code. And every time I try it, it touches hundreds of classes! The problem in this case is definitely a “smell”, nulls shouldn’t have been given this meaning in the code in the first place, but Optional, which I thought would address this problem, did not fix this problem. In fact they made it worse. So, it’s not an abused feature, but one that needs extra care and thought to really get any benefit from.
You mention in previous interviews that you have to test any performance improvements on a case-by-case basis: what’s your advice for going about this?
I’ve been using JMH for microbenchmarking specific sections of code, but you really do need to be careful of microbenchmarks (you can read about this elsewhere if you do a quick Google). In the case of one of the code bases, it’s a database driver so although microbenchmarks point to particular methods being “slower”, overall when you factor in talking to the database it has a tiny impact in the grand scheme of things. Performance testing is best when you know what you really need (is it nano-second response time, or perhaps just a response which doesn’t “feel slow” to a user?), so you need to know your requirements and you need to measure the thing that you really care about.
Finally, how do you go about debugging Java 8 features like lambdas and streams?
That sounds like a topic for a blog post or talk in its own right! You may need, certainly at the beginning, to expand these features into idioms you’re more comfortable with. For example, extract lambdas into their own methods so the stack traces and debug breakpoints are in a place you understand; you may want to refactor the streams API calls into traditional for-loops and if-statements to reason around them in a way that’s familiar to you (you’ll be pleased to hear IntelliJ IDEA 2017.1 lets you refactor from for loops to streams back to for loops seamlessly for this reason). You may want to use the Streams API’s
peek() method to either breakpoint on or output debug info. Like any new framework/API/feature, as you’re starting out with it don’t be afraid to play with what’s there and try things out. As you get more familiar with the Java 8 features, debugging them will become more comfortable too.
There are a lot of advantages from refactoring to Java 8 – from performance improvements to up-skilling and staying up-to-date with your Java knowledge. Join us at Voxxed Days CERN for the full talk.