This part of the book is about the key differences between Java and Scala language syntax. Given some typical Java code, we’ll look at equivalent Scala syntax. In Part III., we’ll look more at Scala features for which there is no direct equivalent in Java.
We’re going to look at:
for
loops.Scala is very flexible. There are generally several ways to achieve the same thing. I don’t mean the difference between using a while
loop or for
loop; I mean that the language has different syntax options for expressing the same thing. This flexibility gives a lot of freedom but can be confusing when you’re reading code from different authors.
An example is the infix notation we saw earlier. You can often drop the dots and brackets when calling methods. Scala is opinion-less; it’s up to you if you want to use the dots or not.
Java, on the other hand, is very restrictive; there are generally very few ways to express the same things. It’s often easier to recognise things at a glance. You might have to work a little harder to recognise some of the more exotic syntax options in Scala.
This is true when it comes to the structure of your code too; you can create functions within functions, import statements in the middle of a class, or have a class live in a file with an unrelated name. It can all be a little disorienting when you’re used to the rigidity of Java.
Because Scala favours immutability, you might also notice a different approach to solving problems. For example, you might notice a lack of looping over mutable variables. Scala programs usually favour more functional idioms to achieve the same thing.
This more declarative way of doing things says “tell me what to do, not how to do it”. You may be more used to the Java / imperative way of doing things that says “tell me exactly how to do it”. Ultimately, when you give up the micro-management style of imperative programming, you allow the language more freedom in how it goes about its business.
For example, a traditional imperative for loop in Java looks like this:
// java
for
(
int
count
=
0
;
count
<
100
;
count
++)
{
System
.
out
.
println
(
count
);
}
It’s a typical imperative loop. We’re telling it explicitly to enumerate serially from zero to one hundred. If, on the other hand, we use a more declarative mechanism, like this:
// scala
(
0
to
100
).
foreach
(
println
(
_
))
…the enumeration is done within the foreach
method, not by a language construct. We’re saying, “for a range of numbers, perform some function on each”. Although only subtly different, we’re not saying how to enumerate the sequence. It means Scala is free to implement the enumeration however it likes. (For example, it may choose to do it in parallel.)
Interestingly, Oracle has adopted these ideas in Java 8. If you’ve been using that, you’re probably already familiar with the concepts.