2010-06-11 37 views
9

Tôi có đoạn code sau trong Java:gọi method Java vararg từ Scala với nguyên thủy

public class JavaClass { 

    public static void method(Object x) { 
    } 

    public static void varargsMethod(Object... x) { 
    } 

} 

Khi tôi cố gắng và truy cập nó từ Scala,

object FooUser { 
    JavaClass.method(true) 
    JavaClass.varargsMethod(true) // <-- compile error 
} 

tôi nhận được lỗi biên dịch sau:

type mismatch; found : Boolean(true) required: java.lang.Object Note: primitive types are not implicitly converted to AnyRef. You can safely force boxing by casting x.asInstanceOf[AnyRef]

Thông báo lỗi rất hữu ích và hiển thị cách khắc phục lỗi, nhưng tôi tự hỏi tại sao trình biên dịch lại là (pparently) vui vẻ chuyển đổi một cách rõ ràng scala.Boolean trong một cuộc gọi phương thức nhưng không phải là phương thức khác. Đây có phải là lỗi hoặc cố ý không?

Đã cập nhật để thêm: Tôi đang sử dụng Scala 2.8. Nếu tôi thực hiện chữ ký varargsMethod

public static <T> void varargsMethod(T... xs) { 

thay vào đó, thì lỗi cũng biến mất. Tôi vẫn còn bối rối là tại sao trình biên dịch không thể tìm ra được.

+0

CẢM ƠN BẠN! Thủ thuật này void varargsMethod (T ... xs) hoạt động !!! – ZiglioUK

Trả lời

5

Varala varargs và Java varargs là khác nhau. Bạn cần phải do a conversion:

def g(x: Any*) = x.asInstanceOf[scala.runtime.BoxedObjectArray] 
.unbox(x.getClass) 
.asInstanceOf[Array[Object]] 
... 
JavaClass.varargsMethod(g(true)) 

hoặc (in 2.8.0+)

JavaClass.varargsMethod(java.util.Arrays.asList(true)) 
+3

Phiên bản 2.8 "Arrays.asList (true)" không hoạt động, vì nó đưa ra một đối số duy nhất cho "varargsMethod" của kiểu "Arrays $ ArrayList". Tuy nhiên, việc tìm một giải pháp không thực sự là vấn đề - thông báo lỗi cho thấy cách sửa lỗi - thay vào đó tôi muốn biết tại sao trình biên dịch sẽ không biên dịch cuộc gọi này khi nó sẽ cho người khác trong các tình huống tương tự. –

+0

Tôi cũng muốn nhận được câu trả lời cho điều này. – Kevin

+0

do đó, Scala> 2.8 kiểu trả về BoxedObjectArray không phải là thành viên của gói thời gian chạy – ZiglioUK

0

lẽ có thể nộp một lỗi về điều đó. Có vẻ như nó nên ném một ngoại lệ trong cả hai trường hợp hay không. Không chắc chắn nó là cái gì đó sẽ bao giờ được cố định vì nó có thể là do một số thông minh trong việc thực hiện varargs ngăn cản boxing diễn ra.

2

Kể từ scala.Boolean là một lớp con của scala.AnyVal nhưng không scala.AnyRef (dịch sang java.lang.Object), một Boolean không thể được truyền cho một phương pháp dự đoán Object (s).

Bạn có thể sử dụng đối tượng đồng scala.Boolean để "hộp" (theo nghĩa của Java, tất nhiên) một boolean vào java.lang.Boolean:

JavaClass.varargsMethod(Boolean.box(true)) 

Các AnyVal lớp khác đã tương ứng box phương pháp (ví dụ Int.box). Ngoài ra còn có các phương pháp unbox để làm ngược lại.

Một sử dụng trường hợp phức tạp hơn:

JavaClass.varargsMethod(Seq(1, 2, 3, 4).map(Int.box): _*) // passes 1, 2, 3, 4 

Tôi không biết khi nào chúng được bổ sung vào thư viện chuẩn, nhưng với những bạn không cần phải sử dụng các lớp thực hiện scala.runtime.*.

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