[back to bqbase index]

From Java to Scala

This chaotic entry should describe migration from Java.

using maps

Scala maps are different from Java maps, because they return an Option.
Map map = new HashMap<int,String>
String s = map.get(0)
if (s!=null) {...}
	
map.get(0) match {
  case Some(s) => ...
  case None    => // do nothing 
}
	

Scala offers a lot of different ways to achieve the same. You can use a for-comprehension on an option

for(val theValue <- map.get(key)) {
  theValue.myMethod
}
  

This is the same as writing map.get(key).foreach(.myMethod), which personally I do not find very informative but it's there.

some tips when rewriting source code

Uff, just translated the code generation parts of the pattern matching phase from Java(or rather: Pico) to Scala. 1500 lines became 1530 lines. This is probably the most tedious and boring task one could do, but there are things that are worth remembering.

Here's a list of what to do when translating a source file from Java (before 1.5, no generics!) to Scala (some people might take this as a little description of syntax changes):

  • Import descriptors: Turn import xxx.* into import xxx._
  • remove public modifier from class declaration
  • Move the primary constructor of class X extends Foo { ... } up. This yields a class X(arg1:T1,...,argsN:TN) extends Foo(...) { ... }. If you have several constructors, choose one to be the primary one.
  • If you extend a class, nothing changes, but instead of implements myInterface, write extends myInterface if its the only one. Write with i1 ... with iN if there are several (this is a oversimplified description, it might go wrong in some cases that I won't go into here.)
  • Of course, change all declarations T x into x:T
  • While you're at it, replace field declarations T x; with value or variable declarations var x:T = _;. If you don't supply a default value, your class must become abstract
  • If you made Java fields just to store constructor arguments, omit those and add val to your primary constructor argument class X(arg1:T1,...,val argJ: TJ, ... argsN:TN). Sorry this does not work with mutable fields (var).
  • remove public modifier from method definitions. Turn definition T m(args) {...} into def m(args): T = {...}. Pay attention to that equal sign.
  • Another thing about type declarationg: T x[] and T[] x both become x: Array[T]. If you also want to initialize an array, turn T x[] = { y1,...,yN } into val x = Predef.Array[T](y1,...,yN).
  • Turn all for loops into while loops. You could also use for-loops, but it takes to long to write. Pay attention to not forget the increment, decrement operations, which you of course have to move to the end of the block. for(int i = ...; test; inc) {body} becomes val i = ...; while(test) {body; inc}. Of course this pollutes the scope with variables (which in Java you might have reused in other loops), but those you can fix by renaming later.
  • Ah yes, say goodbye to x++, change it to x and to x = x + 1;
  • If you have static stuff in a class X, create an object X of the same name and move the translated thingies there (without the static modifier). Change access sites of a static method or field into qualified access ( i.e. foo becomes X.foo ). For most uses of static, this is enough, e.g. the main method.
  • switch statements require more care. First turn case pat: into case pat =>. Now you should take some more involved measures: scala does not need a break, which is convenient, but an unmentioned default case will not be ignored by lead to a runtime error. If your switch does not have a default case, add one case _ => (the right-hand side is empty.)
  • remove all return statements. Those at the end you don't need, returns that are somewhere in the middle of your method body are either supported or unsupported, depending on whether they get translated via some syntactic quirks. Add exit flag variables in loops and stuff. The same holds for break statements in for/while loops. Get rid of those things.

After all this, you will probably not appreciate scala a lot, because your program has not become any nicer. Now is the time to fix all those syntax errors that you introduced. Only when you got all these and your test suites run through you can look into ways to take advantage of Scala. For instance, replace all uses of collection classes with the equivalent (or better) scala ones. Use higher order functions to express things concisely. I'll get back to this page to add some cures for those "Java smells".

Problems

Even if you have a package of the same name, you won't be able to access package-protected things from Java. Either you translate the classes with those parts you want to access, too, or you make the public.


published:2005-01-21  last change:2006-11-07

changelog: