31장 Combining Scala and Java - codeport/scala GitHub Wiki

31.1 Using Scala from Java

Value types:

  • Intint로 가능하면 int로 안되면 java.lang.Integer로 컴파일된다.

Singleton Objects:

object App {
  def main(args: Array[String]) {
    println("Hello, world!")
  }
}

컴파일해서 디컴파일 하면

App.class:

import scala.reflect.ScalaSignature;

@ScalaSignature(bytes=" ... ")
public final class App
{
  public static void main(String[] paramArrayOfString)
  {
    App..MODULE$.main(paramArrayOfString);
  }
}

App$.class:

import scala.Predef.;

public final class App$
{
  public static final  MODULE$;

  private App$()
  {
    MODULE$ = this;
  }

  public void main(String[] args)
  {
    Predef..MODULE$.println("Hello, world!");
  }

  static
  {
    new ();
  }
}

Traits as interfaces:

Trait은 인터페이스로 컴파일된다. App에 아래와 같은 Trait을 추가해보자:

trait Trait {
  def method() = println("method")
}

object App extends Trait {
  def main(args: Array[String]) {
    println("Hello, world!")
  }
}

그리고 다시 디컴파일 하면:

App$.class:

import scala.Predef.;

public final class App$
  implements Trait
{
  public static final  MODULE$;

  public void method()
  {
    Trait.class.method(this);
  }

  private App$()
  {
    MODULE$ = this;Trait.class.$init$(this);
  }

  public void main(String[] args)
  {
    Predef..MODULE$.println("Hello, world!");
  }

  static
  {
    new ();
  }
}

App.class:

import scala.reflect.ScalaSignature;

@ScalaSignature("...")
public final class App
{
  public static void method()
  {
    App..MODULE$.method();
  }

  public static void main(String[] paramArrayOfString)
  {
    App..MODULE$.main(paramArrayOfString);
  }
}

Trait$class.class:

import scala.Predef.;

public abstract class Trait$class
{
  public static void method(Trait $this)
  {
    Predef..MODULE$.println("method");
  }

  public static void $init$(Trait $this) {}
}

Trait.class:

import scala.reflect.ScalaSignature;

@ScalaSignature(bytes="...")
public abstract interface Trait
{
  public abstract void method();
}

Trait으로 만들어 mixin 하면 해당 이름의 인터페이스를 만들고 mix한 클래스에 인터페이스를 구현한다.

31.2 Annotations

Annotation은 먼저 Scala rule을 적용하고 그다음에 Java rule을 적용한다.

  • @deprecated: Java의 @deprecated가 그대로 사용된다.
  • @volitile: Java의 volitile Modifier로 컴파일한다.
  • @serializable: Serializable 인터페이스를 구현하도록 추가된다.
  • @SerialVersionUID(1234L): private final static long SerialVersionUID = 1234L라는 필드를 추가한다.
  • @transient: Java의 transient Modifier로 컴파일한다.
  • Exception throwns: Scala는 Checked Exception이 없으니 throws 키워드가 없지만, Java에는 있으니 이를 위해 @throws Annotation이 있다:
@throws(classOf[IOException])
def read() = in.read()

throws 키워드로 컴파일한다:

public int read() throws java.io.IOException;
  • Java Annotation은 그냥 그대로 쓴다.
  • Annotation을 직접 만들 때는 Java로 만들어서 javac로 컴파일해야 한다. 그래야 Java Reflection에서 알 수 있다.

31.3 Existential types

  • Java Iterator<T>는 Scala의 Iterator[T]에 대응되지만 Iterator<?> 같은 wildcard는 예외다.
  • Existential types의 General form은 type forSome { declarations }이다. 아래와 같이 사용한다^1:
class Foo[A]

type Outer = List[Foo[T]] forSome { type T }
type Inner = List[Foo[T] forSome { type T }]
  • Java Iterator<?>는 Scala의 Iterator[T] forSome { type T }와 같고 placeholder syntax로는 Iterator[_]다.
  • Java Iterator<? extends Component>는 Scala의 Iterator[T] forSome { type T <: Component }와 같고 placeholder syntax로는 Iterator[ _ <: Component ]다.

forSome이랑 placeholder랑 같은 것 같은데(이것도 맞나?) 왜 두 개 있는지 모르겠음.

31.4 Using synchronized

  • Scala도 wait, notify, notifyAll가 있고 Java처럼 사용하고 동작한다.
  • Scala의 synchronized는 메소드다:
var counter = 0
synchronized {
  // One thread in here at a time
  counter = counter + 1
}

31.5 Compiling Scala and Java together

  • scalac는 Java 소스도 컴파일한다.

31.6 Conclusion