2010-10-04 35 views
5

Tôi muốn gọi phương thức java sau từ scala:làm thế nào để vượt qua một String * scala vararg đến một phương pháp java sử dụng Scala 2,8

protected final FilterKeyBindingBuilder filter(String urlPattern, String... morePatterns) { 
    return filtersModuleBuilder.filter(Lists.newArrayList(urlPattern, morePatterns)); 
} 

gọi scala của tôi trông như thế này

def test(url: String, urls: String*) { 
    filter(url, urls: _*).through(classOf[MyTestWhateverFilter]) 
} 

biên dịch này, tuy nhiên, thực thi mã cho một ngoại lệ:

java.lang.ClassCastException: scala.collection.mutable.WrappedArray$ofRef cannot be cast to [Ljava.lang.String; 

Tôi cũng đã thử điều này:

def test(url: String, urls: String*) { 
    filter(url, urls.map(_.asInstanceOf[java.lang.String]) :_*).through(classOf[MyTestWhateverFilter]) 
} 

trong trường hợp này ngoại trừ là:

java.lang.ClassCastException: scala.collection.mutable.ArrayBuffer cannot be cast to [Ljava.lang.String; 

Tôi nghĩ rằng trong 2,8 Array [Chuỗi] được chuyển cho java như String [] mảng và không unboxing thêm là cần thiết.

Bất kỳ ý tưởng nào?

Cảm ơn trước!

EDIT:

làm thế nào để tái tạo nó:

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 

kết quả:

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) 

Trả lời

7

Tôi vừa cố gắng để tái tạo lỗi của bạn sử dụng Scala 2.8.0 và không thể. Dưới đây là mã của tôi

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

tôi nhận được kết quả như sau:

class scala.collection.mutable.WrappedArray$ofRef 
class [Ljava.lang.String; 

Vì vậy, nó trông giống như các trình biên dịch được chèn chuyển đổi chính xác để chuyển đổi WrappedArray.ofRef đến một String[].

Sửa

Chỉ cần cố gắng chạy ví dụ của bạn. Dường như một số tương tác của các siêu truy cập trong các đặc điểm với việc chuyển đổi các biến thể Scala thành các biến thể Java. Nếu bạn thay đổi đặc điểm thành một lớp, nó sẽ hoạt động.

Từ đầu ra được biên dịch của ScalaServletModule$class, có vẻ như nó không thực hiện chuyển đổi cần thiết từ String* thành String[] khi gọi thiết bị siêu truy cập (dòng 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 
+0

Tôi đã thử nó với ví dụ của bạn nó dường như làm việc. hmm không chắc tại sao gọi phương thức của guice servlet lại tạo nên sự khác biệt. – poko

+0

(đã thêm ví dụ) – poko

+0

thú vị! Tôi có thể báo cáo lỗi này là lỗi – poko

2

Các Scala và Java cách tiếp cận để varargs không phù hợp: varargs Scala được dựa trên Seqs (hoặc như vậy?) Và Java varargs trên mảng. Bạn đã thử

filter(url, urls.toArray:_*).through(classOf[MyTestWhateverFilter]) 

?

Ít nhất điều này dường như đã làm việc ở đây: Using varargs from Scala

+0

cảm ơn câu trả lời của bạn.String * của loại là WrapperArray và toArray sẽ không thay đổi điều đó. do đó, điều này sẽ dẫn đến thông báo lỗi đầu tiên – poko

+0

Lạ, đối với tôi một cái gì đó như 'System.out.printf ("% s% s ", Array (" Xin chào "," Thế giới "): _ *)' hoạt động tốt. – Landei

+0

Tôi đã có cùng một câu hỏi về varargs, câu trả lời này đã giải quyết được vấn đề của tôi! – Magnus

Các vấn đề liên quan