2015-06-12 16 views
5

dự án của tôi có mã như sau:Chaining Null-Safe hành

params.stringValue?.trim().replaceAll('aa', 'a') 

Chúng tôi hy vọng rằng nếu params.stringValue là null, mà cảtrim()replaceAll() sẽ không được gọi.

Tuy nhiên chúng tôi đã nhận được một NullPointerException trên dòng này nói rằng replaceAll() không thể được gọi trên một đối tượng rỗng.

Chúng tôi đã phải thay đổi mã để được như thế này:

params.stringValue?.trim()?.replaceAll('aa', 'a') 

Tại sao đoạn mã đầu tiên ở trên không hoạt động? Đây có phải là một lỗi trong Groovy rằng nó tiếp tục đánh giá biểu thức sau khi một null đã được gặp phải một lần?

+0

Tôi nghĩ đó là "tính năng", chứ không phải là lỗi (!) – Armand

Trả lời

4

Đó là cách Groovy hoạt động, thực sự, và đã cắn others:??.

println cuốn sách .author .firstName .trim() concat ("là rất tốt.")

...

Nhìn vào dòng mã này, tôi nghĩ chắc chắn rằng tôi đã được an toàn từ bất kỳ NullPointerException lén lút nào. Nếu cuốn sách, tác giả hoặc firstName là null tôi sẽ chỉ đơn giản là kết thúc in null và không phải lo lắng về concat() phương pháp. Sau khi tất cả, nếu phương thức trim() thành công, không có ý nghĩa trong việc bảo vệ kết quả của nó là null. Và đó là nơi tôi đã sai.

Đã có ít nhất this discussion để thay đổi điều đó:?

một .b.c // Bạn có thấy lỗi? ;)

Tôi sẽ nhận được NullPointerException. Ý tôi là, nếu bạn sử dụng null an toàn? nhà điều hành trong một biểu thức xích, bạn phải sử dụng trong tất cả các thuộc tính bởi vì nếu bạn quên đặt ở một nơi nào đó, bạn sẽ nhận được một lỗi quá. Nó sẽ được tốt đẹp nếu Groovy có thể phát hiện?. toán tử trong một biểu thức, và nó tiêm nó vào các thuộc tính khác nếu nó thấy toán tử bị thiếu. Vì vậy, nếu bạn nhập loại này

a? .b? .e.f? .g // Tôi quên đặt?. ? .n là "f" tài sản một .befg

Groovy có thể sửa chữa nó với một biểu thức null-an toàn thực như thế này:???

một .b .e .f .g

8

Tôi không nghĩ giả định của bạn là chính xác.này:

params.stringValue?.trim().replaceAll('aa', 'a') 

không có nghĩa là:

if(params.stringValue is null) 
    dont proceed to trim() and replaceAll() 

Nó khá có nghĩa là:

if(params.stringValue is null) 
    skip trim() without complain but pass null to replaceAll() 

vì vậy bạn cần phải nói:

params.stringValue?.trim()?.replaceAll('aa', 'a') 

này sẽ bỏ qua cả trim()replaceAll() nếu đối số đến là null.

8

Giả định của bạn chỉ đúng một phần.

Máy điều hành ? không phá vỡ quá trình thực hiện trong trường hợp không có, nó chặn gọi phương thức hiện tại và trả lại null thay vào đó, đó là lý do cần thiết để bảo vệ phía bên phải của chuỗi với ?