Scala versus Java

by Stephane Micheloud, July 2009

[Home]
[Back]

Scala sets a new milestone in the evolution of modern programming languages with its unification of programming paradigms and its emancipation from unlucky Java language features. Java itself achieved a similar shift from C/C++ fifteen years ago and moreover became a mainstream language.

Similarities

Differences

Main differences are:

Further differences are:

Examples

  1. In Scala try-catch-finally returns a value. []

    object ClientApp {
      private val SRV_HOST =
        System.getProperty("SRV_HOST", "localhost")
      private val SRV_PORT =
        try System.getProperty("SRV_PORT", "8080").toInt
        catch { case e: NumberFormatException => 8080 }
      def main(args: Array[String]) { /* .. */ }
    }
    

    The same program written in Java:

    public class ClientApp {
        private static final String SRV_HOST =
            System.getProperty("SRV_HOST", "localhost");
        private static /*final*/ int SRV_PORT;
        static {
            try { SRV_PORT = Integer.parseInt(System.getProperty("SRV_PORT", "8080")); }
            catch (NumberFormatException e) { SRV_PORT = 8080; }
        }
        public static void main(String[] args) { /* .. */ }
    }
  2. Examples of Scala literals are []

    // File literals.scala
    object literals extends App {
      val twice = (x: Int) => x * 2
      val usage = """Usage: scalac <options> <source files>
        |where possible standard options include:
        |...""".stripMargin
      val levels = ('info, 'warning, 'error)
      val link =
        <a class="external"
           href="http://scala-lang.org">Scala <em>2</em></a>
    
      println(twice(3))
      println(usage)
      println(levels)
      println(link)
    }

    Output:

    6
    Usage: scalac <options> <source files>
    where possible standard options include:
    ...
    ('info,'warning,'error)
    <a class="external" href="http://scala-lang.org">Scala</a>
  3. Examples of Scala imports []

    // File imports.scala
    import /*static*/ java.util.Collections._
    import java.util.ArrayList
    
    object imports extends App {
      val xs = emptyList[Int]()
      val ys = new ArrayList(xs); ys add 1
    
      import java.util.LinkedList
      val zs = new LinkedList(ys); zs add 2
    
      val v1 = Vector() ++ List(1, 2)
      println(v1+"\t"+v1.getClass.getName)
      
      println {
        import java.util.Vector
        val v2 = new Vector(zs)
        v2+"\t"+v2.getClass.getName
      }
    }

    Output:

    Vector(1, 2)	scala.collection.immutable.Vector
    [1, 2]	java.util.Vector
  4. In Java the protected modifier gives access both to subclasses and to members of the same package. In Scala access is granted to subclasses only. []
    For instance:

    // File protected.scala
    package example
    class Person {
      protected def nickname = "Nick"
    }
    class Student {
      private var p = new Person()
      override def toString = p.nickname
    }

    Output:

    error: method nickname in class Person \
    cannot be accessed in example.Person
     Access to protected method nickname not permitted ..
  5. In Java, arrays are covariant, e.g. String <: CharSequence implies String[] <: CharSequence[].
    Concretely one may write the following code in Java: []
    public class TestArrays {
        static void f(CharSequence[] a) {
            for (CharSequence s : a) System.out.println(s);
        }
        public static void main(String[] args) {
            f(args);
        }
    }

    In Scala, arrays are invariant. The above code must be slightly adapted in order to compile: one can either widen the type of args ([1]) before passing it to method f or define another method g ([2]) as follows:

    object arrays {
      def f(a: Array[CharSequence]) { a foreach println }
      def g[T<: CharSequence](a: Array[T]) { a foreach println } // [2]
      def main(args: Array[String]) {
        f(Array[CharSequence](args: _*)) // [1]
        g(args)
      }
    }
  6. ...

    class A {
        class B {
            @Override
            public String toString() { return getClass().getName(); }
        };
        @Override
        public String toString() { return getClass().getName(); }
        public B newB() { return new B(); }
    }
    public class ex1 {
        public static void main(String[] args) {
            A a = new A();
            //A.B b = new a.B();  // error: package a does not exist
            A.B b = a.newB();
            System.out.println(a);
            System.out.println(b);
        }
    }

    The same program written in Scala:

    class A {
      class B {
        override def toString = getClass.getName
      };
      override def toString = getClass.getName
    }
    object ex1 extends Application {
      val a = new A
      val b = new a.B
      println(a)
      println(b)
    }

    A
    A$B

References

About the Author

Stephane's Picture
Stéphane Micheloud is a senior software engineer. He holds a Ph.D in computer science from EPFL and a M.Sc in computer science from ETHZ. At EPFL he worked on distributed programming and advanced compiler techniques and participated for over six years to the Scala project. Previously he was professor in computer science at HES-SO // Valais in Sierre, Switzerland.
[Top]

Other Articles