扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
假设场景是java某个函数返回了一个byte[]
十多年专注成都网站制作,成都定制网页设计,个人网站制作服务,为大家分享网站制作知识、方案,网站设计流程、步骤,成功服务上千家企业。为您提供网站建设,网站制作,网页设计及定制高端网站建设服务,专注于成都定制网页设计,高端网页制作,对成都玻璃贴膜等多个方面,拥有多年的网站营销经验。
现在需要在scala代码中调用这个函数,并转换为Array[Byte]
可以先用java写一个包装函数,将
返回值
修改为Listbyte,使用
java.util.Arrays.asList
可以达成这个目的
然后在scala中使用转换,例如
import
scala.collection.JavaConversions.asScalaBuffer
val
buffer
=
asScalaBuffer(JavaList)
将结果转换为一个buffer,调用toArray即可转换为Array[Byte]
导入也是没有问题的,intellij是做了这方面的功能。其实不导入也是没有问题的,intellij上建一个工程,把eclipse的工具复制曩昔,也是一样的。你之所以问这个问题是不清嚣张j2ee的一些基本常识。eclipse的工程名目和inteliij最终编程的是j2ee的
Java 和 Scala 都支持变参方法, 写在最后的位置上,最基本的调用方式也都是一样的,一个个罗列过去。也可以传入数组参数,因为变参本质上就是一个数组,就是把 ... 开始位置到最后一个参数都收纳到数组中去,所以变参之所以要放在最后的位置上,且一个方法中最多只能有一个变参类型。
这里主要是对比 Scala 对变参方法的调用,基本调用法当然是没问题的,但是在传入数组作为变参的参数列表与 Java 相对时就稍有变化了。
另外提一下,如果想传入 List 作为变参列表,而不是整体作为变参的第一个元素就是调用集合的 toArray() 方法转换成一个数组传入。
下面看 Java 中对变参方法的调用,参数列表和数组
public class JavaVarArgs {
public static void main(String[] args) {
foo("a", "b", "c");
foo(new String[]{"d", "e"});
}
public static void foo(String...params) {
System.out.println(params + " : " + params.length);
for(String s: params) {
System.out.println(s);
}
}
}
从输出结果能够很明白的看出变参 params 实际上就是一个数组
[Ljava.lang.String;@3f91beef : 3
a
b
c
[Ljava.lang.String;@1a6c5a9e : 2
d
e
我们知道 Scala 和 Java 之间可以互相调用,现在写一段 Scala 代码来调用 foo() 方法
object ScalaVarArgs {
def main(args: Array[String]) {
JavaVarArgs.foo("a", "b", "c")
// JavaVarArgs.foo(Array[String]("d", "e"))
}
}
JavaVarArgs.foo("a", "b", "c") 调用没问题
而 JavaVarArgs.foo(Array[String]("d", "e")) 会有编译问题
Type mismatch: expected String, actual Array[String]
Java 在调用变参方法时可以直接传入相应类型的数组,而 Scala 确不允许这么做了,因它试图把 Array[String] 整体作为一个元素传递给 foo() 方法,而 foo() 要求的元素类型是字符串,所以编译不过。
而 Scala 这时该如何使得与 Java 调用变参方法时的行为一致呢,那就是在调用时再附加说明:是要把数组中的元素逐个传递级变参,写法
JavaVarArgs.foo(Array[String]("d", "e") :_*)
这样的调用输出就是
本文原始链接 , 来自隔叶黄莺 Unmi Blog
[Ljava.lang.String;@7a718e31 : 2
d
e
如果从上面的例子说来,我们的运气还不错,因为编译器告诉了你出现了什么问题。最麻烦的问题总是在能编译,但运行时诡异的情况。
因为在我本人实际中遭遇到的情形是变参类型是 Object 的方法,形如
public static void foo(Object...params) {
System.out.println(params + " : " + params.length);
for(Object o: params) {
System.out.println(o);
}
}
上面把参数改为 Object...params, 不会改变 Java 传数组调用它的行为,但却增加了 Scala 调用它时的排错难度。
在 Scala 中使用 foo(Array[String]("d", "e") 调用并没有编译错误,加入上面的调试代码才发现,不管传入多大的数组,总是输出像
[Ljava.lang.Object;@7814d044 : 1
[Ljava.lang.String;@ea25c1
说方法只接收到了一个元素,类型被识别为形参的类型,不过进一步遍历变参,发现第一个元素是一个字符串数组,所以 Scala 把 Array[String]("d", "e") 整体作为 params 的第一个元素传给了 foo() 方法。写成
foo(Array[String]("d", "e") : _*)
是为了把数组拆散了传给 foo() 方法。
起初以为是 Scala 调用 Java 的变参方法需要这么做,后来重新用 Scala 实现下变参方法
def foo(params: AnyRef*) {
println(params + " : " + params.length)
for (s - params) {
println(s)
}
}
用 Scala 代码来调用它,传入数组,如果不想整体作为一个元素时也必须加上 : _*参数说明,同样的:
foo(Array[String]("d", "e") :_*)
在写这篇之前,我所认定的这是 Scala 调用变参方法的一个缺陷, : _* 似乎是一种默认行为,现在认为这恰恰是 Scala 的一个灵活性所在。Scala 提供了两种方式来传递数组给变参,而为何 Java 不让数组整体作为变参的一个元素呢,不过 Scala 放开这一特性,当变参为 Object... params 确实放大了 Bug 的出现机率。
scala中的collect分为mutable和immutable两种,分别在scala.collection.mutable 和scala.collection.immutable package下。但是有时候我们需要将scala中的collection,比如Seq, ArrayBuffer等转换为java中的List, 以便存到数据库中,以数组或List的形式存在。
比如,我们通过spark任务得到了一个Seq[Long]类型的变量,并希望将其保存到MongoDB中。我们通常会这样处理:
(1)生成一个BasicDBObject对象,val obj = new BasicDBObject();
(2)obj.put(key, value), value为我们需要保存的Seq[Long], 但是需要注意的是value必须是java的类型,由于java不支持Seq[Long]类型,所以需要将其转换为List[Long]类型。
如何转换呢?
scala提供了一个implicit conversion机制,只需要引入scala.collection.JavaConversions._, 然后显示转换即可。具体参见
例如,上面的代码可以写成:
import scala.collection.JavaConversions._
val jul: java.util.List[Long] = visitors // 其中visitors类型为Seq[Long]类型
obj.put("visitors", jul)
值得注意的是,scala和java类型之间的转换,并不会发生拷贝。例如先将java容器转换为scala容器,然后将该scala容器再转换成java容器,实际上两个对象都指向同一片内存区域。
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流