Java: Làm thế nào để kiểm tra xem đối tượng có rỗng không?


87

Tôi đang tạo một ứng dụng lấy hình ảnh từ web. Trong trường hợp không lấy được ảnh thì nên sử dụng ảnh cục bộ khác.

Trong khi cố gắng thực hiện các dòng sau:

Drawable drawable = Common.getDrawableFromUrl(this, product.getMapPath());
if (drawable.equals(null)) {
  drawable = getRandomDrawable();
}

Dòng if (drawable.equals (null)) ném một ngoại lệ nếu drawable là null.

Có ai biết nên kiểm tra giá trị của drawable như thế nào để không ném ra một ngoại lệ trong trường hợp nó là null và lấy ra hình ảnh cục bộ (thực thi drawable = getRandomDrawable ())?


23
Sử dụng if (drawable == null) Gọi bất kỳ phương thức nào trên đối tượng NULL là NullPointerException.
diciu

3
Tại sao bạn không viết một câu trả lời thông thường thay vì một bình luận, diciu?
Dừng lại

@JaredBurrows Không chỉnh sửa mã trong câu hỏi theo cách đánh bại mục đích của câu hỏi!
Gilles 'Somali dừng tà ác'

@Gilles Đọc nhận xét biên tập của tôi, tôi đã làm cho mã dễ đọc hơn.
Jared Burrows

@JaredBurrows Không, chỉnh sửa của bạn không phải là thay đổi về “định dạng”. Bạn đã thay đổi mã không hoạt động là đối tượng của câu hỏi, thành mã hoạt động khiến câu hỏi gây tranh cãi.
Gilles 'Somali dừng tà ác'

Câu trả lời:


35

Giải pháp Java 8 đã chỉnh sửa:

final Drawable drawable = 
    Optional.ofNullable(Common.getDrawableFromUrl(this, product.getMapPath()))
        .orElseGet(() -> getRandomDrawable());

Bạn có thể khai báo drawable finaltrong trường hợp này.

Như Chasmo đã chỉ ra, Android hiện không hỗ trợ Java 8. Vì vậy, giải pháp này chỉ có thể thực hiện được trong các bối cảnh khác.


7
Có lẽ không phải là một ý kiến ​​hay - bạn đang quay lại Fortran 60, nơi cả hai bên của điều kiện được đánh giá, sau đó chỉ một bên được sử dụng. Điều này thật tệ nếu nhánh không sử dụng có bất kỳ tính toán nào, điều này luôn đúng, vì vậy nó không phải là một phương pháp nói chung hữu ích. Tôi sẽ chuyển điều kiện sang Commonlớp và cho phép bạn cung cấp URL dự phòng và giữ các trách nhiệm cùng nhau.
Pete Kirkham

1
Ví dụ này hiện được viết lại hoàn toàn bằng Java 8, vì vậy giải pháp của tôi không còn bị đánh giá vô ích nữa (như @PeteKirkham đã chỉ ra trong giải pháp ban đầu của tôi).
phó tế

1
Android không hỗ trợ Java 8. Nó chỉ hỗ trợ tối đa Java 7 (nếu bạn có kitkat) và nó vẫn không có hàm động, chỉ có đường cú pháp mới. Bên cạnh đó, Optional.ofngụ ý rằng giá trị không phải là null, và do đó giá trị là không orElseGetcần thiết. Bạn nên sử dụng Optional.ofNullabletrong trường hợp này.
Martin Seeler

179
Drawable drawable = Common.getDrawableFromUrl(this, product.getMapPath());
if (drawable == null) {
    drawable = getRandomDrawable();
}

Các equals()kiểm tra phương pháp giá trị bình đẳng, có nghĩa là nó sẽ so sánh nội dung của hai đối tượng. Vì nullkhông phải là một đối tượng, điều này xảy ra khi cố gắng so sánh nội dung của đối tượng của bạn với nội dung của null.

Các ==kiểm tra nhà điều hành cho tham khảo bình đẳng, có nghĩa là nó trông cho dù hai đối tượng thực sự là những đối tượng rất giống nhau . Điều này không yêu cầu các đối tượng thực sự tồn tại; hai đối tượng không tồn tại ( nulltham chiếu) cũng bằng nhau.


56
Tôi muốn thêm một mẹo rất có giá trị: Nếu bạn có chuỗi hoặc hằng số để so sánh, hãy luôn đặt chúng trước trong mệnh đề bằng. (if ("coyote" .equals (myDogString))) tốt hơn nhiều so với (if (myDogString.equals ("coyote"))) bởi vì trong trường hợp thứ hai, myDogString có thể rỗng và ném NPE trong khi ở trường hợp đầu tiên thì không 'không thành vấn đề nếu myDogString là null.
Thorsten S.

20
Được biết đến như một điều kiện Yoda: "nếu một con sói, con chó là ..."
Thomas

1
Tôi cũng muốn nói thêm, rằng kể từ Java 7 có một phương pháp Objects.equals (), let đó là bạn không quan tâm đến Yoda cú pháp
maryokhin

21

Tôi sử dụng cách tiếp cận này:

if (null == drawable) {
  //do stuff
} else {
  //other things
}

Bằng cách này, tôi thấy cải thiện khả năng đọc của dòng - khi tôi đọc nhanh qua một tệp nguồn, tôi có thể thấy đó là dấu kiểm.

Liên quan đến lý do tại sao bạn không thể gọi .equals()một đối tượng có thể là null; nếu tham chiếu đối tượng bạn có (cụ thể là 'drawable') trong thực tế null, nó không trỏ đến một đối tượng trên heap. Điều này có nghĩa là không có đối tượng nào trên đống mà lệnh gọi equals()có thể thành công.

May mắn nhất!


4
Tôi cũng thích cấu trúc if (<constant> == <variable>) như một cách để bảo vệ bản thân khỏi bị gán ngẫu nhiên.
Scott

8

DIY

private boolean isNull(Object obj) {
    return obj == null;
}

Drawable drawable = Common.getDrawableFromUrl(this, product.getMapPath());
if (isNull(drawable)) {
    drawable = getRandomDrawable();
}

6
drawable.equals(null)

Dòng trên gọi phương thức "equals (...)" trên đối tượng có thể vẽ.

Vì vậy, khi drawable không phải là null và nó là một đối tượng thực, thì tất cả đều suôn sẻ khi gọi phương thức "equals (null)" sẽ trả về "false"

Nhưng khi "drawable" là null, thì nó có nghĩa là gọi phương thức "equals (...)" trên đối tượng null, có nghĩa là gọi một phương thức trên một đối tượng không tồn tại để nó ném "NullPointerException"

Để kiểm tra xem một đối tượng có tồn tại và nó không phải là null hay không, hãy sử dụng cách sau

if(drawable == null) {
    ...
    ...
}

Trong điều kiện trên, chúng tôi đang kiểm tra xem biến tham chiếu "drawable" là null hoặc chứa một số giá trị (tham chiếu đến đối tượng của nó) vì vậy nó sẽ không ném ra ngoại lệ trong trường hợp drawable là null khi kiểm tra

null == null

là hợp lệ.


5

if (yourObject instanceof yourClassName)sẽ đánh giá falsenếu yourObjectnull.


0

Có thể hiệu quả hơn một chút khi bắt NullPointerException. Các phương pháp trên có nghĩa là thời gian chạy đang kiểm tra con trỏ null hai lần.


1
if x == nullGiải pháp kiểm tra hai lần ở đâu?
chối

Sau câu lệnh if, thời gian chạy sẽ kiểm tra lại một con trỏ null khi đối tượng được sử dụng. Tôi không biết liệu điều này có được trình biên dịch tối ưu hóa hay không.
Tom R

4
Điều này đi ngược lại sự khôn ngoan thông thường, sử dụng các ngoại lệ làm luồng kiểm soát.
James

1
Các ngoại lệ rất tốn kém, vì chúng cần phải tạo toàn bộ hệ thống ngăn xếp.
phó tế

0

Sử dụng google ổi libs để xử lý is-null-check (cập nhật của deamon)

Drawable drawable = Optional.of(Common.getDrawableFromUrl(this, product.getMapPath())).or(getRandomDrawable());

Tốt hơn hãy sử dụng Java 8 Optionalngay hôm nay.
phó tế

-1

Chỉ để đưa ra một số ý tưởng cho nhà phát triển nguồn Java của oracle :-)

Giải pháp đã tồn tại trong .Net và rất dễ đọc hơn!

Trong Visual Basic .Net

Drawable drawable 
    = If(Common.getDrawableFromUrl(this, product.getMapPath())
        ,getRandomDrawable()
        )

Trong C #

Drawable drawable 
    = Common.getDrawableFromUrl(this, product.getMapPath() 
        ?? getRandomDrawable();

Các giải pháp này mạnh mẽ như giải pháp Java Tùy chọn (chuỗi mặc định chỉ được đánh giá nếu giá trị ban đầu là null) mà không sử dụng biểu thức lambda, chỉ cần thêm một toán tử mới.

Để nhanh chóng thấy sự khác biệt với giải pháp Java, tôi đã thêm 2 giải pháp Java

Sử dụng Tùy chọn trong Java

Drawable drawable = 
    Optional.ofNullable(Common.getDrawableFromUrl(this, product.getMapPath()))
        .orElseGet(() -> getRandomDrawable());

Sử dụng {} trong Java

Drawable drawable = Common.getDrawableFromUrl(this, product.getMapPath());
if (drawable != null)
    {
    drawable = getRandomDrawable();
    }

Cá nhân, tôi thích VB.Net nhưng tôi thích ?? C#hoặc if {}giải pháp trong Java ... còn bạn?

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.