2010-05-27 37 views
7

tham khảo: http://java.sun.com/j2se/1.5.0/docs/guide/language/autoboxing.htmlTại sao autoboxing trong Java cho phép tôi có 3 giá trị có thể cho một boolean?

"Nếu chương trình của bạn cố gắng autounbox null, nó sẽ ném một NullPointerException."

javac sẽ cung cấp cho bạn lỗi biên dịch nếu bạn cố gán giá trị null cho boolean. có ý nghĩa. gán null cho Boolean là a-ok. cũng có ý nghĩa, tôi đoán vậy.

nhưng hãy suy nghĩ về thực tế là bạn sẽ nhận được NPE khi cố gắng tự động hủy hộp thư. điều này có nghĩa là bạn không thể thực hiện các thao tác boolean một cách an toàn trên Booleans mà không cần kiểm tra null hoặc xử lý ngoại lệ. tương tự như khi thực hiện các phép toán trên một số nguyên.

trong một thời gian dài, tôi là một fan hâm mộ của autoboxing trong java1.5 + bởi vì tôi nghĩ rằng nó có java gần hơn để được thực sự hướng đối tượng. nhưng, sau khi chạy vào vấn đề này tối qua, tôi phải nói rằng tôi nghĩ rằng điều này hút. trình biên dịch cho tôi một lỗi khi tôi đang cố gắng để làm công cụ với một nguyên thủy uninitialized là một điều tốt. Tôi không muốn sử dụng autoboxing nếu tôi bị mất.

Tôi nghĩ rằng tôi có thể hiểu sai về điểm tự động hóa, nhưng đồng thời tôi sẽ không bao giờ chấp nhận rằng boolean sẽ có thể có 3 giá trị. bất cứ ai có thể giải thích điều này? tôi không nhận được gì?

+0

Câu hỏi Có hoặc không có thể có ba câu trả lời: Có, Không, tôi không biết. – ADTC

Trả lời

0

Tự động hóa tự động chuyển đổi các loại dữ liệu giữa các loại nội tại và loại đối tượng.

Loại đối tượng cho Boolean có thể là Boolean.TRUE, Boolean.FALSE hoặc null. Đó là lý do tại sao bạn phải đối phó với 3 giá trị có thể cho một boolean.

Trong cơ sở dữ liệu, thông thường có ba trạng thái cho loại boolean. Xem xét một bản ghi theo dõi xem có ai đó đã vượt qua một lớp học hay không. Có TRUE, để vượt qua; FALSE không được chuyển và NULL cho "hiện đang tham gia lớp học". Có, nó là lẻ, nhưng không có một giá trị được kế thừa trong lập trình hướng đối tượng.

Tôi cũng tìm thấy autoboxing một chút khó chịu, chủ yếu là vì nó là một tính năng mà trình biên dịch thêm bytecode để xử lý quá trình chuyển đổi. Theo tôi, điều này có thể dẫn đến việc mọi người quên đi các chi tiết quan trọng trong quá trình chuyển đổi mà có thể được nhớ rõ hơn (chẳng hạn như xử lý null trong trường hợp của bạn). Nó rất hữu ích, nhưng không hữu ích như hầu hết các tính năng khác của ngôn ngữ Java.

Cá nhân, tôi ước rằng nội tại đã được triển khai dưới dạng đối tượng nhẹ thay vì các loại "được tích hợp sẵn". Có rất nhiều lần mà hệ thống kiểu nội tại/đối tượng lai bị cản trở. Điều đó nói rằng, nội tại được cho là có để cải thiện hiệu suất, nhưng có vẻ như nếu bạn phải làm rất nhiều nội tại đối với marshalling Object, bạn không thể thưởng thức tăng hiệu suất nội tại chỉ.

16

Loại đóng hộp là loại tham chiếu và tất cả các loại tham chiếu, hộp nguyên thủy hay không, có thể tham chiếu đến null. Đó là lý do tại sao một số Boolean có thể tham chiếu đến null. Vì vậy, có thể là Integer. Vì vậy, có thể là String, v.v.

Các loại đóng hộp không được thiết kế để làm cho Java hướng đối tượng thực sự. Java sẽ không bao giờ là ngôn ngữ hướng đối tượng thuần túy và bạn không nên mã hóa như thể đây là trường hợp. Các loại nguyên thủy sẽ không bao giờ biến mất, và trên thực tế nên được ưa thích bất cứ khi nào có sự lựa chọn.

Dưới đây là một trích dẫn từ Effective Java 2nd Edition, khoản 49: thích loại nguyên thủy để nguyên thủy đóng hộp (nhấn mạnh bởi tác giả):

Nói tóm lại, nguyên thủy sử dụng trong các ưu tiên cho đóng hộp nguyên thủy bất cứ khi nào bạn có lựa chọn. Các kiểu nguyên thủy đơn giản và nhanh hơn. Nếu bạn phải sử dụng nguyên thủy đóng hộp, hãy cẩn thận! Autoboxing làm giảm độ dài, nhưng không phải là nguy hiểm, khi sử dụng nguyên thủy đóng hộp. Khi chương trình của bạn so sánh hai nguyên thủy đóng hộp với toán tử ==, nó so sánh danh tính, gần như chắc chắn là không phải là những gì bạn muốn. Khi chương trình của bạn thực hiện các tính toán kiểu hỗn hợp liên quan đến các thành phần nguyên gốc đóng hộp và không hộp, nó sẽ unboxing và khi chương trình của bạn thực hiện unboxing, nó có thể ném NullPointerException. Cuối cùng, khi chương trình của bạn chứa các giá trị nguyên thủy, nó có thể dẫn đến các sáng tạo đối tượng tốn kém và không cần thiết.

+0

Có một vài lần khi autoboxing có thể có vấn đề (IMHO, khi thực hiện độ phân giải quá tải cho một hàm N-argument, autoboxing sẽ bị vô hiệu hóa đối số thứ k nếu đối số K của * bất kỳ * N-đối số quá tải là một nguyên thủy), nhưng tự động unboxing có vẻ nguy hiểm trong hầu hết các tình huống. – supercat

1

Tôi nghĩ nó mang tính triết học hơn là câu hỏi kỹ thuật. Khi bạn chuyển đổi kiểu nguyên thủy thành kiểu tham chiếu, bạn nên sẵn sàng các kiểu tham chiếu (tức là các đối tượng) không có giá trị.

Bạn có thể xem The Billion Dollars Mistake bản trình bày ở đâu C.A.R. Hoare nói rằng việc giới thiệu các tham chiếu rỗng của mình với oop (Algol 60) là một sai lầm.

Josh Bloch trong Java hiệu quả khuyến nghị nên chọn các kiểu nguyên thủy nếu có thể. Nhưng đôi khi bạn phải xác minh biến Boolean của bạn với null.

0

Thực sự không có sự khác biệt lớn so với ngày trước Java 1.5 - vấn đề không phải là kiểu boolean (nó vẫn có hai trạng thái) nhưng trình bao bọc Boolean (luôn có 3 trạng thái Boolean.TRUE, Boolean.FALSE và vô giá trị).

Mọi chuyển đổi từ đối tượng Boolean cho nguyên thủy boolean yêu cầu kiểm tra rỗng, có hoặc không có hộp tự động.

5

Ngoài tất cả mọi thứ được nói ở đây, có những trường hợp bạn rất muốn có giá trị thứ ba cho các phép toán - trường hợp của thuộc tính "tùy chọn".

Chúng tôi thường gặp nó với cơ sở dữ liệu, với các cột boolean cho phép null. Nếu không sử dụng Boolean, chúng ta sẽ cần phải sử dụng hai biến riêng biệt, một biến cho biết giá trị và biến khác cho dù là hợp lệ. Trên thực tế, nếu bạn nhìn vào API JDBC, bạn có thể thấy một ví dụ về vấn đề này, trong đó các cột nhận giá trị mặc định nếu chúng là rỗng (ví dụ, 0 cho trường số), và sau đó bạn phải gọi "wasNull" để kiểm tra xem đó có phải là 0 thực hay không giả!

7

Tôi đã xem ít nhất một trường hợp khi giá trị null hữu ích. Nhiều đối tượng dữ liệu trong các dịch vụ web có các trường boolean vô giá trị. Đôi khi người dùng bỏ qua để bao gồm một giá trị. Trong trường hợp này, bạn muốn có thể phân biệt được thiếu giá trị từ một giá trị mặc định. Trước đây, mọi người sẽ viết các phương thức getX, setXisXSet(), trong đó isXSet trả về false cho đến khi ai đó gọi setX. Bây giờ có thể làm cho X là một loại có thể vô hiệu hóa và rõ ràng là nó không được đặt nếu getX trả về null.

0

Đó là vấn đề với autoboxing, giống như Integer i = null;. Integer đối tượng có thể là null trong khi một bản địa int không thể.

4

Vấn đề của bạn là tự động un quyền anh, chứ không phải tự động. Tôi nghĩ autounboxing là ác vì những lý do quan trọng hơn:

Hãy xem xét điều này:

Integer i = new Integer(1); 
Integer i2 = new Integer(12); 

System.out.println(i == 10 || i != i2); 

Một == unboxes và người kia thì không.

Mở hộp trên các toán tử (trái ngược với các nhiệm vụ) là một sai lầm trong quan điểm của tôi (được đưa ra ở trên - nó không chỉ là Java). Boxing, tuy nhiên, là rất tốt đẹp.

0

Nó chưa bao giờ có ý định, với việc giới thiệu hộp số tự động, nó thay thế nguyên thủy. Ở hầu hết các nơi nguyên thủy là những gì bạn muốn. Nếu bạn muốn bắt đầu sử dụng các kiểu tham chiếu vì "nó có java gần hơn để thực sự hướng đối tượng" thì đó là cuộc gọi của bạn, nhưng khi bạn đang khám phá, có những nhược điểm với cách tiếp cận đó. Hiệu suất sẽ là một vấn đề khác.

Tự động tạo hộp (và tự động phát) có sẵn để trợ giúp chuyển tiếp giữa mã sử dụng nguyên thủy (phần lớn) và mã phải sử dụng loại tham chiếu (hiếm). Trong số các kiểu tham chiếu, Boolean chắc chắn là hiếm nhất, vì số lượng các cá thể nhỏ của nó có nghĩa là nó gần như không bao giờ có giá trị trong một Collection.

Tóm lại: nếu các loại tham chiếu gây ra rắc rối cho bạn, đừng sử dụng chúng. Nhưng đừng nói 'autoboxing là xấu' chỉ vì chúng không thành công trong tình huống của bạn.

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