2015-03-11 14 views
28

Tôi đã gặp phải một lỗi trong codebase của mình, tôi đã thu hẹp lại những gì gây ra hành vi này. Trường hợp thử nghiệm đầu tiên không thành công, trong khi trường hợp cuối cùng thành công.Không được gõ vào Java

@Test 
public void testBooleanNull1() { 
    Boolean nullB = null; 
    assertFalse(Boolean.valueOf(nullB)); 
} 

@Test 
public void testBooleanNull2() { 
    String nullS = null; 
    assertFalse(Boolean.valueOf(nullS)); 
} 
@Test 
public void testBooleanNull3() { 
    assertFalse(Boolean.valueOf(null)); 
} 

Tôi biết rằng Boolean.valueOf là một phương pháp quá tải với hai biến thể một mất một String và người kia có một nguyên thủy của loại boolean.

Tôi nghi ngờ rằng điều này xảy ra vì auto-boxing nhưng tôi không chắc chắn nếu đó là trường hợp, hơn nữa tôi không biết tại sao null đang được chuyển đổi sang một Boolean như xa như tôi biết null không phải là một hợp lệ primitive loại.

Tôi đã chuyển sang sử dụng BooleanUtils từ Apache Commons, tôi đã yêu cầu điều này tại đây để hiểu rõ hơn về lý do hành vi theo cách này.

+0

xem thêm http://stackoverflow.com/questions/2707322/what-is-null-in-java – cymatist

Trả lời

31

này

Boolean.valueOf(nullB) 

là một lời gọi Boolean#valueOf(boolean).

Không thành công do việc mở hộp số Boolean giá trị nullB không thành công với NullPointerException. Nói cách khác, nó trở nên

boolean val = nullB.booleanValue(); // at runtime nullB stores the value null 
Boolean.valueOf(val) 

Quá trình này được mô tả trong JLS here

Nếu r là một tài liệu tham khảo của loại Boolean, sau đó chuyển đổi unboxing chuyển đổi r vào r.booleanValue()

Điều này

Boolean.valueOf(null) 

đang gọi số overloaded version that accepts a String (từ null không phải là biểu thức hợp lệ của loại boolean).

Trả về Boolean với giá trị được đại diện bởi chuỗi được chỉ định. Boolean trả về đại diện cho giá trị true nếu đối số chuỗi là không null và bằng nhau, bỏ qua trường hợp, với chuỗi "true".

1

Tại sao giải pháp thứ hai thành công? Xem tài liệu của public static Boolean valueOf(String s):

Trả về giá trị Boolean có giá trị được đại diện bởi chuỗi được chỉ định. Boolean trả về đại diện cho một giá trị thực nếu đối số chuỗi là không null và bằng nhau, bỏ qua trường hợp, với chuỗi "true".

Bạn đã chuyển số null vào, vì vậy nó sẽ trả lại false.

5

độ phân giải phương pháp quá tải được mô tả trong JLS:

15.12.2. Biên dịch thời gian Bước 2: Xác định phương pháp Chữ ký

...

  1. Giai đoạn đầu (§15.12.2.2) thực hiện Nghị quyết tình trạng quá tải mà không cho phép đấm bốc hoặc chuyển đổi unboxing, hoặc sử dụng các phương pháp biến arity gọi. Nếu không có phương pháp áp dụng được tìm thấy trong giai đoạn này thì việc xử lý tiếp tục đến giai đoạn thứ hai.

Trong trường hợp của chúng tôi, lựa chọn giữa Boolean.valueOf(boolean)Boolean.valueOf(String) biên dịch chọn valueOf(String) bởi vì nó không cần thiết unboxing.

+0

Câu trả lời này đánh vào móng trên đầu! –

2

Nhìn vào mã nguồn của lớp Boolean

public static Boolean valueOf(String s) { 
    return toBoolean(s) ? TRUE : FALSE; 
} 

.. và sau đó:

private static boolean toBoolean(String name) { 
    return ((name != null) && name.equalsIgnoreCase("true")); 
} 

Nếu đối số chuỗi là null cho Boolean.valueOf(String s), nó sẽ trả về false, vì thế thứ hai trường hợp thành công.

Trong trường hợp đầu tiên, về việc sử dụng Boolean.valueOf mà mất kiểu dữ liệu như boolean, đây là những gì các tài liệu khẳng định:

public static Boolean valueOf(boolean b) 

Returns a Boolean instance representing the specified boolean value. If the specified boolean value is true, this method returns Boolean.TRUE; if it is false, this method returns Boolean.FALSE. If a new Boolean instance is not required, this method should generally be used in preference to the constructor Boolean(boolean), as this method is likely to yield significantly better space and time performance. 

Parameters: 
b - a boolean value. 
Returns: 
a Boolean instance representing b. 

Các tham số cần thiết ở đây là một giá trị boolean mà chấp nhận True hoặc False và không phải là giá trị Boolean chấp nhận True, False hoặc null. Vì bạn đã vượt qua giá trị Boolean và không phải là giá trị boolean, tôi đoán đó là lý do không thành công.

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