Back and forth from Scala to Java
Tags: scala, java, functional, programming
Published: 2019-11-07 10:47:13

---
title: Back and forth from Scala to Java
published: true
description: Programming in Java after years of Scala
tags: scala,java,functional,programming
---
For over two years I've programmed nearly exclusively in Scala on the backend, while using mostly JavaScript and TypeScript on the frontend. Before that I mostly used Java for over 15 years, as well as a few other programming languages
Since a month I use Java, Java 8 even, on an assignment, and I thought I shared my experience.
The reason I use Java again, because the client uses Java and more broadly, I wondered how easy it would be to switch back if needed. After all I claim to be programming-language agnostic

First, going back wasn't as hard as I thought it was, it all came back to me pretty quickly. Of course I'd need to add ; and some more superfluous code, but that's doable.

#### Lambda's
I use Java 8, which is the first Java version to feature lambda's. I don't think I could bear a language without. I use lambda's heavily, probably more than people who'd never used a programming language.
Scala uses **=>**, Java uses **->**, but that's ok.

### Mutable data
Just as in Scala, mutable data-structures can lead to unpredictable behavior. In the Scala world people are by now pretty used to using immutable data-structures.
In the Java world, rather then thinking about how to transform data correctly, people still deliberate about [anthropomorphic](https://www.cs.utexas.edu/users/EWD/transcriptions/EWD09xx/EWD936.html) questions like what responsibilities an object has and how a Employee class relates to an employee in the real world.

#### Option
Java 8 introduced the Optional class, so there's no excuse for having [NullPointerExceptions](https://duckduckgo.com/?q=NullPointerException+java+Optional) in your code (well, except when using older code and libraries).
Java 8 Optional has a [map](https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html#map-java.util.function.Function-) method. Annoyingly, it's [orElse](https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html#orElse-T-) method of Option returns the actual value type instead of the value wrapped in an Optional, so you can't chain an orElse. I have no idea what the language designers were thinking. Well, as alternative I could use map, but that's a bit less readable:
```java
      Optional<String>  firstName=Optional.of("John");
      Optional<String>  lastName=Optional.empty();
      Optional<String> name = firstName.map(Optional::of).orElse(lastName);
```
Fortunately, Java 9 introduced [or](https://docs.oracle.com/javase/9/docs/api/java/util/Optional.html#or-java.util.function.Supplier-).
#### Optional and streams
Also, Java's Optional can't be used as [Iterable](https://docs.oracle.com/javase/8/docs/api/java/lang/Iterable.html), while Scala's [Option](https://www.scala-lang.org/api/current/scala/Option.html) can. Allowing to treat Option as a collection of zero or one values helped me better understanding what an Option is and how you could use it beyond the [isPresent()](https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html#isPresent--) method.
Converting an Option to a Stream shouldn't be too hard:
```java
    public static <T> Stream<T> stream(Optional<T> option) {
        return option.map(Stream::of).orElse(Stream.empty());
    }

```
Which will then allow me to write:
```java
      Optional<String>  firstName=Optional.of("John");
      Optional<String> middleName=Optional.empty();
      Optional<String>  lastName=Optional.of("Doe");

      ...
   private String toName(Optional<String> firstName, Optional<String> middleName, Optional<String> lastName) {
      return Stream.of(
              stream(firstName),
              stream(middleName),
              stream(lastName))
              .flatMap(Function.identity())
              .collect(Collectors.joining(" "));
   }
```
That doesn't look so concise anymore, but arguably better than nested if else blocks.

#### Try catch finally and Either
In Java 8, when you use a resource that implements the [Closeable](https://docs.oracle.com/javase/8/docs/api/java/io/Closeable.html) interface working, a finally block to close the resource is no longer necessary. That's pretty nice:
```java
    public String readMe() throws IOException {
        try(BufferedReader in = new BufferedReader(new FileReader("some file.txt"))) {
            return in.readLine();
        }
    }
```

At least when an exception is thrown, the resource is closed. What I greatly miss, is a [Try class](https://docs.scala-lang.org/overviews/scala-book/functional-error-handling.html), [Either](https://typelevel.org/cats/datatypes/either.html) or something similar so no exception is thrown by the method at all. There are a few libraries that do add something like Either, like [functionalj](http://www.functionaljava.org/features.html), but of course these are non-standard so a bit harder to introduce at project.
#### Beyond the limits of imperative OO: annotations, aspects and reflection.
As is pretty common, [Spring](https://spring.io) is also used to extend Java. Spring is based on the principle of aspect- or plugin-oriented programming and heavily relies on bytecode-enhancement and reflection to extend the language Java. In practice this means you use either annotations or config files.
The biggest disadvantage: everything is applied at *runtime*, e.g., when your application runs.
In Scala, the language itself is flexible enough using pattern matching, implicits, macros and other language constructs.
Scala pattern matching does use reflection in some cases, but most errors are catched compile time rather then runtime. And despite people complaining about implicit, having an error during *compilation* because you forgot to import an implicit is a lot easier to handle than an error that occurs when *running* your software because some configuration is wrong, or something fails during reflection.

Spring will give you pretty good errors when having a wrongly applied annotation, and IntelliJ does have good support for Spring. So most of the times you'll get reasonable descriptive warnings or errors for missing beans, wrong spring-configuration, etc, which makes Spring almost feel being part of the language. And it still feels cumbersome, if only because your code is cluttered with annotations.
#### Lombok, case classes
Scala introduced [case classes](https://docs.scala-lang.org/overviews/scala-book/case-classes.html), which allows you to write value based classes without a lot of boilerplate - or mistakes like accidentally committing a property in [equals](https://docs.oracle.com/javase/10/docs/api/java/lang/Object.html#equals(java.lang.Object)) or [hashCode](https://docs.oracle.com/javase/10/docs/api/java/lang/Object.html#hashCode()).

Java by default doesn't. I'm very glad [someone](https://projectlombok.org/order-license-info) created [Lombok](https://projectlombok.org) and it seems well accepted.
```java
import lombok.Value;

@Value
public class Employee {
    String firstName;
    String middleName;
    String lastName;
    long employNumber;
}

```
You can't do everything you could do in Scala, like pattern matching on a case class, and unlike Scala there's still a difference between methods and properties in Java.
But it's a whole lot better then generated equals, toString and get'ter methods.

[IDE support for Lombok](https://www.baeldung.com/lombok-ide) is very good, so you hardly notice you're using language extensions.


### Conclusion
Switching back and forth from Scala to Java is doable, but I certainly wouldn't want to go back indefinitely. The Scala world is still thriving. Java is bearable, but Scala makes programming doable.