Преобразование Scala varargs в Java Object ... varargs - PullRequest
13 голосов
/ 25 февраля 2010

У меня есть класс 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}"

А теперь кто-нибудь знает, как преобразовать параметры в объект [], который может потребляться правильно?

Я пытался сделать:

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

Но это не работает:

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

Подобное происходит, когда вы делаете:

params.asInstanceOf[WrappedArray[Object]].array

Ответы [ 2 ]

19 голосов
/ 25 февраля 2010

Нашел ответ:

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

Следующий код возвращает Seq [AnyRef] => params.map (_. AsInstanceOf [AnyRef]), а часть ': _ *' указывает компилятору передать его как varargs

Результат:

"Started on 127.0.0.1:1234"

Кроме того, это решение работает как с AnyVals, так и с AnyRefs

12 голосов
/ 25 февраля 2010

@ Galder - есть более простой способ, позволяющий избежать громоздкого asInstanceOf[Object] вызова:

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

В Scala 2.7 функция format(args : Any*) неявно включена через RichString (и имеет неоптимальную реализацию - условия отражения без веской причины, которую я вижу), тогда как в 2.8 метод включен через StringLike и реализуется через прямой вызов String.format(String, Object ...)

Я понимаю, что причина, по которой Java не содержит такого метода, заключается в том, что он подразумевает , что «каждая строка является строкой формата», что не так. к счастью, я готов отказаться от логической корректности для более полезного класса, который предоставляет scala!

...