読者です 読者をやめる 読者になる 読者になる

新人SEの学習記録

14年度入社SEの学習記録用に始めたブログです。気づけば社会人3年目に突入。

学習記録:ドワンゴ 新人向けScala研修テキスト

学習記録 関数型 プログラミング Scala

19. Javaとの相互運用

ScalaJava

ScalaJVM上で動作するため,JavaのライブラリのほとんどをそのままScalaから呼び出すことができる。
また,現状ではJavaの機能を利用せざるを得ないことがある。
Javaの機能といっても,Scalaの機能とほとんど同じように利用することができる。

import

Javaのライブラリをimportするためには,Scalaでほとんど同じことを記述すればよい。

import java.util._
import java.util.ArrayList

注意すべきは,Javaでのワイルドカードが*ではなく_になっている点である。

インスタンスの生成

インスタンスの生成もJavaと同様にできる。

scala> import java.util._
import java.util._

scala> val list = new ArrayList[String]()
list: java.util.ArrayList[String] = []

上記は,ArrayList list = new ArrayList<>();に対応する。

インスタンスメソッドの呼び出し

こちらも同様。

scala> list.add("hello")
res0: Boolean = true

scala> list.add("world")
res1: Boolean = true

scala> list
res2: java.util.ArrayList[String] = [hello, world]
staticメソッドの呼び出し

staticメソッドの呼び出しも同様に可能だが,Scalaではstaticメソッドは継承されない(というかstaticメソッドという概念がない)という点に注意が必要である。
つまり,クラスAがstaticメソッドfooを持っていても,Aを継承したクラスBについてB.foo()とすることはできず,A.foo()としなければならない。

scala> System.currentTimeMillis
res3: Long = 1470559909192
staticフィールドの参照

staticフィールドもstaticメソッドと同様継承されない。
Javaであれば,JFrameを継承したクラスでフィールドEXIT_ON_CLOSEを使用できるが,Scalaの場合はJFrame.EXIT_ON_CLOSEと書く必要がある。

Scalaの型とJavaの型のマッピング

Javaの型は適切にScalaマッピングされる。

Javaの型 Scalaの型
void scala.Unit
boolean scala.Boolean
byte, short, int, long, char, float, double scala.Byte, ..., scala.Double
java.lang.Object scala.AnyRef
java.lang.String java.lang.String
nullとOption

Scalaの世界ではnullを使うことはなく,代わりにOption型を使う。
一方,Javaのメソッドを呼び出したりすると,返り値としてnullが返ってくることがある。
幸いにも,ScalaではOption(value)とすることでvalueがnullのときにNoneを,nullでないときにSome(value)を返すことができる。

scala> val map = new java.util.HashMap[String, Int]()
map: java.util.HashMap[String,Int] = {}

scala> map.put("A", 1)
res0: Int = 0

scala> Option(map.get("A"))
res1: Option[Int] = Some(1)

scala> Option(map.get("B"))
res2: Option[Int] = None

このように,Scalaの世界からJavaのメソッドを呼び出すときは,返り値をできるだけOption()でくるむよう意識するべきである。

JavaConverters

JavaのコレクションとScalaのコレクションはインタフェースに互換性がないので,JvaConverterを使う必要がある。

import scala.collection.JavaConverters._

これで,JavaScalaのコレクションのそれぞれにasJava()やasScala()といったメソッドが追加されるので,以下のように呼び出せばよい。

scala> import scala.collection.JavaConverters._
import scala.collection.JavaConverters._

scala> val list = new java.util.ArrayList[String]()
list: java.util.ArrayList[String] = []

scala> list.add("A")
res3: Boolean = true

scala> list.add("B")
res4: Boolean = true

scala> val scalaList = list.asScala
scalaList: scala.collection.mutable.Buffer[String] = Buffer(A, B)