Java 互操作零障碍:programming-scala-book-code-examples 中数组、元组与 Bean 互操作示例 Java 互操作零障碍programming-scala-book-code-examples 中数组、元组与 Bean 互操作示例【免费下载链接】programming-scala-book-code-examplesThe code examples used in Programming Scala, 2nd and 3rd Editions (OReilly)项目地址: https://gitcode.com/gh_mirrors/pr/programming-scala-book-code-examples学习 Scala 3 的新手最关心的一个问题就是Java 互操作到底顺不顺畅。作为 OReilly《Programming Scala》第 2、3 版的官方配套代码库programming-scala-book-code-examples用大量真实可运行的示例回答了这个问题无论是 Java 调用 Scala 的元组还是 Scala 生成标准的 Java Bean几乎都是零障碍的。本文就带你快速盘点其中与数组、元组和 Bean 相关的互操作代码帮你少踩坑、快上手。为什么说 Java 互操作是 Scala 的看家本领Scala 运行在 JVM 之上天生就与 Java 共享运行时。但能跑不等于好用真正的互操作要解决三件事类型能否互通、命名能否对齐、集合能否转换。programming-scala-book-code-examples 恰好用三个典型的例子把这三件事逐一演示了一遍。数组互操作先看懂 Java 数组的协变陷阱先看一个 Java 侧的经典问题。在 JavaArrays.java 中作者故意写了一段会抛异常的代码Integer[] array1 new Integer[] { 1, 2, 3 }; Number[] array2 array1; // 编译通过但其实不该通过 array2[2] Double.valueOf(3.14); // 编译通过运行时报 ArrayStoreException因为 Java 数组是协变的Integer[]可以赋值给Number[]但运行时数组会记住自己的真实元素类型写入不兼容类型就会抛出ArrayStoreException。这个示例的价值在于它用最小的代码让你记住 Java 数组的类型规则这样你在 Scala 中写数组互操作代码时才能理解为什么某些类型转换会编译期安全、运行期爆炸。而在 Scala 侧Array[T]其实就对应 JVM 上的原生数组互操作是透明的你可以直接new ArrayInt并在 Java 代码里当作int[]使用两边无需任何桥接。元组互操作Java 代码里直接 new 一个 Scala 元组Java 8 之后才引入了Map.Entry之类的伪元组而 Scala 从第一天起就有真正的元组类型。在互操作场景下Java 调用 Scala 元组正是 programming-scala-book-code-examples 重点演示的内容。看看 JavaWithScalaTuples.java 这段 Java 代码import scala.Tuple2; Tuple2String,Integer stringInteger new Tuple2String,Integer(one, 2); System.out.println(stringInteger); // 输出 (one,2)这段代码验证了两件事Scala 的标准库类如Tuple2编译后就是普通的 JVM 类Java 可以直接new出来使用Scala 元组的toString输出格式(one,2)在 Java 侧同样生效。这意味着如果你的团队里有 Java 老代码想让它们消费 Scala 函数返回的元组完全不需要改造——直接当作普通对象用即可。Bean 互操作一个注解让 Scala case class 变身标准 Java BeanJava 生态的框架Spring、MyBatis、各类 JSON 库普遍依赖JavaBean 规范要求有getXxx/setXxx方法。而 Scala 的 case class 默认只生成字段不生成 Bean 风格方法。这个鸿沟怎么填答案就在 ComplexBean.scala 里作者在 case class 的构造参数上加了一个注解case class ComplexBean( scala.beans.BeanProperty var real: Double, scala.beans.BeanProperty var imaginary: Double)加上BeanProperty之后编译器会自动生成getReal()、setReal()、getImaginary()、setImaginary()这些标准 Bean 方法Java 框架就能无缝识别和操作它了。注意这里用的是var可变字段因为 Bean 需要 setter如果你的字段是val则只会生成 getter。作者还贴心地在文件注释里给出了 Scala 2 版本 ComplexBean2.scala方便对比新旧语法下写法差异。对照练习仓库里的 JavaPerson.java 是一个手工编写、完全符合 Bean 规范的 Java 类含getName/setName/getAge/setAge你可以把它和ComplexBean放在一起对比——一边是 Java 手写样板代码一边是 Scala 一行注解搞定互操作的优雅程度高下立判。运算符互操作targetName 让 Java 调用 Scala 运算符方法如果说数组、元组、Bean 是数据层面的互操作那么 AllOpChars.scala 演示的就是语法层面的互操作。Scala 允许方法名是、-、*、::这样的运算符但 Java 源码里没法直接写这些字符。Scala 3 为此提供了targetName注解给运算符方法一个 Java 可读的名字targetName(plus) def : Int // Java 侧调用 plus() targetName(eqeq) def : Int // Java 侧调用 eqeq()编译后Java 代码可以调用plus()、eqeq()等普通方法名来访问这些运算符逻辑。对编写 DSL、数学库的开发者来说这是 Java 互操作里非常实用的一招。集合互操作一键在 Scala 集合与 Java 集合之间切换最后补一个日常最常用的互操作场景——集合转换。在 CollectionConverters.scala 中作者演示了scala.jdk.CollectionConverters的用法import scala.jdk.CollectionConverters.* val s Set(one) val js s.asJava // Scala Set 转 Java Set js.add(two) // 操作 Java 集合 assert(s Set(two, one)) // 注意asJava 是视图共享底层数据 assert(js.asScala Set(two, one)) // 再转回 Scala这个脚本的关键提醒是asJava返回的是视图view它和原 Scala 集合共享底层数据所以js.add(two)之后Scala 侧的s也跟着变了。理解了这一点你在混合使用 Java/Scala 集合时就不会被意外修改吓到。如何运行这些互操作示例想要亲手跑一遍这些示例只需要克隆仓库后用 sbt 构建git clone https://gitcode.com/gh_mirrors/pr/programming-scala-book-code-examples cd programming-scala-book-code-examples sbt compile然后在 sbt 提示符下用runMain运行对应的 main 类例如runMain progscala3.javainterop.JavaWithScalaTuples runMain progscala3.objectsystem.JavaArrays # 会看到预期的 ArrayStoreExceptionJava 源码位于 src/main/java/progscala3 目录Scala 源码在 src/main/scala/progscala3 目录脚本类示例则放在 src/script/scala/progscala3对照着书目录结构找代码非常方便。小结Java 互操作学 Scala 3 的必修课从 programming-scala-book-code-examples 的这几个示例可以看出Scala 3 与 Java 的互操作是双向且完备的Java → Scala直接new Tuple2调用targetName生成的普通方法名Scala → Java用BeanProperty生成 Bean 方法用asJava/asScala转换集合共同的坑记住 Java 数组协变和asJava视图共享底层数据这两个特性就能避免绝大多数互操作运行时错误。如果你正在 Scala 与 Java 混编的项目中挣扎强烈建议把javainterop包下的这几个文件通读一遍再配合书中的讲解亲手运行一次。零障碍的 Java 互操作从读懂这几十行示例代码开始。【免费下载链接】programming-scala-book-code-examplesThe code examples used in Programming Scala, 2nd and 3rd Editions (OReilly)项目地址: https://gitcode.com/gh_mirrors/pr/programming-scala-book-code-examples创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考