2010-10-26 37 views
77

Nếu tôi có phương pháp Java vararg foo(Object ...arg) và tôi gọi foo(null, null), tôi có cả arg[0]arg[1]null s. Nhưng nếu tôi gọi foo(null), thì chính nó là arg. Tại sao chuyện này đang xảy ra?Gọi phương thức Java varargs với đối số null đơn?

Tôi nên gọi số foo sao cho foo.length == 1 && foo[0] == nulltrue?

Trả lời

82

Vấn đề là khi bạn sử dụng chữ cái rỗng, Java không biết loại nó được cho là gì. Nó có thể là một đối tượng rỗng, hoặc nó có thể là một mảng đối tượng null. Đối với một đối số duy nhất nó giả định sau này.

Bạn có hai lựa chọn. Truyền null một cách rõ ràng đến Object hoặc gọi phương thức bằng cách sử dụng một biến gõ mạnh mẽ. Xem ví dụ dưới đây:

public class Temp{ 
    public static void main(String[] args){ 
     foo("a", "b", "c"); 
     foo(null, null); 
     foo((Object)null); 
     Object bar = null; 
     foo(bar); 
    } 

    private static void foo(Object...args) { 
     System.out.println("foo called, args: " + asList(args)); 
    } 
} 

Output:

foo called, args: [a, b, c] 
foo called, args: [null, null] 
foo called, args: [null] 
foo called, args: [null] 
+0

Sẽ hữu ích cho người khác nếu bạn đã liệt kê phương thức 'asList' trong mẫu và mục đích của nó. –

+4

@ArunKumar 'asList()' là một nhập tĩnh từ lớp 'java.util.Arrays'. Tôi chỉ cho rằng điều đó là hiển nhiên. Mặc dù bây giờ tôi đang nghĩ về nó, tôi có lẽ nên đã chỉ sử dụng 'Arrays.toString()' vì lý do duy nhất nó được chuyển đổi sang một danh sách là vì vậy nó sẽ in đẹp. –

18

Bạn cần một diễn viên rõ ràng để Object:

foo((Object) null); 

Nếu đối số được giả định là toàn bộ mảng rằng varargs đại diện.

+0

Không thực sự, hãy xem bài đăng của tôi. –

+11

tốt, tôi nghĩ rằng bạn là sai :) – Bozho

+0

Rất tiếc, cùng ở đây ... xin lỗi, dầu nửa đêm. –

3

Điều này là do phương pháp varargs có thể được gọi với một mảng thực tế chứ không phải là một loạt các phần tử mảng. Khi bạn tự cung cấp nó với chính mình là null, nó giả định null là một số Object[]. Việc đúc null đến Object sẽ khắc phục điều này.

5

Một Test Case để minh họa điều này:

Mã Java với một phương pháp kê khai vararg chép (mà sẽ xảy ra là tĩnh):

public class JavaReceiver { 
    public static String receive(String... x) { 
     String res = ((x == null) ? "null" : ("an array of size " + x.length)); 
     return "received 'x' is " + res; 
    } 
} 

Mã Java này (trường hợp kiểm tra JUnit4) gọi ở trên (chúng tôi đang sử dụng trường hợp kiểm tra để không kiểm tra bất kỳ điều, chỉ để tạo ra một số lượng):

import org.junit.Test; 

public class JavaSender { 

    @Test 
    public void sendNothing() { 
     System.out.println("sendNothing(): " + JavaReceiver.receive()); 
    } 

    @Test 
    public void sendNullWithNoCast() { 
     System.out.println("sendNullWithNoCast(): " + JavaReceiver.receive(null)); 
    } 

    @Test 
    public void sendNullWithCastToString() { 
     System.out.println("sendNullWithCastToString(): " + JavaReceiver.receive((String)null)); 
    } 

    @Test 
    public void sendNullWithCastToArray() { 
     System.out.println("sendNullWithCastToArray(): " + JavaReceiver.receive((String[])null)); 
    } 

    @Test 
    public void sendOneValue() { 
     System.out.println("sendOneValue(): " + JavaReceiver.receive("a")); 
    } 

    @Test 
    public void sendThreeValues() { 
     System.out.println("sendThreeValues(): " + JavaReceiver.receive("a", "b", "c")); 
    } 

    @Test 
    public void sendArray() { 
     System.out.println("sendArray(): " + JavaReceiver.receive(new String[]{"a", "b", "c"})); 
    } 
} 

Chạy này như một sản lượng kiểm tra JUnit:

 
sendNothing(): received 'x' is an array of size 0 
sendNullWithNoCast(): received 'x' is null 
sendNullWithCastToString(): received 'x' is an array of size 1 
sendNullWithCastToArray(): received 'x' is null 
sendOneValue(): received 'x' is an array of size 1 
sendThreeValues(): received 'x' is an array of size 3 
sendArray(): received 'x' is an array of size 3 

Để làm điều này thú vị hơn, chúng ta hãy gọi chức năng từ Groovy 2.1.2 và xem những gì xảy ra. Nó chỉ ra rằng các kết quả không giống nhau! Đây có thể là một lỗi mặc dù.

import org.junit.Test 

class GroovySender { 

    @Test 
    void sendNothing() { 
     System.out << "sendNothing(): " << JavaReceiver.receive() << "\n" 
    } 

    @Test 
    void sendNullWithNoCast() { 
     System.out << "sendNullWithNoCast(): " << JavaReceiver.receive(null) << "\n" 
    } 

    @Test 
    void sendNullWithCastToString() { 
     System.out << "sendNullWithCastToString(): " << JavaReceiver.receive((String)null) << "\n" 
    } 

    @Test 
    void sendNullWithCastToArray() { 
     System.out << "sendNullWithCastToArray(): " << JavaReceiver.receive((String[])null) << "\n" 
    } 

    @Test 
    void sendOneValue() { 
     System.out << "sendOneValue(): " + JavaReceiver.receive("a") << "\n" 
    } 

    @Test 
    void sendThreeValues() { 
     System.out << "sendThreeValues(): " + JavaReceiver.receive("a", "b", "c") << "\n" 
    } 

    @Test 
    void sendArray() { 
     System.out << "sendArray(): " + JavaReceiver.receive(["a", "b", "c"] as String[]) << "\n" 
    } 

} 

Chạy thử này như một thử nghiệm JUnit cho kết quả như sau, với sự khác biệt với Java được in đậm.

 
sendNothing(): received 'x' is an array of size 0 
sendNullWithNoCast(): received 'x' is null 
sendNullWithCastToString(): received 'x' is null 
sendNullWithCastToArray(): received 'x' is null 
sendOneValue(): received 'x' is an array of size 1 
sendThreeValues(): received 'x' is an array of size 3 
sendArray(): received 'x' is an array of size 3 
1

tôi thích

foo(new Object[0]); 

để tránh trường hợp ngoại lệ con trỏ Null.

Hy vọng điều đó sẽ hữu ích.

+8

Vâng, nếu nó là một phương pháp vararg, tại sao không chỉ gọi nó là 'foo()'? –

+0

@ BrainStorm.exe câu trả lời của bạn phải được đánh dấu là câu trả lời. cảm ơn. –

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