日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Scala入门到精通——第二十八节 Scala与JAVA互操作

發布時間:2024/1/23 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Scala入门到精通——第二十八节 Scala与JAVA互操作 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本節主要內容

  • JAVA中調用Scala類
  • Scala中調用JAVA類
  • Scala類型參數與JAVA泛型互操作
  • Scala與Java間的異常處理互操作
  • 1. JAVA中調用Scala類

    Java可以直接操作縱Scala類,如同scala直接使用Java中的類一樣,例如:

    //在Person.scala文件中定義Scala語法的Person類 package cn.scala.xtwy.scalaToJava class Person(val name:String,val age:Int) //伴生對象 object Person{def getIdentityNo()= {"test"} } //ScalaInJava.java文件中定義了ScalaInJava類 //直接調用Scala中的Person類 package cn.scala.xtwy.scalaToJava;public class ScalaInJava {public static void main(String[] args) {Person p=new Person("搖擺少年夢", 27);System.out.println("name="+p.name()+" age="+p.age());//伴生對象的方法當做靜態方法來使用System.out.println(Person.getIdentityNo());} }

    對!就是這么簡單,Java似乎可以無縫操縱Scala語言中定義的類,在trait那一節中我們提到,如果trait中全部是抽象成員,則它與java中的interface是等同的,這時候java可以把它當作接口來使用,但如果trait中定義了具體成員,則它有著自己的內部實現,此時在java中使用的時候需要作相應的調整。我們先看下trait中全部是抽象成員的情況,例如:

    //全部是抽象成員,與java的interface等同 trait MySQLDAO{def delete(id:String):Booleandef add(o:Any):Booleandef update(o:Any):Intdef query(id:String):List[Any] } //MySQLDAO字節碼反編譯后的結果 D:\ScalaWorkspace\ScalaChapter28\bin\cn\scala\xtwy\scalaToJava>javap MySQLDAO.cl ass Compiled from "MySQLDAO.scala" public interface cn.scala.xtwy.scalaToJava.MySQLDAO {public abstract boolean delete(java.lang.String);public abstract boolean add(java.lang.Object);public abstract int update(java.lang.Object);public abstract scala.collection.immutable.List<java.lang.Object> query(java.l ang.String); }//java直接implement,與普通的java接口一樣 public class MySQLDAOImpl implements MySQLDAO{@Overridepublic boolean delete(String id) {// TODO Auto-generated method stubreturn false;}@Overridepublic boolean add(Object o) {// TODO Auto-generated method stubreturn false;}@Overridepublic int update(Object o) {// TODO Auto-generated method stubreturn 0;}@Overridepublic List<Object> query(String id) {// TODO Auto-generated method stubreturn null;}}

    那如果Trait中包括了具體的成員,此時又該怎么使用呢?此時需要作特殊處理,代碼如下:

    /*** Created by 搖擺少年夢 on 2015/8/16.*/ trait MySQLDAO {//具體方法def delete(id:String):Boolean={ true}def add(o:Any):Booleandef update(o:Any):Intdef query(id:String):List[Any]}//JAVA語言實現帶有具體成員方法的MySQLDAO /*** Created by 搖擺少年夢 on 2015/8/16.*/ public class MySQLDAOImpl implements MySQLDAO {@Overridepublic boolean delete(String id) {//調用生成帶有具體delete方法實現的MySQLDAO$classif (MySQLDAO$class.delete(this, id)) return true;else return false;}@Overridepublic boolean add(Object o) {return false;}@Overridepublic int update(Object o) {return 0;}@Overridepublic List<Object> query(String id) {return null;} }

    用javap命令查看帶具體成員方法的trait MySQLDAO時,其代碼是一樣的

    D:\ScalaIntellijIDEAWorkSpace\out\production\ScalaChapter28\cn\scala\xtwy\JavaRe vokeScala>javap MySQLDAO$class.class Compiled from "MySQLDAO.scala" public abstract class cn.scala.xtwy.JavaRevokeScala.MySQLDAO$class {public static boolean delete(cn.scala.xtwy.JavaRevokeScala.MySQLDAO, java.lang .String);public static void $init$(cn.scala.xtwy.JavaRevokeScala.MySQLDAO); }D:\ScalaIntellijIDEAWorkSpace\out\production\ScalaChapter28\cn\scala\xtwy\JavaRe vokeScala>javap MySQLDAO.class Compiled from "MySQLDAO.scala" public abstract class cn.scala.xtwy.JavaRevokeScala.MySQLDAO$class {public static boolean delete(cn.scala.xtwy.JavaRevokeScala.MySQLDAO, java.lang .String);public static void $init$(cn.scala.xtwy.JavaRevokeScala.MySQLDAO); }

    但其實并不是這樣的,經本人查閱相關資料發現,可能是scala版本原因導致的,這篇文獻中提到的跟實際情況應該是穩合的http://www.importnew.com/6188.html
    這篇文章中給出了下面這樣一個trait的定義:

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

    它生成下面兩個字節碼文件MyTrait.class、MyTrait$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 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); }

    這種情況應該是跟實際情況穩合的,trait MyTrait會自動生成一個名為MyTrait的interface,MyTrait$class的抽象類。我們可以看到,該作者的scala版本是2.8.1,而我們的scala版本是2.10.4,至于為什么出現這樣的原因,本人暫時還沒有弄清楚,但可以肯定的是,http://www.importnew.com/6188.html這篇文章講的內容跟實際是穩合的,因為前面的MySQLDAOImpl仍然是實現MySQLDAO接口方式定義的,但在重寫delete方法時采用的是

    @Overridepublic boolean delete(String id) {//調用生成帶有具體delete方法實現的MySQLDAO$classif (MySQLDAO$class.delete(this, id)) return true;else return false;}

    這種方式進行方法的實現,即MySQLDAO$class是個抽象類,該抽象類中包含了MySQLDAO中實現的方法。也即

    trait MySQLDAO {//具體方法def delete(id:String):Boolean={ true}def add(o:Any):Booleandef update(o:Any):Intdef query(id:String):List[Any]}

    最終反編譯后的代碼應該具有以下形式:

    public cn.scala.xtwy.JavaRevokeScala.MySQLDAO extends scala.ScalaObject{public abstract boolean delete(java.lang.String);public abstract boolean add(java.lang.Object);public abstract int update(java.lang.Object);public abstract scala.collection.immutable.List<java.lang.Object> query(java.l ang.String); }

    值得注意的是在Scala IDE for Eclipse中不能實現下列代碼的調用

    @Overridepublic boolean delete(String id) {//調用生成帶有具體delete方法實現的MySQLDAO$classif (MySQLDAO$class.delete(this, id)) return true;else return false;}

    只有在Intellij IDEA中才能正確使用,從這點上也說明了Intellij IDEA在編寫scala應用程序時更貼近實際。

    2. Scala中調用JAVA類

    Scala可以直接調用Java實現的任何類,只要符合scala語法就可以,不過某些方法在JAVA類中不存在,但在scala中卻存在操作更簡便的方法,例如集合的foreach方法,在java中是不存在的,但我們想用的話怎么辦呢?這時候可以通過隱式轉換來實現,scala已經為我們考慮到實際應用場景了,例如:

    import java.util.ArrayList;/*** Created by 搖擺少年夢 on 2015/8/16.*/ class RevokeJavaCollections {def getList={val list=new ArrayList[String]()list.add("搖擺少年夢")list.add("學途無憂網金牌講師")list}def main(args: Array[String]) {val list=getList//因為list是java.util.ArrayList類型,所以下這條語句編譯不會通過list.foreach(println)} }

    此時只要引入scala.collection.JavaConversions._包就可以了,它會我們自動地進行隱式轉換,從而可以使用scala中的一些非常方便的高階函數,如foreach方法,代碼如下:

    package cn.scala.xtwy.ScalaRevokeJavaimport java.util.ArrayList; //引入下面這條語句后便可以調用scala集合中的方法,如foreach,map等 import scala.collection.JavaConversions._ /*** Created by 搖擺少年夢 on 2015/8/16.*/ object RevokeJavaCollections{def getList={val list=new ArrayList[String]()list.add("搖擺少年夢")list.add("學途無憂網金牌講師")list}def main(args: Array[String]) {val list=getList//現在可以調用scala集合中的foreach等方法了list.foreach(println)val list2=list.map(x=>x*2)println(list2)} }

    前面我們使用的是隱式轉換,我們還可以顯式地進行轉換,例如:

    import java.util.ArrayList; import scala.collection.JavaConversions._ /*** Created by 搖擺少年夢 on 2015/8/16.*/ object RevokeJavaCollections{def getList={val list=new ArrayList[String]()list.add("搖擺少年夢")list.add("學途無憂網金牌講師")list}def main(args: Array[String]) {val list=getListlist.foreach(println)val list2=list.map(x=>x*2)println(list2)//顯式地進行轉換val listStr=asJavaIterable(JavaListString.getListString)for(i<- listStr)println(i)} }

    下面給出的是Scala集合與Java集合支持的轉換操作(取自JavaConversions源碼):

    /** A collection of implicit conversions supporting interoperability between* Scala and Java collections.** The following conversions are supported:*{{{ //相互轉換* scala.collection.Iterable <=> java.lang.Iterable* scala.collection.Iterable <=> java.util.Collection* scala.collection.Iterator <=> java.util.{ Iterator, Enumeration }* scala.collection.mutable.Buffer <=> java.util.List* scala.collection.mutable.Set <=> java.util.Set* scala.collection.mutable.Map <=> java.util.{ Map, Dictionary }* scala.collection.mutable.ConcurrentMap (deprecated since 2.10) <=> java.util.concurrent.ConcurrentMap* scala.collection.concurrent.Map <=> java.util.concurrent.ConcurrentMap*}}}* In all cases, converting from a source type to a target type and back* again will return the original source object, eg.**{{{//源類型到目標類型轉換,再從轉換回去,得到的是相同對象* import scala.collection.JavaConversions._** val sl = new scala.collection.mutable.ListBuffer[Int]* val jl : java.util.List[Int] = sl* val sl2 : scala.collection.mutable.Buffer[Int] = jl* assert(sl eq sl2)*}}}* In addition, the following one way conversions are provided:**{{{ //只支持單向轉換的類* scala.collection.Seq => java.util.List* scala.collection.mutable.Seq => java.util.List* scala.collection.Set => java.util.Set* scala.collection.Map => java.util.Map* java.util.Properties => scala.collection.mutable.Map[String, String]*}}}** @author Miles Sabin* @author Martin Odersky* @since 2.8*/

    3. Scala類型參數與JAVA泛型互操作

    Java中的泛型可以直接轉換成Scala中的泛型,在前面的課程中我們已經有所涉及,例如Java中的Comparator<T> 可以直接轉換成 Scala中的Comparator[T] 使用方法完全一樣,不同的只是語法上的。下列代碼給出了其使用方法:

    package cn.scala.xtwy.JavaAndScalaGeneric import java.util._ /*** Created by 搖擺少年夢 on 2015/8/16.*/ case class Person(val name:String,val age:Int) //在Java中Comparator是這么用的:Comparator<Person> //而在Scala中,是這么用的:Comparator[Person] class PersonComparator extends Comparator[Person]{override def compare(o1: Person, o2: Person): Int = if(o1.age>o2.age) 1 else -1 } object ScalaUseJavaComparator extends App{val p1=Person("搖擺少年夢",27)val p2=Person("李四",29)val personComparator=new PersonComparator()if(personComparator.compare(p1,p2)>0) println(p1)else println(p2)}

    下面的代碼演示了Java是如何使用Scala中的泛型的:

    package cn.scala.xtwy.JavaAndScalaGenericimport scala.beans.BeanProperty/*** Created by 搖擺少年夢 on 2015/8/16.*///Student類用泛型定義,成員變量name及age指定泛型參數//并且用注解的方式生成JavaBean規范的getter方法//因為是val的,所以只會生成getter方法 class Student[T,S](@BeanProperty val name:T,@BeanProperty val age:S){}package cn.scala.xtwy.JavaAndScalaGeneric;/*** Created by 搖擺少年夢 on 2015/8/16.*/ public class JavaUseScalaGeneric {public static void main(String[] args){Student<String,Integer> student=new Student<String,Integer>("小李",18);//Scala版本的getter方法System.out.println(student.name());//JavaBean版本的getter方法System.out.println(student.getName());} }

    通過上述代碼,我們已經十分清楚了Scala中的泛型如何與Java中的泛型進行互操作了,但還有一個問題值得去考慮,那就是Java中的通配符的泛型如何與Scala中的泛型進行操作呢?例如:

    package cn.scala.xtwy.JavaAndScalaGeneric;import java.util.ArrayList; import java.util.List; /*** Created by 搖擺少年夢 on 2015/8/16.*/ public class JavaWildcardGeneric {//Java的通配符類型,要接受任何類型public static List<?> getList(){List<String> listStr=new ArrayList<String>();listStr.add("搖擺少年夢");listStr.add("學途無憂網金牌講師");return listStr;} }package cn.scala.xtwy.JavaAndScalaGenericimport java.util.List import scala.collection.JavaConversions._ /*** Created by 搖擺少年夢 on 2015/8/16.*/ class ScalaExistTypeToJavaWildcardGeneric1 {//采用Scala中的存在類型與Java中的能匹符泛型進行互操作def printList(list: List[T] forSome {type T}):Unit={//因為我們引入了import scala.collection.JavaConversions._//所以可以直接調用foreach方法list.foreach(println)}//上面的函數與下面的等同def printList2(list: List[_]):Unit={list.foreach(println)}}object Main extends App{val s=new ScalaExistTypeToJavaWildcardGeneric1s.printList(JavaWildcardGeneric.getList)s.printList2(JavaWildcardGeneric.getList) }

    4. Scala與Java間的異常處理互操作

    Java中的異常處理具有如下形式:

    package cn.scala.xtwy.ScalaAndJavaException;import java.io.File; import java.io.IOException;/*** Created by 搖擺少年夢 on 2015/8/16.*/ public class JavaExceiptionDemo {public static void main(String[] args) {File file = new File("a.txt");if (!file.exists()) {try {file.createNewFile();} catch (IOException e) {e.printStackTrace();}}}}

    Scala中的異常處理是通過模式匹配來實現的,代碼如下:

    package cn.scala.xtwy.ScalaAndJavaExceptionimport java.io.File/*** Created by 搖擺少年夢 on 2015/8/16.*/ object ScalaExceptionDemo extends App{val file: File = new File("a.txt")if (!file.exists) {try {file.createNewFile}catch {//通過模式匹配來實現異常處理case e: IOException => {e.printStackTrace}}} }

    上面給的例子是Scala如何捕獲Java中拋出的異常,下面的例子給出的是Java如何捕獲Scala中聲明的異常,代碼如下:

    package cn.scala.xtwy.ScalaAndJavaException class ScalaThrower {//Scala利用注解@throws聲明拋出異常@throws(classOf[Exception])def exceptionThrower {throw new Exception("Exception!")} }//Java中調用ScalaThrower(Scala類),然后捕獲其拋出的異常 public class JavaCatchScalaThrower {public static void main(String[] args){ScalaThrower st=new ScalaThrower();try{st.exceptionThrower();}catch (Exception e){e.printStackTrace();}} }

    通過本節,我們基本能掌握Scala與Java的互操作,當然這里面還有很多內容沒有涉及,但在日常開發工作當中,掌握本節講的內容便可以應付絕大多數互操作問題。

    總結

    以上是生活随笔為你收集整理的Scala入门到精通——第二十八节 Scala与JAVA互操作的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。