Converting Java to Scala

This page dicusses the Scala language and converting java to scala.

Much of the scala syntax is similar to java and it can use the java class library so in theory it should be relativly easy to convert between java and scala. However it is best to write programs directly in scala using a functional style rather than doing a line by line translation.

Sometimes though we need to get things working quickly and then improve the style quickly so here are some notes that I have made about how to convert:

Import and Class Declaration

  Java Scala
import import javax.swing.* import javax.swing._
class declaration public class AttributeList {... class AttributeList {...
primary constructor class myClass{
myClass(int par) {...}
}
class myClass(par: Int){
{...}
}
secondary constructor classname(...) this(...)

Object and Method declarations

  Java Scala
  private Hashtable list; var list: Hashtable
  public AttributeList() {... def AttributeList(): Unit={...
method declaration private int size() {... def size(): Int={...
array declaration char[] arr; var arr: Array[Char]
  class person extends Object
implements property{...}
class person() extends Object
with property{...}
  super(msg) super.Exception(msg)
  x instanceof String x.instanceOf[String]
  procedure() throws Exception {  

Control Structures

  Java Scala
  return (String) value; return value.asInstanceOf[String]
array declaration char[] arr; var arr: Array[Char]
two dimensional array othersign boolean[][]=new boolean(2)(2) var otherSign:Array[Array[Boolean]] = new Array[Array[Boolean]](2,2);
for loop for(i=0;i<len;i++){...}

var i:Int=0;
while(i<len){
...
i=i+1;
}

try
catch
try{...}
catch(Exception e){...}
try{...}
catch{case e: Exception =>{...}}
  class person extends Object
implements property{...}
class person() extends Object
with property{...}
  super(msg) super.Exception(msg)
  x instanceof String x.instanceOf[String]
  procedure() throws Exception {  
for  

for (i <- 0 until args.length)

var greeting = "" for (i <- 0 until args.length) { greeting += (args(i) + " ") }

foreach

for (String arg : args)
{ greeting += arg + " "; }

for (polynomialTerm sn:terms){ sn.multiplyBy(m); }

args.foreach { arg => greeting += (arg + " ") }

terms.foreach((sn:polynomialTerm) => {sn.multiplyBy(m)})

switch switch (t) {
case product: if (tableGeometric ==null) tableGeometric = new table(dimension,signMap,zeroMap,subAlgebra,elementLabels); return tableGeometric;
case inner: if (tableInner ==null) tableInner = new table(dimension,signMap,zeroMap,subAlgebra,elementLabels); return tableInner; case outer: if (tableOuter ==null) tableOuter = new table(dimension,signMap,zeroMap,subAlgebra,elementLabels); return tableOuter;
}
object t { def main(args: Array[String]) : unit = {
args.length match { case 1 => Console.println("1 argument");
case 2 => Console.println("2 arguments");
case _ => Console.println("more than 2!"); } } }
     

 


Feature Java Scala
Static Typing Yes Yes
Object Oriented programming Yes Yes
Functional programming No Yes
Variable declaration

// type var_name = init_value;
int i = 0;

// var var_name: type = init_value;
var i : int = 0;
Constant declaration

// final type var_name = init_value;
final int i = 0;

// val var_name: type = init_value;
val i : int = 0;
Class declaration

class Person {
// members here
}

class Person {
// members here
}
Methods

// RetType name(PType1 pName1, PType2 pName2...)

class Person {
// members here
public String getName() {
// code here..
}

public void setAge(int age) {
// code here..
}
}


// def name(pName: PType1, pName2: PType2...) : RetType

class Person {
// members here
def getName() : String = {
// code here..
}

def setAge(age: int) : unit = {
// code here..
}
}
Constructors Method(s) with same name as class name with no return type.

class Person {
public Person(String name, int age) {
// initialization here..
}

public Person(String name) {
// call the other constructor
this(name, 1);
}
}
Constructor parameters are specified in class declaration itself. Example:

class Person(name: String, age: int) {
// any method can access "name" or "age" parameter
}
You can have "secondary constructors" as well. Example:

class Person(name: String, age: int) {
// any method can access "name" or "age" parameter
def this(name: String) {
// call the "primary" constructor
this(name, 1);
}
}
Operator overloading No. Except that string concatenation can be done using "+" - which gets transformed as "concat" calls. Yes. Just use operator as method name. Example:

class Complex {
def + (other: Complex) : Complex = {
//....
}
}
Also, any single parameter method can be used as an infix operator. Example:

// call System.exit(int) using infix notation
System exit 0
// call Thread.sleep(int) using infix notation
Thread sleep 10
See also: Scala operators
Static fields and methods

class Person {
private static Person president = ....
private static Person getPresident() {
return president;
}
}

No static members. Use singletons.
Singletons No language support. You can simulate something like this:

class President extends Person {
// make the constructor private - so that
// instance can not be created outside of this class
private President() {}

// create the singleton object here..
private static President thePresident = new President();

// provide accessor for singleton
// and add other methods here..
}

object President extends Person {
// have methods of the singleton object
}
Singleton "objects" are in effect "modules" in Scala. Also, every Java class is viewed like any other Scala class without static methods and fields and a singleton object [whose name is same as Java class name] that contains only the static methods and fields of Java class as it's (non-static) members. This allows accesing static methods of Java classes but at the same time not having static members in Scala.
Inheritance

class Person {
}

class Graduate extends Person {
}

class Person {
}

class Graduate extends Person {
}
See also: Scala subclassing. But, this reference needs update. Now, Java (since JDK 5.0) supports covariant return types.
Calling super class constructor

class Graduate extends Person {
public Graduate(String name, int age, String degree) {
super(name, age);
}
}
You call super class constructor in class declaration itself.

class Graduate(name: String , age: int, degree: String)
extends Person(name, age)
{
}
Method Overriding

class Graduate extends Person {
@Override public String getName() {
// code here...
}
}
@Override is optional - but helps with detecting errors (you may be thinking you are overriding - but in fact you may actually be overloading a super class method).

class Graduate extends Person {
override def getName(): String = {
// code here...
}
}
The keyword "override" is mandatory for non-abstract method overrides.
Abstract classes and methods

abstract class Person {
abstract public String getName();
}

abstract class Person {
def getName(): String;
}
No "abstract" keyword for methods. Only for classes.
Root of all reference types java.lang.Object scala.AnyRef - which is same as java.lang.Object in JVM implementation of Scala
Uniform object orientation? (i.e., is everything object?) No. There are primitive types and reference types. But with autoboxing/unboxing, you don't need to explicitly convert b/w primitive types and corresponding box types. Yes. "int" is an alias to "scala.Int" and so on. A bit explanation of type hierarchy. scala.Any is supertype of all types. scala.AnyVal is super type of value types (such as "int" etc.). scala.AnyRef is super type of all "reference" types. But, method calls etc. work on value types as well. Examples:
  • 44.+(4) is same as 44 + 4 where "+" is a method on scala.Int class.
  • Also, single argument methods can be called using "infix" notation just like operator methods are. Example: System exit 4 is same as System.exit(4)
interfaces

interface Runnable {
void run();
}
Use traits. Traits are like interface but can have method bodies (i.e., not just method declarations). See also: multiple inheritance.

trait Runnable {
def run(): unit;
}
Multiple inheritance No. Only multiple interfaces may be implemented. Only single class may be extended. Multiple classes can not be extended. Multiple traits can be. And traits can have code -- not just declarations.

trait Runnable {
// parameter accepting run method
def run(obj: AnyRef) : unit;

// no params - assuming "null" instead
def run() : unit = {
System.out.println("assuming null...");
run(null);
}
}

// extend a single class, but can "extend"
// multiple traits with "with"

class MyClass extends AnyRef with Runnable {
// just implement run with param.
// Other "run" is inherited from Runnable
def run(obj: AnyRef) : unit = {
System.out.println("got " + obj);
}
}
See also: Scala mixins, mixins paper, traits paper.
Inner classes

public class Book {
private String name;
// ...

public Order newOrder() {
...
}

public class Order {
private Date orderDate;
private int quantity;
// ...
}
}

class Book(name: String) {

class Order(orderDate: Date,
quantity : int) {
}

def newOrder() : Order {
return new Order(new Date(), 1);
}
}

Unlike Java where such inner classes are members of the enclosing class, in Scala inner classes are bound to the outer object. With the above classes, in Java you can write


// Java
Book freakonomics = new Book("Freakonomics");
Book letUsKillGandhi = new Book("Let us kill Gandhi");
Book.Order o1 = freakonomics.newOrder();
Book.Order o2 = letUsKillGandhi.newOrder();

// You can assign any Book.Order
// to any other Book.Order

o2 = o1;

// Not in Scala!
val freakonomics: Book = new Book("freakonomics");
val letUsKillGandhi : Book = new Book("Let us kill Gandhi");
var o1 = freakonomics.newOrder();
var o2 = letUsKillGandhi.newOrder();

// this line below will not compile!
// type of "o1" is "freakonomics.Order"
// and type of "o2" is "letUsKillGandhi.Order"

o2 = o1;
In other words, order for "Freakonomics" book can not be treated as instance of order for "Let us kill Gandhi"! If you really want to refer to inner class type as in Java, you can use the following:

var o1 : Book#Order = freakonomics.newOrder();
var o2 : Book#Order = letUsKillGandhi.newOrder();
o1 = o2;
See also: Scala inner classes.
Class literals [section 15.8.2 of JLS].

String.class
Object.class

classOf[String]
classOf[AnyRef]
See also: Scala classOf.
Dynamic type check

x instanceof String
n instanceof Number

x.isInstanceOf[String]
n.isInstanceOf[Number]
Dynamic type cast

String x = (String) obj;
Number n = (Number) obj;

x : String = obj.asInstanceOf[String];
n : Number = obj.asInstanceOf[Number];
Generics

// an interface with a type parameter
interface Stack<E> {
void push(T t);
T pop();
boolean isEmpty();
}

// a class with two type parameters
class Pair<K, V> {
private K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
// more code...
}

// a trait with a type parameter
trait Stack[E] {
def push(o: E) : unit;
def pop() : E;
def isEmpty(): boolean;
}

// a class with two type parameters
class Pair[K, V](key: K, value: V) {
// code here...
}
See also: Scala generics.
Generic methods

class Test {
public <T> List<T> dup(T t, int n) {
//....
}
}

class Test {
def dup[T](x: T, n: Int): List[T] = {
if (n == 0) Nil
else x :: dup(x, n - 1)
}
}
See also: Scala polymorphic methods.
Bounded type parameter

// upper bound
class Foo<E extends SomeType> {
// ... code here
}

// lower bound
class Foo<E super SomeType> {
// ...
}

// type parameter in bound
class Stack<E extends Comparable<E>> {
// ...
}

// upper bound
class Foo[E <: SomeType] {
// ...
}

// lower bound
class Foo[F >: SomeType] {
// ...
}

// type parameter in bound
class Stack[E extends Comparable[E]] {
// ...
}
Wildcards

// upper bound
ArrayList<? extends Number> l = ...

// lower bound
ArrayList<? super Number> l = ...

// wildcard without bound
List<?> list = ...
See also: Wildcards paper
In Java, variance annotations are specified by "clients" [a.k.a use-site]. In Scala, if you want Foo[A] to be subtype of Foo[B] whenever A is subtype of B, you have to declare Foo as

// annotation +T declares type T to be used
// only in covariant positions.
class Foo[+A] {
// ...
}


// annotation -T declares type T to be used
// only in contravariant positions.
class Foo[-A] {
}

Example: In Scala, Lists are immutable and List has covariant annotation. So, List[B] is subtype of List[A] whenever B is subtype of A.

See also: Scala variances
Arrays

String[] s = new String[10];

var s : Array[String] = new Array[String](10);
Array is a generic type in Scala (much like "Vector", "List" etc. in Java are). Note: Arrays do not follow the covariant subtype rule. i.e., Array[Graduate] is not a subtype of Array[Person] even if Graduate is subtype of Person - this is unlike Java language in which Graduate[] is a subtype of Person[].
Array element access, update

int[] a = new int[3];
a[0] = 3;
System.out.println(a[0]);

var a : Array[int] = new Array[int](3);
a(0) = 3;
System.out.println(a(0));

Array element access and update are actually method
calls on Array[T]. You may be wondering how method call
appears on the right side (for element update). No,
Scala does not have C++ style reference (&) types.
a(i) = 10 is translated as a.update(i, 10)
Varargs

class Calc {
public static int sum(int... values) {
int res;
for (int i in values) {
res += i;
}
return res;
}
}

// with the above definition, caller can use
Calc.sum(3, 44)
Calc.sum(4, 4, 5,45, 45);
With '...' after type of last parameter, your method becomes variadic. The type of "values" in above example is int[]. In general, the type would be T[], if the last param type was T....

object Calc {
def sum(values: int*): int = {
var res: int = 0;
for (val v <- values) {
res = res + 1;
}
return res;
}
}

// With the above definition, caller can use
Calc.sum(3, 44);
Calc.sum(4, 5, 6, 6);
With '*' for the last parameter, your method becomes variadic. The type of "values" in above example is Seq[int]. In general, the type would be Seq[T], if the last param type was T*.
Type inference Only for generic methods ( possible future improvements?) Supported everywhere possible. Examples:
  • You can leave types for in var and val. Based on initial value type is inferred.
  • You can leave return type for non-recursive methods as well. Based on return expression return type is inferred.

// int type for "i" inferred
val i = 10;

// String type for "s" inferred
var s = "hello"

// "int" return type inferred
def add(i: int, j:int) = i * j

// "unit" return type inferred
def sayHello = System.out.println("hello world")

// scala.List[java.lang.String] inferred
var v = List("hello", "world");

// with class Pair[K, V](k: K, v: V) {...}
// Pair[int, String] is inferred for the following.
var p = new Pair(2, "hello");
See also: Scala type inference.
Functions, anonymous functions and closures Not yet. May be in future?. Yes. Can define functions, anonymous functions and closures anywhere -- except in top-level scope (compilation unit level).

// function
def add(i: int, j: int) = i + j

// functions are first-class objects
// accepts a callback function as parameter
def oncePerSecond(callback: ()=>unit): unit = {
while (true) { callback(); Thread.sleep(1000);
}

def printHello() = {
System.out.println("hello world");
}

// pass printHello as parameter
oncePerSecond(printHello);

// define anonymous function and call it
((i:int, j:int) => i+j)(3, 4)

// anonymous function passed as parameter
oncePerSecond(()=>System.out.println("hello"));

// nested functions too
def outer() = {
def inner() = {
System.out.println("I am inner");
}
inner();
}

// inner functions can access outer's locals
// and arguments
def outer(s: String) = {
def inner() = {
System.out.println("outer's 's': " + s);
}
inner();
}

// Java closure proposals talk about converting
// closures to interfaces automatically. I think
// we can use views in Scala.

// define conversion from any parameterless function
// to java.lang.Runnable
implicit
def asRunnable(func : ()=>unit) : Runnable = {
new Runnable() {
def run() {
func()
}
}
}

def main ( args : Array[String] ) = {
// create a new thread -
// passing an anonymous function
// for Runnable
var t = new Thread(()=>Console.println("hello"));
t.start();

// you can now initialize Runnable
// with any function
var r : Runnable = ()=>Console.println("I am running!")
r.run();
}
See also: Scala views.
List support Use java.util.List and classes implementing it.

// create a List with "List" function (which is actually
// an object with "apply")

var names : List[String] = List("Java", "JavaScript")

// :: is the cons operator
// creates a new list with first element as "Scala"
// and rest of the elements from "names" list
val l = "Scala" :: names

// :: becomes method call on List -- unlike
// other operators :: takes right-side value
// as list as target object to call method on!
Lists in Scala are immutable. There are methods on List class - like map, filter etc. that accept closure arguments. Examples:


// make a new list that contains only short names
// shortNames is of type List[String]
var shortNames = names.filter(n=>n.length() < 6)

// make a new list that has lengths of names
// "lengths" is of type List[int]
var lengths = names.map(n=>n.length())
scala.List has covariant type parameter [note: Lists are immutable]. So, List[Graduate] is subtype of List[Person] if Graduate is subtype of Person.

val graduates:List[Graduate] =...
val persons:List[Person] = graduates;

metadata block
see also:
Correspondence about this page

This site may have errors. Don't use for critical systems.

Copyright (c) 1998-2023 Martin John Baker - All rights reserved - privacy policy.