Tôi đã tìm thấy một lỗi khác thường trong mã của mình gần đây thông qua thử nghiệm ngẫu nhiên. Vì vậy, tôi đã thực hiện một trường hợp thử nghiệm cho nó.Trong toán tử ternary của Java, đối số đầu tiên có thể được đánh giá ngay cả khi biểu thức dẫn đến giá trị sai?
Đây là trường hợp thử nghiệm của tôi:
SampleRequest request = new SampleRequest();
request.setA(null);
request.setB(null);
assertEquals(null, request.getAOrB());
A và B được định nghĩa là loại java.lang.Integer và có phương pháp setter trực tiếp để thiết lập giá trị của họ vào yêu cầu.
Ngoài ra còn có một điều tra liên quan. Nó có một giá trị nguyên nguyên, và một phương thức được sử dụng trong mã này. Tôi sẽ đăng các phần có liên quan tại đây:
enum Swapper {
public int c;
Swapper findSwapperToUse(final int a) {
for(Swapper swapper : values()) {
if(swapper.c == a) {
return swapper;
}
}
return null;
}
}
Bây giờ, đây là phương pháp gây nhầm lẫn. Gọi phương thức thử nghiệm trên phương thức đó dẫn đến một NPE, nhưng trên dòng cuối cùng của phương thức.
public class SampleRequest {
private Integer A;
private Integer B;
public void setA(final Integer A) {
this.A = A;
}
public void setB(final Integer B) {
this.B = B;
}
public Integer getAOrB() {
return A != null ? Swapper.findSwapperToUse(A).c
: B;
}
}
Trong thử nghiệm, cả A và B được đặt thành rỗng. Do đó, A! = Null trả về false. Tuy nhiên, tôi nhận được một NullPointerException tại số dòng cho dòng: B.
Tôi đoán là vì lý do nào đó biểu thức đầu tiên, Swapper.findSwapperToUse (A) .c, đang được đánh giá, và do đó hàm A.intValue() được gọi thông qua autoboxing, dẫn đến NullPointerException trên giá trị null. Thông qua gỡ lỗi, nó được biết rằng findSwapperToUse() không được gọi.
Tuy nhiên, theo này questionthis không nên xảy ra: Java ternary (immediate if) evaluation
Biểu thức toán hạng không chọn không được đánh giá cho rằng đánh giá cụ thể của biểu thức điều kiện.
Trả về giá trị rỗng (B) sẽ không dẫn đến NullPointerException - hoàn toàn tốt để trả về kết quả rỗng tại đây.
Chuyện quái gì đang xảy ra?
EDIT: Tôi quên thêm rằng tôi thay đổi mã để tránh điều này bằng cách sử dụng một tuyên bố thẳng lên nếu - đoạn mã sau làm việc như mong đợi:
public Integer getAOrB() {
if(A != null) {
return Swapper.findSwapperToUse(A).c;
}
return B;
}
Mã bạn đã nhất định sẽ không biên dịch (ví dụ một thiếu kiểu trả về). Vui lòng đưa ra một ví dụ ngắn nhưng * hoàn chỉnh * và chúng ta sẽ thấy những gì đang diễn ra. –
Làm thế nào bạn có thể được _ABSOLUTELY_ nhất định rằng A là null? –
Tôi đã cung cấp loại trả lại, xin lỗi - đó là Swapper. @Thor - vì thử nghiệm (request.setA (null), request.setB (null)) – MetroidFan2002