(点击
上方公众号
,可快速关注)
英文:Scala School
译文:朱伟杰
如需转载,发送「转载」二字查看说明
这个章节主要讲解Scala和Java进行互操作。
-
Javap
-
类
-
异常
-
Trait
-
对象
-
闭包函数(closures functions)
Javap
javap是JDK附带的一个工具,而不是JRE。它们之间还是有差别的。Javap反编译class文件,并且向你展示它里面放的是什么。使用起来很简单。
[local ~/projects/interop/target/scala_2.8.1/classes/com/twitter/interop]$ javap MyTrait
Compiled from "Scalaisms.scala"
public interface com.twitter.interop.MyTrait extends scala.ScalaObject{
public abstract java.lang.String traitName();
public abstract java.lang.String upperTraitName();
}
如果你想了解底层的话,你可以查看对应的字节码
[local ~/projects/interop/target/scala_2.8.1/classes/com/twitter/interop]$ javap -c MyTrait\$class
Compiled from "Scalaisms.scala"
public abstract class com.twitter.interop.MyTrait$class extends java.lang.Object{
public static java.lang.String upperTraitName(com.twitter.interop.MyTrait);
Code:
0: aload_0
1: invokeinterface #12, 1; //InterfaceMethod com/twitter/interop/MyTrait.traitName:()Ljava/lang/String;
6: invokevirtual #17; //Method java/lang/String.toUpperCase:()Ljava/lang/String;
9: areturn
public static void $init$(com.twitter.interop.MyTrait);
Code:
0: return
}
如果你在Java平台上有什么问题,你可以通过javap来排查。
类
从Java的角度来使用Scala的_class_需要注意的四个要点如下:
我们来创建一个简单的scala类来展示这几个要点
package com.twitter.interop
import java.io.IOException
import scala.throws
import scala.reflect.{BeanProperty, BooleanBeanProperty}
class SimpleClass(name: String, val acc: String, @BeanProperty var mutable: String) {
val foo = "foo"
var bar = "bar"
@BeanProperty
val fooBean = "foobean"
@BeanProperty
var barBean = "barbean"
@BooleanBeanProperty
var awesome = true
def dangerFoo() = {
throw new IOException("SURPRISE!")
}
@throws(classOf[IOException])
def dangerBar() = {
throw new IOException("NO SURPRISE!")
}
}
类参数
class SimpleClass(acc_: String) {
val acc = acc_
}
下面就可以通过Java代码来访问它们了。
常量(Val)
变量(Var)
foo$_eq("newfoo");
BeanFactory
你可以通过@BeanProperty注解来标注val和var。这样就会生成类似于POJO的getter/setter方法。假如你想要访问isFoo变量,使用BooleanBeanProperty注解。那么难以理解的foo$eq就可以换成:
setFoo("newfoo");
getFoo();
异常
Scala里没有受检异常(checked exception),但是Java里有。这是一个语言层面上的问题,我们这里不进行讨论,但是在Java里你对异常进行捕获的时候你还是要注意的。dangerFoo和dangerBar的定义里对这进行了示范。在Java里,你不能这样做。
// exception erasure!
// 异常擦除!
try {
s.dangerFoo();
} catch (IOException e) {
// UGLY
// 非常丑陋
}
Java编译器会因为s.dangerFoo不会抛出IOException而报错。我们可以通过捕获Throwable来绕过这个错误,但是这样做没多大用处。
不过,作为一个Scala用户,比较正式的方式是使用throws注解,就像我们之前在dangerBar上的一样。这个手段使得我们能够使用Java里的受检异常(checked exception)。
延伸阅读
支持Java互操作的注解的完整列表在http://www.scala-lang.org/node/106。
Trait
我们怎样可以得到一个接口和对应的实现呢?我们简单看看trait的定义
trait MyTrait {
def traitName:String
def upperTraitName = traitName.toUpperCase
}
这个trait有一个抽象的方法(traitName)和一个已实现的方法(upperTraitName)。对于这样的trait,Scala会生成什么样的代码呢?它会生成一个MyTrait接口,同时还会生成对应的实现类MyTrait$class。
MyTrait的实现和你猜想的差不多:
[local ~/projects/interop/target/scala_2.8.1/classes/com/twitter/interop]$ javap MyTrait
Compiled from "Scalaisms.scala"
public interface com.twitter.interop.MyTrait extends scala.ScalaObject{