多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

中國最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2

scala教程

Java 與 Scala

閱讀 (2329)

Java 與 Scala

Javap

javap 的是 JDK 附帶的一個工具。不是 JRE,這里是有區別的。javap 反編譯類定義,給你展示里面有什么。用法很簡單

[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 類 時要考慮的四個要點

  • 類參數
  • 類常量
  • 類變量
  • 異常

我們將構建一個簡單的 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!")
  }
}

類參數

  • 默認情況下,類參數都是有效的 Java 構造函數的參數。這意味著你不能從類的外部訪問。
  • 聲明一個類參數為 val/var 和這段代碼是相同的
class SimpleClass(acc_: String) {
  val acc = acc_
}

這使得它在 Java 代碼中就像其他常量一樣可以被訪問

類常量

  • 常量(val)在 Java 中定義了一個獲取方法。你可以通過方法“foo()”訪問“val foo”的值

類變量

  • 變量(var)會生成一個 _$eq 方法。你可以這樣調用它
foo$_eq("newfoo");

BeanProperty

你可以通過 @BeanProperty 注解 val 和 var 定義。這會按照 POJO 定義生成 getter/setter 方法。如果你想生成 isFoo 方法,使用 BooleanBeanProperty 注解。丑陋的 foo$_eq 將變為

setFoo("newfoo");
getFoo();

異常

Scala 沒有像 Java 那樣有受檢異常(checked exception)。需不需要受檢異常是一個我們不會進入的哲學辯論,不過當你需要在Java中捕獲它時就 很重要 了。dangerFoo 和 dangerBar 將演示這一點。在 Java 中不能這樣做

        // exception erasure!
        try {
            s.dangerFoo();
        } catch (IOException e) {
            // UGLY
        }

Java 會抱怨說 s.dangerFoo 從未拋出過 IOException 異常。我們可以通過捕獲 Throwable 來跳過,但是這樣不好。

相反,作為一個良好的 Scala 公民,可以很體面地像在 dangerBar 中那樣使用 throws 注解。這使我們能夠繼續在 Java 中使用受檢異常。

進一步閱讀

支持 Java 互操作的 Scala 注解的完整列表在這里 http://www.scala-lang.org/node/106

特質

你如何獲得一個接口+實現?讓我們看一個簡單的特質定義

trait MyTrait {
  def traitName:String
  def upperTraitName = traitName.toUpperCase
}

這個特質有一個抽象方法(traitName)和一個實現的方法(upperTraitName)。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{
    public abstract java.lang.String traitName();
    public abstract java.lang.String upperTraitName();
}

MyTrait$class 更有趣

[local ~/projects/interop/target/scala_2.8.1/classes/com/twitter/interop]$ javap 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);
    public static void $init$(com.twitter.interop.MyTrait);
}

MyTrait$class 只有以 MyTrait 實例為參數的靜態方法。這給了我們一個如何在 Java 中來擴展一個特質的提示。

首先嘗試下面的操作

package com.twitter.interop;

public class JTraitImpl implements MyTrait {
    private String name = null;

    public JTraitImpl(String name) {
        this.name = name;
    }

    public String traitName() {
        return name;
    }
}

我們會得到以下錯誤

[info] Compiling main sources...
[error] /Users/mmcbride/projects/interop/src/main/java/com/twitter/interop/JTraitImpl.java:3: com.twitter.interop.JTraitImpl is not abstract and does not override abstract method upperTraitName() in com.twitter.interop.MyTrait
[error] public class JTraitImpl implements MyTrait {
[error]        ^

我們 可以 自己實現。但有一個鬼鬼祟祟的方式。

package com.twitter.interop;

    public String upperTraitName() {
        return MyTrait$class.upperTraitName(this);
    }

我們只要把調用代理到生成的 Scala 實現上就可以了。如果愿意我們也可以覆蓋它。

單例對象

單例對象是 Scala 實現靜態方法/單例模式的方式。在 Java 中使用它會有點奇怪。沒有一個使用它們的完美風格,但在 Scala2.8 中用起來并不很糟糕

一個 Scala 單例對象會被編譯成由“$”結尾的類。讓我們創建一個類和一個伴生對象

class TraitImpl(name: String) extends MyTrait {
  def traitName = name
}

object TraitImpl {
  def apply = new TraitImpl("foo")
  def apply(name: String) = new TraitImpl(name)
}

我們可以像這樣天真地在 Java 中訪問

MyTrait foo = TraitImpl$.MODULE$.apply("foo");

現在你可能會問自己,這是神馬玩意?這是一個正常的反應。讓我們來看看 TraitImpl$ 里面實際上是什么

local ~/projects/interop/target/scala_2.8.1/classes/com/twitter/interop]$ javap TraitImpl\$
Compiled from "Scalaisms.scala"
public final class com.twitter.interop.TraitImpl$ extends java.lang.Object implements scala.ScalaObject{
    public static final com.twitter.interop.TraitImpl$ MODULE$;
    public static {};
    public com.twitter.interop.TraitImpl apply();
    public com.twitter.interop.TraitImpl apply(java.lang.String);
}

其實它里面沒有任何靜態方法。取而代之的是一個名為MODULE$的靜態成員。方法實現被委托給該成員。這使得訪問代碼很難看,但卻是可行的。

轉發方法(Forwarding Methods)

在 Scala2.8 中處理單例對象變得相對容易一點。如果你有一個類與一個伴生對象,2.8 編譯器會生成轉發方法在伴生類中。所以,如果你用 2.8,你可以像這樣調用 TraitImpl 單例對象的方法

MyTrait foo = TraitImpl.apply("foo");

閉包函數

Scala 的最重要的特點之一,就是把函數作為頭等公民。讓我們來定義一個類,它定義了一些以函數作為參數的方法。

class ClosureClass {
  def printResult[T](f: => T) = {
    println(f)
  }

  def printResult[T](f: String => T) = {
    println(f("HI THERE"))
  }
}

在 Scala 中可以像這樣調用

val cc = new ClosureClass
cc.printResult { "HI MOM" }

在 Java 中卻不那么容易,不過也并不可怕。讓我們來看看 ClosureClass 實際上被編譯成什么:

[local ~/projects/interop/target/scala_2.8.1/classes/com/twitter/interop]$ javap ClosureClass
Compiled from "Scalaisms.scala"
public class com.twitter.interop.ClosureClass extends java.lang.Object implements scala.ScalaObject{
    public void printResult(scala.Function0);
    public void printResult(scala.Function1);
    public com.twitter.interop.ClosureClass();
}

這也不是那么恐怖。“f: => T”被轉義成“Function0”,“f: String => T”被轉義成“Function1”。Scala 實際上從 Function0 定義到 Function22,最多支持 22 個參數。這真的應該足夠了。

現在我們只需要弄清楚如何在 Java 中使用這些東東。我們可以傳入 Scala 提供的 AbstractFunction0 和 AbstractFunction1,像這樣

    @Test public void closureTest() {
        ClosureClass c = new ClosureClass();
        c.printResult(new AbstractFunction0() {
                public String apply() {
                    return "foo";
                }
            });
        c.printResult(new AbstractFunction1<String, String>() {
                public String apply(String arg) {
                    return arg + "foo";
                }
            });
    }

注意我們可以使用泛型參數。

關閉
程序員人生
主站蜘蛛池模板: 直接在线观看的三级网址 | 午夜网站在线播放 | 能看毛片的网址 | 日本乱码一卡二卡三卡永久 | h视频在线免费观看 | 久久亚洲欧洲日产国码 | 亚洲免费视 | 校园春色激情网 | 精品视频在线观看一区二区三区 | 久久亚洲一区二区 | 欧美黑人在线视频 | 日本黄色免费片 | 最新日本免费一区二区三区中文 | 欧美高清精品videossex | 东京干男人都知道的网站 | 久久久精品456亚洲影院 | 亚洲久久在线 | 不卡欧美 | 亚洲高清免费视频 | 爱爱小视频免费体验区在线观看 | 多人做人爱视频大全在线观看 | 一区二区三区成人 | 六月亚洲精品一区 | 最新欧美18videosex性欧美 | 好看欧美视频高清va | 忘忧草wyc.apk | 亚洲区小说区激情区图片区 | 免费国产在线视频 | 欧美色图偷窥自拍 | 日韩欧美天堂 | 亚洲欧美成人综合在线 | 欧美日韩天堂 | 看毛片的网址 | 性生交酡 | 开操网 | 国产91成人精品亚洲精品 | 成人做爰免费视频免费看 | 在线国产毛片 | 国产99视频精品免视看7 | 一级作爱视频 | 中国老头gay高清xxxx |