我想从scala调用以下java方法:
protected final FilterKeyBindingBuilder filter(String urlPattern, String... morePatterns) {
return filtersModuleBuilder.filter(Lists.newArrayList(urlPattern, morePatterns));
}
Run Code Online (Sandbox Code Playgroud)
我的scala来电看起来像这样
def test(url: String, urls: String*) {
filter(url, urls: _*).through(classOf[MyTestWhateverFilter])
}
Run Code Online (Sandbox Code Playgroud)
但是,编译时执行代码会产生异常:
java.lang.ClassCastException: scala.collection.mutable.WrappedArray$ofRef cannot be cast to [Ljava.lang.String;
Run Code Online (Sandbox Code Playgroud)
我也试过这个:
def test(url: String, urls: String*) {
filter(url, urls.map(_.asInstanceOf[java.lang.String]) :_*).through(classOf[MyTestWhateverFilter])
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,例外是:
java.lang.ClassCastException: scala.collection.mutable.ArrayBuffer cannot be cast to [Ljava.lang.String;
Run Code Online (Sandbox Code Playgroud)
我认为在2.8中,Array [String]作为String []数组传递给java,并且不需要额外的拆箱.
有任何想法吗?
提前致谢!
编辑:
如何复制它:
import com.google.inject.servlet.ServletModule
trait ScalaServletModule extends ServletModule{
def test(s: String,strs: String*) = {
println(strs.getClass)
println(super.filter(s,strs:_*))
}
}
object Test {
def main(args: Array[String]) {
val module = new ServletModule with ScalaServletModule
module.test("/rest")
}
}
/opt/local/lib/scala28/bin/scala -cp /Users/p.user/Downloads/guice-2.0/guice-2.0.jar:/Users/p.user/Downloads/guice-2.0/guice-servlet-2.0.jar:/Users/p.user/Downloads/guice-2.0/aopalliance.jar:/Users/p.user/Downloads/javax.jar/javax.jar:. Test
Run Code Online (Sandbox Code Playgroud)
结果:
class scala.collection.mutable.WrappedArray$ofRef
java.lang.ClassCastException: scala.collection.mutable.WrappedArray$ofRef cannot be cast to [Ljava.lang.String;
at ScalaServletModule$class.test(test.scala:6)
at Test$$anon$1.test(test.scala:11)
at Test$.main(test.scala:12)
at Test.main(test.scala)
Run Code Online (Sandbox Code Playgroud)
我刚刚尝试使用Scala 2.8.0重现您的错误,但不能.这是我的代码
// Example.java
public class Example {
public static void test(String... args) {
System.out.println(args.getClass());
}
}
// In test.scala
object Test {
def main(args: Array[String]) {
test("1", "2", "3")
}
def test(strs: String*) = {
println(strs.getClass)
Example.test(strs:_*)
}
}
Run Code Online (Sandbox Code Playgroud)
我得到以下输出:
class scala.collection.mutable.WrappedArray$ofRef
class [Ljava.lang.String;
Run Code Online (Sandbox Code Playgroud)
所以看起来编译器正在插入正确的转换以将其转换WrappedArray.ofRef为a String[].
编辑
刚试过运行你的例子.它看起来像是特征中的超级访问者与Scala varargs转换为Java varargs的一些交互.如果您将特征更改为类,则可以使用.
从反编译的输出ScalaServletModule$class,它看起来像它不会做必要的转换String*,以String[]调用超级访问(19行)时.
public static void test(ScalaServletModule, java.lang.String, scala.collection.Seq);
Code:
0: getstatic #11; //Field scala/Predef$.MODULE$:Lscala/Predef$;
3: aload_2
4: invokevirtual #18; //Method java/lang/Object.getClass:()Ljava/lang/Class;
7: invokevirtual #22; //Method scala/Predef$.println:(Ljava/lang/Object;)V
10: getstatic #11; //Field scala/Predef$.MODULE$:Lscala/Predef$;
13: aload_0
14: aload_1
15: aload_2
16: checkcast #24; //class "[Ljava/lang/String;"
19: invokeinterface #30, 3; //InterfaceMethod ScalaServletModule.ScalaServletModule$$super$filter:(Ljava/lang/String;[Ljava/lang/String;)Lcom/google/inject/servlet/ServletModule$FilterKeyBindingBuilder;
24: invokevirtual #22; //Method scala/Predef$.println:(Ljava/lang/Object;)V
27: return
Run Code Online (Sandbox Code Playgroud)