X

Sundararajan's Weblog

  • Java |
    March 4, 2007

Scala for Java programmers

There are many languages that target to the Java Virtual Machine (JVM)
-- not just the scripting and dynamically typed ones. How about learning another statically typed language
that is compiled JVM and seamlessly integrates to the Java platform? The
latest mantra is "One Great VM, Many Languages", Right? :-)

We will look at - Scala? - a functional,
object-oriented and concurrent language that runs on the Java platform. Note:
this is not a language comparison exercise [i.e., X versus Y comparison to
"conclude" which one is better!]. Rather, it is an attempt to give head-start to the Java programmers
who want to learn other languages that run on the Java platform. So, the aim is
same as it was for my blog past entries such as Java, Groovy and (J)Ruby,
Java, JavaScript and Jython -
except that we are now looking at a statically typed language...

















































































































































































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 heredef 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 constructorthis(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" constructorthis(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;

There is much more to Scala - pattern matching, for-comprehension, exception handling, packages, abstract types, XML literals, currying, implicit parameters etc. But, we have had enough for a single blog entry :-)

To be continued.. stay tuned!

Join the discussion

Comments ( 9 )
  • Someone Monday, March 5, 2007
    Are there option types in Scala (like in Nice)?
    Something like this:
    var text? = null;
    Question mark means that value can hold a null and needs to be checked before use. Otherwise assigning null is not possible:
    var text = null; // Compiler throws exception
  • Vaibhav Monday, March 5, 2007
    So tell me one thing, dont you think Java packet means j2sdk is going heavier and heavier. Can we have a different download options for this new ADVANCE j2sdk which I guess going to cover 22+ language engine, right now and keep on increasing !!
  • A. Sundararajan Monday, March 5, 2007
    On option types (like in Nice): it does not seem that such a facility is available with Scala.
    Vaibhav: I am sorry I don't get the context of your comment. Would you please clarify?
  • Vaibhav Choudhary Monday, March 5, 2007
    Yes Sundar, I want to say that all these code go into jdk. As I read jdk 1.7 is going to cover 22 other languages like jruby, jython and all. So, putting all these code in jdk, cant make it too much bulky ? I guess the current size of jdk is something around 60MB(offline installation).
  • A. Sundararajan Monday, March 5, 2007
    No! I do not think \*all\* these scripting (or otherwise) languages will become
    part of JDK/JRE!
  • Robert Tuesday, March 6, 2007
    Scala seems to me to be a great JVM language.
  • David Pollak Tuesday, March 6, 2007
    This is a nice list of differences between Scala and Java. A couple of things:
    Scala has an Option class which works really well:
    <code>
    def foo(maybe: Option[String]) {
    Console.println("The parameters is "+(maybe getOrElse "Nothing"))
    }
    def byQuery(where: Option[String], order: Option[String]): String = {
    var query = "SELECT \* FROM foo"
    where.foreach(w => query = query + " WHERE "+w)
    order.foreach(o => query = query + " ORDER BY "+o)
    query
    }

    </code>
    There are lots of other things that can be done with Option.
    Scala supports abstract methods on Traits and Abstract classes:
    <code>
    abstract class Foo {
    def bar: String // I'm abstract
    def baz(in: int): List[String] = List(in.toString) // I'm not abstract
    }

    </code>
  • Rich Dougherty Tuesday, March 6, 2007

    Thanks - really great summary!

    Another great thing about Scala, not explicitly mentioned above, is the fact that Scala integrates really nicely with Java. You can implement Java interfaces, extend Java classes, call Java methods, and so on.

    An example on the Scala website shows how natural this is.

  • guest Wednesday, March 7, 2007
    Hi All: Thank you all for pointing me to the stuff I left out.
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.Captcha
Oracle

Integrated Cloud Applications & Platform Services