Java 和 Scala 如何调用变参

 更新时间:2020年09月02日 10:02:02   作者:Yanbin  
这篇文章主要介绍了Java 和 Scala 如何调用变参,帮助大家更好的理解和学习Java与Scala,感兴趣的朋友可以了解下

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") :_*)

这样的调用输出就是

[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 的出现机率。

以上就是Java 和 Scala 如何调用变参的详细内容,更多关于Java 和 Scala 调用变参的资料请关注脚本之家其它相关文章!

相关文章

  • Java使用ES Client 调用滚动查询及Elasticsearch滚动查询Scrolling机制

    Java使用ES Client 调用滚动查询及Elasticsearch滚动查询Scrolling机制

    Elasticsearch提供了一种称为"滚动查询"(Scrolling)的机制,用于处理大型数据集的分页查询,这篇文章给大家介绍滚动查询的一般步骤及Java使用ESClient调用滚动查询的方法,感兴趣的朋友一起看看吧
    2023-08-08
  • 使用Iterator删除List中的多个元素操作

    使用Iterator删除List中的多个元素操作

    这篇文章主要介绍了使用Iterator删除List中的多个元素操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09
  • Java 遍历取出Map集合key-value数据的4种方法

    Java 遍历取出Map集合key-value数据的4种方法

    这篇文章主要介绍了Java 遍历取出Map集合key-value数据的4种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09
  • spring 自动注入AutowiredAnnotationBeanPostProcessor源码解析

    spring 自动注入AutowiredAnnotationBeanPostProcessor源码解析

    这篇文章主要介绍了spring自动注入AutowiredAnnotationBeanPostProcessor源码解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • Java的分支结构与循环你知道多少

    Java的分支结构与循环你知道多少

    这篇文章主要为大家详细介绍了Java的分支结构与循环,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02
  • java实例方法被覆盖,静态方法被隐藏Explain(详解)

    java实例方法被覆盖,静态方法被隐藏Explain(详解)

    下面小编就为大家带来一篇java实例方法被覆盖,静态方法被隐藏Explain(详解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • Java实现HTTP请求的4种方式总结

    Java实现HTTP请求的4种方式总结

    这篇文章主要给大家介绍了关于Java实现HTTP请求的4种方式,在java开发中,经常遇到需要调用第三方提供的接口服务的需求,文中给出了详细的代码示例,需要的朋友可以参考下
    2023-08-08
  • java的几种定时器的具体使用(4种)

    java的几种定时器的具体使用(4种)

    本文主要介绍了4种类型的定时器:@Scheduled注解、quartz、new Timer().schedule、使用线程控制的具体使用,具有一定的参考价值,感兴趣的可以了解一下
    2021-09-09
  • Eclipse转Itellij IDEA导入Git/svn本地项目的详细步骤

    Eclipse转Itellij IDEA导入Git/svn本地项目的详细步骤

    这篇文章主要介绍了Eclipse转Itellij IDEA导入Git/svn本地项目,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-10-10
  • Java中Arrays数组工具类的基本使用详解

    Java中Arrays数组工具类的基本使用详解

    Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用,而"不用"使用对象来调用(注意:是"不用" 而不是 "不能"),这篇文章主要给大家介绍了关于Java中Arrays数组工具类的基本使用,需要的朋友可以参考下
    2021-12-12

最新评论