Chapter 31《Combining Scala and Java》

从Java角度看Scala

  • scala一般要和Java在大型程序中使用,使用Java中的框架。Scala的实现方式是将代码翻译成为标准的Java字节码,Scala的特性尽可能地直接映射为Java中的特性。可以使用javap来查看.classScala进行的翻译。

1. 值类型

对于值类型,在能够确定的情况下,优先翻译成为Java中的值类型用以获得更好的性能,如果不能确定,则翻译为包装类型。

2. 单例对象

  • 采用静态和实例方法相结合的方式来翻译单例对象,如果是单个的对象,则生成类Test$Test
public final class Test$ {
  public static final Test$ MODULE$;
  public static {};
  public void main(java.lang.String[]);
  public java.lang.String select(java.lang.String[]);
}

其中,编译器插入了代码,保证在运行的时候私有化了Test$的构造方法,并对MODULE$进行了赋值。在Test类中

public final class Test {
  public static java.lang.String select(java.lang.String[]);
  public static void main(java.lang.String[]);
}

Test$中的所有方法在Test中都存在有static的转发版本。在书中说如果object有了对应的class,则在javaclass中不会添加额外的转发方法,但是在实际过程中发现即使有了对应的classjava中的class也添加了额外的转发方法。

3.接口

  • 特质被翻译成为接口。如果在特质中有实现的部分,使用abstract class进行实现。

注解

  • 主要讨论的是Java中的注解。如果是@deprecated,则在Java代码上也加入该注解,这样,当Java代码试图访问Scala中带有@deprecated的代码时,会抛出警告。@volatile也是同样的操作。对与序列化的注解,Scala中的@serializableJava中会翻译为实现了Serializable接口,@SerialVersionUID(1234L)被翻译成为
// Java serial version marker
private final static long SerialVersionUID = 1234L

@transient也是在Java代码上加上同样的注解。

1.异常抛出

  • Scala并不检查是由否有异常抛出,所以转换得到的所有Java代码都是不带throw的。因为在Java中,大程序可能就是吞下并隐藏了许多异常,所以在Scala中并不采用这种throwcatch的方法进行处理。如果生成的Java代码中必须要有throws异常的语法,则在scala中使用@throws的注解,
class Reader(fname: String) {
    private val in =
        new BufferedReader(new FileReader(fname))
    @throws(classOf[IOException])
    def read() = in.read()
}

2.Java注解

现在的Java框架注解都可以直接应用在Scala代码中。

3.定制注解

如果需要注解在Java反射的时候可以看到,则必须使用Java中的注解,并使用javac来编译它。因为Scala不能完全的支持Java中的注解,使用的反射机制也是Java的。可以这么使用:

import java.lang.annotation.*; // This is Java
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Ignore { }

object Tests {
  @Ignore
  def testData = List(0, 1, -1, 5, -5)
  def test1 = {
      assert(testData == (testData.head :: testData.tail))
  }
  def test2 = {
      assert(testData.contains(testData.head))
  }
}
for {
  method <- Tests.getClass.getMethods
  if method.getName.startsWith("test")
  if method.getAnnotation(classOf[Ignore]) == null // 使用的是Java中的反射API,所以比较使用的是null
} {
  println("found a test method: " + method)
}

使用的顺序如下所示:

$ javac Ignore.java
$ scalac Tests.scala
$ scalac FindTests.scala
$ scala FindTests
found a test method: public void Tests$.test2()
found a test method: public void Tests$.test1()

注意到这里是Tests$而不是Tests,因为使用的是Java中的反射API,所以在Tests.getClass.getMethods的时候类就是Tests$,而不是Test,同时注意在Java中的注解参数只能是常量,不能是x*2x是常量这种形式。

通配符类型

  • JavaScala是相通的,一般的转换都是非常简单的,Java中的Iterator<Component> 就是Scala中的Iterator[Component],但是如果在Java中存在有通配符的泛型,比如Iterator<?>或者Iterator<? extends Father>这样的类型,在Scala中有同样的成为通配符的进行匹配转换。使用的是占位符的思想,使用下划线作为通配符进行转换,Iterator<?>就是Iterator[_],表示一个Iterator,但是其中的类型是不明的。同样地,可以插入上限符号和下限符号来限制范围。Iterator[_ <: Father],表示必须是Father的子类,Iterator[_ >: Child],表示必须是Child的父类。

同时编译Scala代码和Java代码

  • 通常如果Scala代码依赖Java代码的话,首先编译Java代码生成对应的class文件,再编译Scala文件,将Java class文件放入到classpath中,如果在Java中同样引用了Scala代码,那么这个方法就失效了,Scala提供了一种解决这个问题的方法。

在Scala2.12中集成Java8

  • Java8中,任意一个需要一个类或者接口对象的地方都可以使用lamda表达式替代,这个类或者接口只能含有一个抽象的方法,叫Single Abstract Method对象,在Scala2.12中对SAM进行子类实现的时候,可以直接使用一个函数代替匿名类的实例。

在Scala2.12中使用Java8中的流

  • Java中的Stream是一个函数数据结构,提供了一个map方法。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342