Câu hỏi Tránh!


tôi sử dụng object != null rất nhiều để tránh NullPointerException.

Có một lựa chọn tốt cho điều này?

Ví dụ:

if (someobject != null) {
    someobject.doCalc();
}

Điều này tránh NullPointerException, khi nó không biết nếu đối tượng là null hay không.

Lưu ý rằng câu trả lời được chấp nhận có thể đã lỗi thời, hãy xem https://stackoverflow.com/a/2386013/12943 cho một cách tiếp cận gần đây hơn.


3553


gốc


@Shervin Khuyến khích null làm cho mã ít dễ hiểu hơn và kém tin cậy hơn. - Tom Hawtin - tackline
Các nhà khai thác Elvis là đề xuất nhưng có vẻ như nó sẽ không ở Java 7. Quá tệ, ?. ?: và? [] là những người tiết kiệm thời gian đáng kinh ngạc. - Scott
Không sử dụng null vượt trội so với hầu hết các đề xuất khác ở đây. Ném ngoại lệ, không trả lại hoặc cho phép null. Từ khóa BTW - 'assert' là vô ích, vì nó bị vô hiệu hóa theo mặc định. Sử dụng cơ chế lỗi luôn được bật - ianpojman
Đây là một lý do tại sao tôi hiện đang sử dụng Scala. Trong tất cả mọi thứ Scala là không nullable. Nếu bạn muốn cho phép để vượt qua hoặc trả về "không có gì", sau đó bạn phải exlicitly sử dụng Option [T] thay vì chỉ là đối số T als hoặc kiểu trả về. - Thekwasti
@thSoft Thật vậy, Scala tuyệt vời Option loại bị hủy hoại bởi sự không sẵn sàng của ngôn ngữ để kiểm soát hoặc không cho phép null. Tôi đã đề cập đến điều này trên các tin tặc và đã được downvoted và nói rằng "không ai sử dụng null trong Scala anyway". Đoán xem, tôi đã tìm được null trong Scala đồng nghiệp. Có, họ đang "làm sai" và phải được giáo dục về nó, nhưng thực tế vẫn là hệ thống kiểu ngôn ngữ nên bảo vệ tôi khỏi điều này và nó không: ( - Andres F.


Các câu trả lời:


Điều này đối với tôi nghe giống như một vấn đề phổ biến hợp lý mà các nhà phát triển trung cấp đến trung cấp có xu hướng phải đối mặt tại một số điểm: họ không biết hoặc không tin tưởng vào các hợp đồng mà họ tham gia và phòng thủ quá nhiều. Ngoài ra, khi viết mã riêng của họ, họ có xu hướng dựa vào việc trả về các giá trị rỗng để chỉ ra một cái gì đó do đó yêu cầu người gọi kiểm tra các giá trị rỗng.

Nói cách khác, có hai trường hợp kiểm tra null xuất hiện:

  1. Trường hợp null là một phản ứng hợp lệ về hợp đồng; và

  2. Đó không phải là câu trả lời hợp lệ.

(2) rất dễ dàng. Sử dụng assert báo cáo (xác nhận) hoặc cho phép lỗi (ví dụ: NullPointerException). Assertions là một tính năng Java được sử dụng rất cao đã được thêm vào trong 1.4. Cú pháp là:

assert <condition>

hoặc là

assert <condition> : <object>

Ở đâu <condition> là một biểu thức boolean và <object> là một đối tượng có toString() đầu ra của phương thức sẽ được bao gồm trong lỗi.

An assert tuyên bố ném một Error (AssertionError) nếu điều kiện không đúng. Theo mặc định, Java bỏ qua các xác nhận. Bạn có thể bật xác nhận bằng cách chuyển tùy chọn -ea với JVM. Bạn có thể bật và tắt xác nhận cho từng lớp và gói. Điều này có nghĩa là bạn có thể xác thực mã với các xác nhận trong khi phát triển và thử nghiệm và vô hiệu hóa chúng trong môi trường sản xuất, mặc dù thử nghiệm của tôi đã hiển thị bên cạnh không có tác động hiệu suất từ ​​các xác nhận.

Không sử dụng xác nhận trong trường hợp này là OK vì mã sẽ chỉ thất bại, đó là điều sẽ xảy ra nếu bạn sử dụng xác nhận. Sự khác biệt duy nhất là với các xác nhận nó có thể xảy ra sớm hơn, theo cách có ý nghĩa hơn và có thể với thông tin bổ sung, có thể giúp bạn tìm ra lý do tại sao nó xảy ra nếu bạn không mong đợi nó.

(1) khó hơn một chút. Nếu bạn không có quyền kiểm soát mã bạn đang gọi thì bạn bị kẹt. Nếu null là một phản hồi hợp lệ, bạn phải kiểm tra nó.

Nếu đó là mã mà bạn kiểm soát, tuy nhiên (và đây thường là trường hợp), thì đó là một câu chuyện khác. Tránh sử dụng null như một phản ứng. Với các phương thức trả về các bộ sưu tập, thật dễ dàng: trả về các bộ sưu tập rỗng (hoặc các mảng) thay cho các giá trị rỗng khá nhiều.

Với các bộ sưu tập không, nó có thể khó hơn. Hãy xem đây là một ví dụ: nếu bạn có các giao diện sau:

public interface Action {
  void doSomething();
}

public interface Parser {
  Action findAction(String userInput);
}

nơi Parser lấy đầu vào của người dùng thô và tìm một cái gì đó để làm, có lẽ nếu bạn đang thực hiện một giao diện dòng lệnh cho một cái gì đó. Bây giờ bạn có thể làm cho hợp đồng mà nó trả về null nếu không có hành động thích hợp. Điều đó dẫn đến việc kiểm tra null mà bạn đang nói đến.

Một giải pháp thay thế là không bao giờ trả về null và thay vào đó hãy sử dụng Mẫu đối tượng Null:

public class MyParser implements Parser {
  private static Action DO_NOTHING = new Action() {
    public void doSomething() { /* do nothing */ }
  };

  public Action findAction(String userInput) {
    // ...
    if ( /* we can't find any actions */ ) {
      return DO_NOTHING;
    }
  }
}

So sánh:

Parser parser = ParserFactory.getParser();
if (parser == null) {
  // now what?
  // this would be an example of where null isn't (or shouldn't be) a valid response
}
Action action = parser.findAction(someInput);
if (action == null) {
  // do nothing
} else {
  action.doSomething();
}

đến

ParserFactory.getParser().findAction(someInput).doSomething();

đó là một thiết kế tốt hơn nhiều vì nó dẫn đến mã súc tích hơn.

Điều đó nói rằng, có lẽ nó là hoàn toàn thích hợp cho phương thức findAction () để ném một ngoại lệ với một thông báo lỗi có ý nghĩa - đặc biệt là trong trường hợp này, nơi bạn đang dựa vào đầu vào của người dùng. Nó sẽ là tốt hơn cho phương pháp findAction để ném một ngoại lệ hơn cho các phương pháp gọi để thổi lên với một NullPointerException đơn giản mà không có lời giải thích.

try {
    ParserFactory.getParser().findAction(someInput).doSomething();
} catch(ActionNotFoundException anfe) {
    userConsole.err(anfe.getMessage());
}

Hoặc nếu bạn cho rằng cơ chế try / catch quá xấu, thay vì Không làm gì thì hành động mặc định của bạn sẽ cung cấp phản hồi cho người dùng.

public Action findAction(final String userInput) {
    /* Code to return requested Action if found */
    return new Action() {
        public void doSomething() {
            userConsole.err("Action not found: " + userInput);
        }
    }
}

2392



Tôi không đồng ý với tuyên bố của bạn về hành động DO_NOTHING. Nếu phương thức hành động tìm không thể tìm thấy một hành động, thì trả về null là điều đúng đắn cần làm. Bạn đã "tìm thấy" một hành động trong mã của bạn vốn không thực sự được tìm thấy, vi phạm nguyên tắc của phương pháp, để tìm một hành động có thể sử dụng được. - MetroidFan2002
Tôi đồng ý rằng null bị lạm dụng trong Java, đặc biệt là với các danh sách. Vì vậy, nhiều apis sẽ tốt hơn nếu họ trả về một danh sách trống / mảng / bộ sưu tập thay vì null. Nhiều lần, null được sử dụng trong đó một ngoại lệ nên được ném thay thế. Một ngoại lệ nên được ném nếu trình phân tích cú pháp không thể phân tích cú pháp. - Laplie Anderson
Ví dụ sau ở đây là IIRC, mẫu thiết kế đối tượng Null. - Steven Evers
@Cshah (và MetroidFan2002). Đơn giản, đặt nó vào hợp đồng và sau đó rõ ràng là một hành động không tìm thấy trả về sẽ không làm gì cả. Nếu đây là thông tin quan trọng cho người gọi, thì hãy cung cấp một cách để khám phá rằng đó là hành động không tìm thấy (nghĩa là cung cấp một phương pháp để kiểm tra xem kết quả có phải là đối tượng DO_NOTHING) hay không. Ngoài ra, nếu hành động bình thường được tìm thấy thì bạn vẫn không nên trả về null mà thay vào đó ném một ngoại lệ đặc biệt cho biết điều kiện đó - điều này vẫn dẫn đến mã tốt hơn. Nếu muốn, hãy cung cấp một phương thức riêng để trả về boolean để kiểm tra xem hành động có tồn tại hay không. - Kevin Brock
Ngắn gọn không bằng mã chất lượng. Tôi xin lỗi bạn nghĩ vậy. Mã của bạn ẩn các tình huống mà lỗi sẽ thuận lợi. - gshauger


Nếu bạn sử dụng (hoặc lập kế hoạch sử dụng) một IDE Java như JetBrains IntelliJ IDEA, Eclipse hoặc Netbeans hoặc một công cụ như findbugs, sau đó bạn có thể sử dụng chú thích để giải quyết vấn đề này.

Về cơ bản, bạn đã có @Nullable và @NotNull.

Bạn có thể sử dụng trong phương thức và tham số, như sau:

@NotNull public static String helloWorld() {
    return "Hello World";
}

hoặc là

@Nullable public static String helloWorld() {
    return "Hello World";
}

Ví dụ thứ hai sẽ không biên dịch (trong IntelliJ IDEA).

Khi bạn sử dụng helloWorld() trong một đoạn mã khác:

public static void main(String[] args)
{
    String result = helloWorld();
    if(result != null) {
        System.out.println(result);
    }
}

Bây giờ trình biên dịch IntelliJ IDEA sẽ cho bạn biết rằng việc kiểm tra là vô ích, vì helloWorld() chức năng sẽ không trả lại null, không bao giờ.

Sử dụng thông số

void someMethod(@NotNull someParameter) { }

nếu bạn viết một cái gì đó như:

someMethod(null);

Điều này sẽ không biên dịch.

Ví dụ cuối cùng sử dụng @Nullable

@Nullable iWantToDestroyEverything() { return null; }

Làm việc này

iWantToDestroyEverything().something();

Và bạn có thể chắc chắn rằng điều này sẽ không xảy ra. :)

Đó là một cách tốt đẹp để cho trình biên dịch kiểm tra một cái gì đó nhiều hơn nó thường làm và để thực thi các hợp đồng của bạn để được mạnh mẽ hơn. Thật không may, nó không được hỗ trợ bởi tất cả các trình biên dịch.

Trong IntelliJ IDEA 10.5 trở đi, họ đã thêm hỗ trợ cho bất kỳ @Nullable  @NotNull triển khai.

Xem bài đăng trên blog Chú thích @ Nullable / @ NotNull linh hoạt và có thể cấu hình được.


518



@NotNull, @Nullable và các chú thích null khác là một phần của JSR 305. Bạn cũng có thể sử dụng chúng để phát hiện các vấn đề tiềm ẩn với các công cụ như FindBugs. - Jacek S
Tôi thấy khó chịu lạ lùng rằng @NotNull & @Nullable giao diện sống trong gói com.sun.istack.internal. (Tôi đoán tôi liên kết com.sun với các cảnh báo về việc sử dụng API độc quyền.) - Jonik
mã di động đi null với jetbrains.I sẽ suy nghĩ hai lần (hình vuông) trước khi buộc xuống để ide level.Like Jacek S cho biết họ là một phần của JSR bất kỳ cách nào mà tôi nghĩ là JSR303 bằng cách này. - Java Ka Baby
Tôi thực sự không nghĩ rằng bằng cách sử dụng một trình biên dịch tùy chỉnh là một giải pháp khả thi cho vấn đề này. - Shivan Dragon
Điều tốt về chú thích, @NotNull và @Nullable là chúng độc đáo làm suy giảm khi mã nguồn được xây dựng bởi một hệ thống không hiểu chúng. Vì vậy, trong thực tế, lập luận rằng mã không di động có thể không hợp lệ - nếu bạn sử dụng một hệ thống hỗ trợ và hiểu các chú thích này, bạn sẽ nhận được lợi ích bổ sung của việc kiểm tra lỗi nghiêm ngặt hơn, nếu không bạn sẽ nhận được ít hơn. xây dựng tốt và chất lượng của chương trình đang chạy của bạn là THE SAME, bởi vì các chú thích này không được thi hành trong thời gian chạy. Bên cạnh đó, tất cả các trình biên dịch là tùy chỉnh ;-) - amn


Nếu không cho phép giá trị null

Nếu phương thức của bạn được gọi ra bên ngoài, hãy bắt đầu với một cái gì đó như thế này:

public void method(Object object) {
  if (object == null) {
    throw new IllegalArgumentException("...");
  }

Sau đó, trong phần còn lại của phương pháp đó, bạn sẽ biết rằng object không phải là null.

Nếu nó là một phương thức nội bộ (không phải là một phần của một API), chỉ cần ghi lại rằng nó không thể là null, và đó là nó.

Thí dụ:

public String getFirst3Chars(String text) {
  return text.subString(0, 3);
}

Tuy nhiên, nếu phương thức của bạn chỉ chuyển giá trị vào, và phương thức tiếp theo truyền nó lên, vv nó có thể gặp vấn đề. Trong trường hợp đó bạn có thể muốn kiểm tra đối số như trên.

Nếu null được cho phép

Điều này thực sự phụ thuộc. Nếu thấy rằng tôi thường làm một cái gì đó như thế này:

if (object == null) {
  // something
} else {
  // something else
}

Vì vậy, tôi chi nhánh, và làm hai điều hoàn toàn khác nhau. Không có đoạn mã xấu, bởi vì tôi thực sự cần phải làm hai việc khác nhau tùy thuộc vào dữ liệu. Ví dụ, tôi nên làm việc trên đầu vào, hoặc tôi nên tính toán một giá trị mặc định tốt?


Thật hiếm khi tôi sử dụng thành ngữ "if (object != null && ...".

Nó có thể dễ dàng hơn để cung cấp cho bạn các ví dụ, nếu bạn hiển thị các ví dụ về nơi bạn thường sử dụng thành ngữ.


282



Điểm trong việc ném IllegalArgumentException là gì? Tôi nghĩ rằng NullPointerException sẽ rõ ràng hơn, và điều đó cũng sẽ bị ném nếu bạn không tự kiểm tra. Tôi sẽ sử dụng khẳng định hoặc không có gì cả. - Axel
Nó không chắc rằng mọi giá trị khác null đều được chấp nhận. Bạn có thể có IllegalArgumentException, OutOfRageException vv vv Đôi khi điều này có ý nghĩa. Lần khác bạn kết thúc việc tạo ra nhiều lớp ngoại lệ không thêm bất kỳ giá trị nào, thì bạn chỉ cần sử dụng IllegalArgumentException. Nó không có ý nghĩa để có một ngoại lệ cho đầu vào null, và một ngoại lệ cho mọi thứ khác. - myplacedk
Có, tôi đồng ý với nguyên tắc không nhanh, nhưng trong ví dụ ở trên, giá trị không được truyền vào, nhưng là đối tượng mà trên đó một phương thức sẽ được gọi. Vì vậy, nó không bằng nhau nhanh chóng, và thêm một kiểm tra null chỉ để ném một ngoại lệ mà sẽ được ném anyway cùng một lúc và địa điểm dường như không làm cho gỡ lỗi bất kỳ dễ dàng hơn. - Axel
Một lỗ hổng bảo mật? JDK đầy mã như thế này. Nếu bạn không muốn người dùng nhìn thấy stacktraces, sau đó chỉ cần vô hiệu hóa chúng. Không ai ngụ ý rằng hành vi không được ghi chép. MySQL được viết bằng C trong đó dereferencing null con trỏ là hành vi không xác định, không có gì giống như ném một ngoại lệ. - fgb
throw new IllegalArgumentException("object==null") - Thorbjørn Ravn Andersen


Wow, tôi gần như ghét phải thêm một câu trả lời khác khi chúng tôi có 57 cách khác nhau để đề xuất NullObject pattern, nhưng tôi nghĩ rằng một số người quan tâm đến câu hỏi này có thể muốn biết rằng có một đề xuất trên bảng cho Java 7 để thêm "xử lý không an toàn"—Một cú pháp được sắp xếp hợp lý cho logic không-nếu-bằng-null.

Ví dụ được đưa ra bởi Alex Miller trông như thế này:

public String getPostcode(Person person) {  
  return person?.getAddress()?.getPostcode();  
}  

Các ?. có nghĩa là chỉ không tham chiếu đến số nhận dạng bên trái nếu nó không phải là null, nếu không thì hãy đánh giá phần còn lại của biểu thức null. Một số người, như thành viên của Java Posse Dick Wall và cử tri tại Devoxx thực sự yêu thích đề xuất này, nhưng cũng có sự phản đối, với lý do nó thực sự khuyến khích sử dụng nhiều hơn null như một giá trị sentinel.


Cập nhật: An đề xuất chính thức cho một toán tử không an toàn trong Java 7 đã được đệ trình theo Dự án Coin. Cú pháp hơi khác một chút so với ví dụ trên, nhưng đó là khái niệm tương tự.


Cập nhật: Đề xuất nhà điều hành không an toàn không đưa nó vào Project Coin. Vì vậy, bạn sẽ không thấy cú pháp này trong Java 7.


215



Tôi nghĩ rằng điều này là sai. Nên có một cách để xác định rằng một biến nhất định là ALWAYS không null. - Thorbjørn Ravn Andersen
Cập nhật: đề xuất sẽ không tạo Java7. Xem blogs.sun.com/darcy/entry/project_coin_final_five . - Boris Terzic
Ý tưởng thú vị nhưng sự lựa chọn cú pháp là vô lý; Tôi không muốn một codebase đầy đủ các dấu hỏi được ghim vào mọi mối nối. - Rob
Toán tử này tồn tại trong Groovy, vì vậy những người muốn sử dụng nó vẫn có tùy chọn đó. - Muhd
Đây là ý tưởng khéo léo nhất mà tôi từng thấy. Nó phải được thêm vào mọi ngôn ngữ hợp lý của cú pháp C. Tôi thà "ghim dấu hỏi" ở khắp mọi nơi hơn là cuộn qua nhiều dòng hoặc tránh "điều khoản bảo vệ" cả ngày. - Victor


Nếu các giá trị không xác định không được phép:

Bạn có thể cấu hình IDE của bạn để cảnh báo bạn về dereferencing null tiềm năng. Ví dụ. trong Eclipse, xem Tùy chọn> Java> Trình biên dịch> Lỗi / Cảnh báo / Phân tích Null.

Nếu giá trị không xác định được cho phép:

Nếu bạn muốn xác định một API mới, nơi các giá trị không xác định có ý nghĩa, sử dụng Mẫu tùy chọn (có thể quen thuộc với các ngôn ngữ chức năng). Nó có những ưu điểm sau:

  • Nó được nêu rõ trong API cho dù đầu vào hay đầu ra có tồn tại hay không.
  • Trình biên dịch buộc bạn phải xử lý trường hợp "không xác định".
  • Tùy chọn là một đơn nguyên, vì vậy không cần kiểm tra chi tiết null, chỉ cần sử dụng map / foreach / getOrElse hoặc một bộ kết hợp tương tự để sử dụng một cách an toàn giá trị (thí dụ).

Java 8 có tích hợp sẵn Optional lớp học (được khuyến nghị); đối với các phiên bản trước, có các lựa chọn thư viện, ví dụ Trái ổi'S Optional hoặc là FunctionalJava'S Option. Nhưng giống như nhiều mẫu kiểu hàm, sử dụng Option trong Java (thậm chí 8) dẫn đến một số bản mẫu hơi, mà bạn có thể giảm bằng cách sử dụng một ngôn ngữ JVM ít chi tiết hơn, ví dụ: Scala hoặc Xtend.

Nếu bạn phải xử lý một API có thể trả về null, bạn không thể làm được gì nhiều trong Java. Xtend và Groovy có Toán tử Elvis  ?: và toán tử dereference không an toàn  ?., nhưng lưu ý rằng điều này trả về null trong trường hợp của một tham chiếu null, do đó, nó chỉ "defers" xử lý thích hợp của null.


177



Thật vậy, mẫu Option là tuyệt vời. Một số tương đương Java tồn tại. Ổi có chứa một phiên bản giới hạn của điều này được gọi là tùy chọn mà lá ra hầu hết các công cụ chức năng. Trong Haskell, mẫu này được gọi là Có thể. - Ben Hardy
Một lớp Tùy chọn sẽ có sẵn trong Java 8 - Pierre Henry
... và nó chưa (chưa) có bản đồ hoặc flatMap: download.java.net/jdk8/docs/api/java/util/Optional.html - thSoft
Mẫu Tùy chọn không giải quyết bất kỳ điều gì; thay vì một đối tượng có khả năng rỗng, bây giờ bạn có hai. - Boann
@Boann, nếu được sử dụng cẩn thận, bạn giải quyết tất cả các vấn đề về NPE của bạn. Nếu không, sau đó tôi đoán có một vấn đề "sử dụng". - Louis F.


Chỉ cho tình huống này -

Không kiểm tra nếu một biến là null trước khi gọi một phương thức equals (một ví dụ so sánh chuỗi bên dưới):

if ( foo.equals("bar") ) {
 // ...
}

sẽ dẫn đến NullPointerException nếu foo không tồn tại.

Bạn có thể tránh điều đó nếu bạn so sánh Strings như thế này:

if ( "bar".equals(foo) ) {
 // ...
}

160



Tôi đồng ý - chỉ trong tình huống đó thôi. Tôi không thể đứng lập trình mà đã đưa điều này đến cấp độ không cần thiết tiếp theo và viết nếu (null! = MyVar) ... chỉ trông xấu xí với tôi và không phục vụ mục đích! - Alex Worden
Đây là một ví dụ cụ thể, có lẽ là ví dụ được sử dụng nhiều nhất, về một thực hành tốt chung: nếu bạn biết, hãy luôn làm <object that you know that is not null>.equals(<object that might be null>);. Nó hoạt động cho các phương thức khác ngoài equals nếu bạn biết hợp đồng và những phương pháp đó có thể xử lý null thông số. - Stef
Đây là ví dụ đầu tiên tôi đã thấy Điều kiện Yoda thực sự có ý nghĩa - Erin Drummond
NullPointerExceptions được ném vì một lý do. Chúng được ném bởi vì một đối tượng là null, nơi nó không nên. Đây là công việc của lập trình viên để sửa lỗi này, không ẩn vấn đề. - Oliver Watkins
Try-Catch-DoNothing che giấu vấn đề, đây là một thực hành hợp lệ để làm việc xung quanh việc thiếu đường trong ngôn ngữ. - echox


Với Java 8 đến mới java.util.Optional lớp được cho là giải quyết một số vấn đề. Người ta ít nhất có thể nói rằng nó cải thiện khả năng đọc mã, và trong trường hợp các API công khai làm cho hợp đồng của API rõ ràng hơn với nhà phát triển ứng dụng khách.

Họ làm việc như thế:

Một đối tượng tùy chọn cho một kiểu đã cho (Fruit) được tạo thành kiểu trả về của một phương thức. Nó có thể trống hoặc chứa Fruit vật:

public static Optional<Fruit> find(String name, List<Fruit> fruits) {
   for (Fruit fruit : fruits) {
      if (fruit.getName().equals(name)) {
         return Optional.of(fruit);
      }
   }
   return Optional.empty();
}

Bây giờ hãy xem mã này, nơi chúng tôi tìm kiếm danh sách Fruit (fruits) cho một cá thể Trái cây đã cho:

Optional<Fruit> found = find("lemon", fruits);
if (found.isPresent()) {
   Fruit fruit = found.get();
   String name = fruit.getName();
}

Bạn có thể dùng map() toán tử để thực hiện tính toán trên - hoặc trích xuất một giá trị từ - một đối tượng tùy chọn. orElse() cho phép bạn cung cấp dự phòng cho các giá trị bị thiếu.

String nameOrNull = find("lemon", fruits)
    .map(f -> f.getName())
    .orElse("empty-name");

Tất nhiên, việc kiểm tra giá trị null / trống vẫn còn cần thiết, nhưng ít nhất nhà phát triển ý thức rằng giá trị có thể trống và nguy cơ quên kiểm tra bị giới hạn.

Trong một API được xây dựng từ đầu bằng cách sử dụng Optional bất cứ khi nào một giá trị trả về có thể trống, và trả về một đối tượng đơn giản chỉ khi nó không thể null (quy ước), mã máy khách có thể từ bỏ các kiểm tra null trên các giá trị trả về đối tượng đơn giản ...

Tất nhiên Optional cũng có thể được sử dụng như một đối số phương thức, có lẽ một cách tốt hơn để biểu thị các đối số tùy chọn hơn 5 hoặc 10 phương thức quá tải trong một số trường hợp.

Optional cung cấp các phương pháp tiện lợi khác, chẳng hạn như orElse cho phép sử dụng giá trị mặc định và ifPresent làm việc với biểu thức lambda.

Tôi mời bạn đọc bài viết này (nguồn chính của tôi để viết câu trả lời này), trong đó NullPointerException (và nói chung là con trỏ null) có vấn đề cũng như giải pháp (một phần) do Optional được giải thích rõ ràng: Các đối tượng tùy chọn Java.


135



Ổi của Google có ý nghĩa tùy chọn cho Java 6+. - Bradley Gottfried
nó là rất quan trọng để nhấn mạnh rằng chỉ sử dụng Tùy chọn với ifPresent () không phải thêm nhiều giá trị trên kiểm tra null bình thường. Đó là giá trị cốt lõi là nó là một đơn nguyên có thể được sử dụng trong các chuỗi chức năng của map / flapMap, nó đạt được kết quả tương tự như toán tử Elvis trong Groovy được đề cập ở đâu đó. Mặc dù không có cách sử dụng này, tuy nhiên, tôi thấy cú pháp orElse / orElseThrow cũng rất hữu ích. - Cornel Masson
Blog này có mục nhập tốt trên Tùy chọn winterbe.com/posts/2015/03/15/avoid-null-checks-in-java - JohnC
Tôi thực sự không bao giờ hiểu tại sao mọi người lại hài lòng với mã soạn sẵn này dzone.com/articles/java-8-elvis-operator - Mykhaylo Adamovych
Tại sao mọi người có xu hướng làm điều này if(optional.isPresent()){ optional.get(); } thay vì optional.ifPresent(o -> { ...}) - Satyendra Kumar


Tùy thuộc vào loại đối tượng bạn đang kiểm tra, bạn có thể sử dụng một số lớp trong các giao thức apache như: apache commons lang và apache commons bộ sưu tập

Thí dụ:

String foo;
...
if( StringUtils.isBlank( foo ) ) {
   ///do something
}

hoặc (tùy thuộc vào những gì bạn cần kiểm tra):

String foo;
...
if( StringUtils.isEmpty( foo ) ) {
   ///do something
}

Lớp StringUtils chỉ là một trong nhiều; có khá một vài lớp học tốt trong commons mà không thao tác an toàn null.

Dưới đây là một ví dụ về cách bạn có thể sử dụng vallidation null trong JAVA khi bạn bao gồm thư viện apache (commons-lang-2.4.jar)

public DOCUMENT read(String xml, ValidationEventHandler validationEventHandler) {
    Validate.notNull(validationEventHandler,"ValidationHandler not Injected");
    return read(new StringReader(xml), true, validationEventHandler);
}

Và nếu bạn đang sử dụng Spring, Spring cũng có chức năng tương tự trong gói của nó, hãy xem thư viện (spring-2.4.6.jar)

Ví dụ về cách sử dụng lớp tĩnh này từ spring (org.springframework.util.Assert)

Assert.notNull(validationEventHandler,"ValidationHandler not Injected");

113



Ngoài ra, bạn có thể sử dụng phiên bản chung chung hơn từ Apache Commons, khá hữu ích khi bắt đầu các phương thức để kiểm tra các thông số tôi tìm thấy. Validate.notNull (đối tượng, "đối tượng không được null"); commons.apache.org/lang/apidocs/org/apache/commons/lang/… - monojohnny
@monojohnny không Xác thực câu lệnh Assert sử dụng vào ?. tôi hỏi rằng bởi vì Assert có thể được kích hoạt / hủy kích hoạt trên JVM và nó đề nghị không sử dụng trong sản xuất. - Kurapika
Đừng nghĩ như vậy - Tôi tin rằng nó chỉ ném một RuntimeException nếu xác nhận thất bại - monojohnny