【问题标题】:Transforming Scala varargs into Java Object... varargs将 Scala 可变参数转换为 Java 对象...可变参数
【发布时间】:2011-01-21 00:13:48
【问题描述】:

我有一个记录东西的 Java 类,它的方法如下:

void info(Object message, Object... params);

在 Scala 中,我为这样的调用创建了一个包装器,如下所示:

def info(msg: => String, params: Any*) {
  log.info(msg, params);
}

当我打电话时:

val host = "127.0.0.1"
val port = "1234"
info("Start on {0}:{1}", host, port)

我明白了:

"Started on WrappedArray(127.0.0.1, 1234):{1}"

现在,有人现在如何将参数转换为可以正常使用的 Object[] 吗?

我尝试过:

def info(msg: => String, params: Any*)
  log.info(msg, params.toList.toArray);
}

但这不起作用:

"Started on [Ljava.lang.Object;@14a18d:{1}"

当你这样做时会发生类似的事情:

params.asInstanceOf[WrappedArray[Object]].array

【问题讨论】:

    标签: scala scala-2.8


    【解决方案1】:

    找到答案:

    log.info(msg,  params.map(_.asInstanceOf[AnyRef]) : _*)
    

    以下返回一个 Seq[AnyRef] => params.map(_.asInstanceOf[AnyRef]),':_*' 部分告诉编译器将其作为可变参数传递

    结果:

    "Started on 127.0.0.1:1234"
    

    此外,此解决方案同时处理 AnyVals 和 AnyRefs

    【讨论】:

    【解决方案2】:

    @Galder - 有一种更简单的方法可以让您避免繁琐的asInstanceOf[Object] 调用:

    def info(msg: => String, params: Any*) =  log.info( msg.format(params : _*) );
    

    在 scala 2.7 中,format(args : Any*) 函数通过 RichString 隐式包含(并且有一个次优的实现是反射术语,我看不到没有充分的理由),而在 2.8 中,该方法通过 @987654325 包含@ 并通过直接调用String.format(String, Object ...) 实现

    我理解Java之所以不包含这样的方法是因为它有一个暗示“每个字符串都是一个格式字符串”,事实并非如此。很高兴,我愿意放弃 scala 提供的更有用的类的逻辑正确性!

    【讨论】:

    • 这无论如何都会急切地创建一个日志字符串,对吧?
    • 这不会编译,它会与存在的其他版本的 log.info 混淆。它无法区分: void info(Object message);和无效信息(对象消息,对象...参数);
    • 这对我来说是个新闻——它直接来自我的生产代码!
    • 哦,我明白你的意思了。在您的代码的另一个片段 旁边时,它不会编译。不完全值得-1,但无论如何。一个建议是将方法重命名为 logf
    • 加一个只是为了对付愚蠢的-1
    猜你喜欢
    • 2018-02-01
    • 1970-01-01
    • 2012-01-09
    • 1970-01-01
    • 2016-04-29
    • 1970-01-01
    • 1970-01-01
    • 2012-12-31
    • 1970-01-01
    相关资源
    最近更新 更多