<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                課程內容涵蓋了Java互操作性。 [TOC=2,2] ## 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](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"; } }); } ~~~ 注意我們可以使用泛型參數。 Built at?[@twitter](http://twitter.com/twitter)?by?[@stevej](http://twitter.com/stevej),?[@marius](http://twitter.com/marius), and?[@lahosken](http://twitter.com/lahosken)?with much help from?[@evanm](http://twitter.com/evanm),?[@sprsquish](http://twitter.com/sprsquish),?[@kevino](http://twitter.com/kevino),?[@zuercher](http://twitter.com/zuercher),?[@timtrueman](http://twitter.com/timtrueman),?[@wickman](http://twitter.com/wickman), and[@mccv](http://twitter.com/mccv); Russian translation by?[appigram](https://github.com/appigram); Chinese simple translation by?[jasonqu](https://github.com/jasonqu); Korean translation by?[enshahar](https://github.com/enshahar); Licensed under the?[Apache License v2.0](http://www.apache.org/licenses/LICENSE-2.0).
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看