Tại sao chính xác Java không cho phép các điều kiện số như if (5) {'}} nếu C không?


33

Tôi có hai chương trình nhỏ này:

C

#include <stdio.h>
int main()
{
    if (5) {
        printf("true\n");
    }
    else {
        printf("false\n");
    }

    return 0;
}

Java

class type_system {
   public static void main(String args[]) {
       if (5) {
           System.out.println("true");
       }
       else {
           System.out.println("false");
       }
   }
}

trong đó báo cáo thông báo lỗi:

type_system.java:4: error: incompatible types: int cannot be converted to boolean
       if (5) {
           ^
1 error

Sự hiểu biết của tôi

Cho đến nay, tôi hiểu ví dụ này như là một minh chứng cho các hệ thống loại khác nhau. C được gõ yếu hơn và cho phép chuyển đổi từ int sang boolean mà không gặp lỗi. Java được gõ mạnh hơn và thất bại, vì không cho phép hội thoại ngầm.

Do đó, câu hỏi của tôi: Tôi đã hiểu nhầm mọi thứ ở đâu?

Những gì tôi không tìm kiếm

Câu hỏi của tôi không liên quan đến phong cách mã hóa xấu. Tôi biết điều đó thật tệ, nhưng tôi quan tâm đến việc tại sao C không cho phép và Java thì không. Do đó, tôi quan tâm đến hệ thống loại ngôn ngữ, đặc biệt là độ mạnh của nó.


22
@toogley: Hệ thống loại trong Java mà bạn muốn biết cụ thể là gì? Hệ thống loại không cho phép điều này vì đặc tả ngôn ngữ cấm nó. Những lý do tại sao C cho phép nó và Java không có mọi thứ để làm với những gì được coi là chấp nhận được ở cả hai ngôn ngữ. Hành vi kết quả của các hệ thống loại là ảnh hưởng của điều đó, không phải là nguyên nhân.
Robert Harvey

8
@toogley: tại sao bạn nghĩ rằng bạn đã hiểu nhầm điều gì đó? Đọc lại văn bản, tôi không hiểu câu hỏi của bạn là gì.
Doc Brown

26
Trên thực tế, đây không phải là một ví dụ về cách gõ yếu trong C. Trước đây (C89), C thậm chí không có kiểu boolean, vì vậy tất cả các hoạt động "boolean" thực sự hoạt động trên intcác giá trị. Một ví dụ thích hợp hơn sẽ là if (pointer).
Rufflewind

5
Tôi đã từ chối vì dường như không có nhiều nghiên cứu được thực hiện để cố gắng hiểu điều này.
jpmc26

11
Có vẻ như câu hỏi ban đầu được hỏi hơi khác so với phiên bản đã chỉnh sửa (đó là lý do tại sao một số ý kiến ​​và câu trả lời dường như đang trả lời một câu hỏi khác). Ở dạng hiện tại, dường như không có câu hỏi nào ở đây. Hiểu lầm gì? Java đang hành xử chính xác như bạn nghĩ.
jamesdlin

Câu trả lời:


134

1. C và Java là các ngôn ngữ khác nhau

Việc họ cư xử khác nhau không đáng ngạc nhiên lắm.

2. C không thực hiện bất kỳ chuyển đổi nào từ intsangbool

Làm thế nào nó có thể? C thậm chí không có một boolloại thực sự để chuyển đổi cho đến năm 1999 . C được tạo ra vào đầu những năm 1970 và iflà một phần của nó trước khi nó thậm chí là C, trở lại khi nó chỉ là một loạt các sửa đổi cho B 1 .

ifkhông chỉ đơn giản là NOPở C trong gần 30 năm. Nó trực tiếp hành động trên các giá trị số. Verbiage trong tiêu chuẩn C ( liên kết PDF ), thậm chí hơn một thập kỷ sau khi giới thiệu bools với C, vẫn chỉ định hành vi của if(p 148) và ?:(p 100) bằng cách sử dụng thuật ngữ "không bằng 0" và "bằng 0 "Thay vì các thuật ngữ Boolean" đúng "hoặc" sai "hoặc một cái gì đó tương tự.

Thuận tiện, ...

3. ... những con số chỉ là những gì hướng dẫn của bộ xử lý hoạt động.

JZJNZlà hướng dẫn lắp ráp x86 cơ bản của bạn để phân nhánh có điều kiện. Các chữ viết tắt là " J ump if Z ero" và " J ump if N ot Z ero". Các tương đương cho PDP-11, nơi C có nguồn gốc, là BEQ(" trang trại B nếu EQ ual") và BNE(" trang trại B nếu N ot E Qual").

Các hướng dẫn này kiểm tra xem thao tác trước đó có dẫn đến 0 hay không và nhảy (hoặc không) tương ứng.

4. Java chú trọng đến an toàn cao hơn nhiều so với C từng làm 2

Và, với sự an toàn trong tâm trí, họ quyết định rằng việc hạn chế ifđể booleans là giá trị chi phí (cả hai đều thực hiện một hạn chế đó và chi phí cơ hội kết quả).


1. B thậm chí không có loại nào cả. Ngôn ngữ hội thường không. Tuy nhiên, B và ngôn ngữ lắp ráp quản lý để xử lý phân nhánh tốt.

2. Theo lời của Dennis Ritchie khi mô tả các sửa đổi được lên kế hoạch cho B đã trở thành C (nhấn mạnh của tôi):

... Dường như một sơ đồ gõ là cần thiết để đối phó với các ký tự và địa chỉ byte, và để chuẩn bị cho phần cứng dấu phẩy động sắp tới. Các vấn đề khác, đặc biệt là kiểm tra giao diện và an toàn , dường như không quan trọng khi chúng trở nên muộn hơn.


13
Điểm hay về biểu thức boolean trong ánh xạ C trực tiếp đến hướng dẫn của bộ xử lý. Tôi đã không nghĩ về điều đó trước đây.
Robert Harvey

17
Tôi nghĩ rằng điểm 4 là sai lệch vì dường như ngụ ý C có một số tiêu điểm an toàn tập trung ... C sẽ cho phép bạn làm bất cứ điều gì bạn muốn: C giả định bạn biết những gì bạn đang làm, thường dẫn đến kết quả thảm hại ngoạn mục.
TemporalWolf

13
@TemporalWolf Bạn nói rằng như thể C cho phép bạn làm những gì bạn muốn là xấu. Sự khác biệt trong quan điểm của tôi là C được viết cho các lập trình viên và một năng lực cơ bản được mong đợi. Java được viết cho khỉ mã và nếu bạn có thể gõ, bạn có thể lập trình trong đó. Thường ngoạn mục xấu nhưng ai quan tâm đúng không? Tôi sẽ không bao giờ quên khi một giáo viên trong lớp java giới thiệu tôi bị buộc phải tham gia vào nhóm CS nhỏ của mình, chỉ ra rằng việc sử dụng đệ quy để tính các số Fibonnaci có thể hữu ích vì nó "dễ viết". Đó là lý do tại sao chúng tôi có phần mềm chúng tôi có.
DRF

25
@DRF Một trong những giáo sư của tôi cho một lớp mạng C nói rằng "C giống như một hộp lựu đạn với tất cả các chân được rút ra." Bạn đã có rất nhiều sức mạnh, nhưng về cơ bản nó được đảm bảo để thổi vào mặt bạn. Trong phần lớn các trường hợp, nó không đáng để gặp rắc rối và bạn sẽ làm việc hiệu quả hơn với ngôn ngữ cấp cao hơn. Tôi đã chuyển mã Python thành hacky C bit-twiddling để tăng tốc độ 6 bậc chưa? Vâng, vâng tôi có. Nhưng đó là ngoại lệ, không phải là quy tắc. Tôi có thể hoàn thành trong một ngày bằng Python, điều đó sẽ khiến tôi mất hai tuần ở C ... và tôi là một lập trình viên C giỏi.
TemporalWolf

11
@DRF Do sự phổ biến của việc khai thác tràn bộ đệm trong phần mềm chính được phát triển bởi các công ty tên tuổi hàng đầu, rõ ràng ngay cả các lập trình viên có năng lực cơ bản cũng không thể tin rằng không bắn vào chân họ.
Phục hồi Monica

14

Dự thảo trực tuyến C 2011

6.8.4.1 if

Ràng buộc câu lệnh

1 Biểu thức kiểm soát của ifcâu lệnh phải có kiểu vô hướng.

Ngữ nghĩa

2 Trong cả hai hình thức, phần thay thế thứ nhất được thực thi nếu biểu thức so sánh không bằng 0. Trong elsebiểu mẫu, phần phụ thứ hai được thực thi nếu biểu thức so sánh bằng 0. Nếu phần thứ nhất đạt được thông qua nhãn, phần phụ thứ hai là không thực hiện được.

3 An elseđược liên kết với từ trước gần nhất nếu được cú pháp cho phép.

Lưu ý rằng mệnh đề này chỉ xác định rằng biểu thức kiểm soát sẽ có loại vô hướng ( char/ short/ int/ long/ v.v.), không cụ thể là loại Boolean. Một nhánh được thực thi nếu biểu thức điều khiển có giá trị khác không.

So sánh với

Đặc tả ngôn ngữ Java SE 8

14.9 Các ifTuyên Bố

Các iftuyên bố cho phép thực hiện điều kiện của một tuyên bố hoặc một sự lựa chọn có điều kiện của hai báo cáo, thực hiện một hay khác nhưng không phải cả hai.
    IfThenStatement :Tuyên bố 
        if ( Biểu hiện )

    IfThenElseStatement :
        if ( biểu thức ) StatementNoShortIf khác Statement

    IfThenElseStatementNoShort If :
        if ( Biểu thức ) StatementNoShort If other StatementNoShort If
Các biểu thức phải có loại booleanhay Boolean, hoặc một lỗi thời gian biên dịch xảy ra.

Java, OTOH, đặc biệt yêu cầu biểu thức kiểm soát trong ifcâu lệnh có kiểu Boolean.

Vì vậy, nó không phải là về việc gõ yếu so với gõ mạnh, mà là về những gì mỗi định nghĩa ngôn ngữ tương ứng chỉ định là một biểu thức kiểm soát hợp lệ.

Chỉnh sửa

Về lý do tại sao các ngôn ngữ khác nhau về khía cạnh đặc biệt này, một số điểm:

  1. C có nguồn gốc từ B, là ngôn ngữ "không chữ" - về cơ bản, mọi thứ đều là một từ 32 đến 36 bit (tùy thuộc vào phần cứng) và tất cả các phép toán số học là các phép toán số nguyên. Hệ thống loại C được bắt vít từng chút một, sao cho ...

  2. C không có loại Boolean riêng biệt cho đến phiên bản 1999 của ngôn ngữ. C chỉ đơn giản tuân theo quy ước B sử dụng số 0 để biểu diễn falsevà khác không để biểu diễn true.

  3. Java sau C vài ngày sau vài thập kỷ và được thiết kế đặc biệt để giải quyết một số thiếu sót của C và C ++. Không còn nghi ngờ gì nữa, việc thắt chặt các hạn chế về những gì có thể là biểu thức kiểm soát trong một iftuyên bố là một phần của điều đó.

  4. Không có lý do để mong đợi bất kỳ hai ngôn ngữ lập trình sẽ làm mọi thứ theo cùng một cách. Ngay cả các ngôn ngữ có liên quan chặt chẽ như C và C ++ cũng phân kỳ theo một số cách thú vị, như bạn có thể có các chương trình C hợp pháp không phải là chương trình C ++ hợp pháp hoặc là chương trình C ++ hợp pháp nhưng có ngữ nghĩa khác nhau, v.v.


Quá buồn, tôi không thể đánh dấu hai câu trả lời là "được chấp nhận" ..
toogley

1
Vâng, đây là một sự phục hồi tốt của câu hỏi. Nhưng câu hỏi hỏi tại sao có sự khác biệt giữa hai ngôn ngữ này. Bạn đã không giải quyết điều này cả.
Dawood nói phục hồi Monica

@DawoodibnKareem: Câu hỏi đặt ra là tại sao C cho phép chuyển đổi từ intđến booleankhi Java thì không. Câu trả lời là không có chuyển đổi như vậy trong C. Các ngôn ngữ khác nhau vì chúng là các ngôn ngữ khác nhau.
John Bode

Có, "nó không phải là về việc đánh máy yếu và mạnh mẽ". Chỉ cần nhìn vào tự động đấm bốc và tự động mở hộp. Nếu C có những cái đó, nó cũng không thể cho phép bất kỳ loại vô hướng nào.
Ded repeatator

5

Nhiều câu trả lời dường như đang nhắm mục tiêu biểu thức gán được nhúng trong biểu thức điều kiện. (Mặc dù đó là một loại cạm bẫy tiềm ẩn đã biết, nhưng nó không phải là nguồn của thông báo lỗi Java trong trường hợp này.)

Có thể điều này là do OP đã không xuất bản thông báo lỗi thực tế và, ^dấu mũ chỉ trực tiếp đến =toán tử gán.

Tuy nhiên, trình biên dịch đang trỏ đến =bởi vì nó là toán tử tạo ra giá trị cuối cùng (và do đó là loại cuối cùng) của biểu thức mà điều kiện nhìn thấy.

Nó đang phàn nàn về việc kiểm tra một giá trị không phải là boolean, với loại lỗi sau:

lỗi: loại không tương thích: int không thể được chuyển đổi sang boolean

Việc kiểm tra các số nguyên, đôi khi thuận tiện, được coi là một cạm bẫy tiềm năng mà các nhà thiết kế Java chọn để tránh. Xét cho cùng, Java có một kiểu dữ liệu boolean thực , mà C thì không (nó không có kiểu boolean) .

Điều này cũng áp dụng cho các con trỏ thử nghiệm của C cho null / non-null thông qua if (p) ...if (!p) ..., điều tương tự Java không cho phép thay vào đó yêu cầu một toán tử so sánh rõ ràng để có được boolean cần thiết.


1
C không có kiểu boolean. Nhưng đó là mới hơn so với iftuyên bố.
MSalters

3
Bool của @MSalters C vẫn là một số nguyên dưới vỏ bọc, do đó bạn có thể làm được bool b = ...; int v = 5 + b;. Điều này khác với các ngôn ngữ có kiểu boolean đầy đủ không thể được sử dụng trong số học.
Jules

Boolean của C chỉ là một số nguyên thực sự nhỏ. "true" và "false" có thể dễ dàng được định nghĩa bằng macro hoặc bất cứ thứ gì.
Oskar Skog

4
@Jules: Bạn đang chỉ ra rằng C có loại an toàn yếu. Chỉ vì một kiểu boolean chuyển đổi thành một giá trị số nguyên không có nghĩa nó một kiểu số nguyên. Theo logic của bạn, các loại số nguyên sẽ là các loại dấu phẩy động vì int v = 5; float f = 2.0 + v;là hợp pháp trong C.
MSalters

1
@MSalters thực sự _Boollà một trong những loại số nguyên không dấu tiêu chuẩn theo định nghĩa của Tiêu chuẩn (xem 6.2.5 / 6).
Ruslan

2

loại không tương thích: int không thể được chuyển đổi sang boolean

Tôi quan tâm tại sao C không cho phép và java thì không. Do đó, tôi quan tâm đến hệ thống loại ngôn ngữ, đặc biệt là độ mạnh của nó.

Có hai phần cho câu hỏi của bạn:

Tại sao Java không chuyển đổi intthành boolean?

Điều này giúp Java có ý định rõ ràng nhất có thể. Nó rất tĩnh, rất "trong khuôn mặt của bạn" với hệ thống loại của nó. Những thứ được tự động nhập kiểu trong các ngôn ngữ khác thì không như vậy, trong Java. Bạn phải viết int a=(int)0.5là tốt. Chuyển đổi floatđể intsẽ mất thông tin; tương tự như chuyển đổi intsang booleanvà do đó sẽ dễ bị lỗi. Ngoài ra, họ sẽ phải chỉ định rất nhiều kết hợp. Chắc chắn, những điều này dường như là rõ ràng, nhưng họ có ý định sai lầm ở phía thận trọng.

Oh, và so sánh với các ngôn ngữ khác, Java là cực kỳ chính xác trong đặc tả của nó, như các bytecode không chỉ là một chi tiết thực hiện nội bộ. Họ sẽ phải chỉ định bất kỳ và tất cả các tương tác, chính xác. Cam kết rất lớn.

Tại sao ifkhông chấp nhận các loại khác hơn boolean?

ifhoàn toàn có thể được định nghĩa là cho phép các loại khác hơn boolean. Nó có thể có một định nghĩa cho biết những điều sau đây là tương đương:

  • true
  • int != 0
  • String với .length>0
  • Bất kỳ tham chiếu đối tượng nào khác không null(và không phải là Booleangiá trị false).
  • Hoặc thậm chí: bất kỳ tham chiếu đối tượng nào khác không phải nullvà có phương thức Object.check_if(được phát minh bởi tôi chỉ cho dịp này) trả về true.

Họ đã không; không có nhu cầu thực sự, và họ muốn có nó mạnh mẽ, tĩnh, minh bạch, dễ đọc, v.v. càng tốt. Không có tính năng ngầm. Ngoài ra, việc triển khai sẽ khá phức tạp, tôi chắc chắn, phải kiểm tra từng giá trị cho tất cả các trường hợp có thể, do đó hiệu năng có thể cũng đóng một yếu tố nhỏ (Java đã từng bị chậm trễ trên các máy tính ngày đó; hãy nhớ rằng không có trình biên dịch JIT với các bản phát hành đầu tiên, ít nhất là không phải trên các máy tính tôi đã sử dụng sau đó).

Lý do sâu xa hơn

Một lý do sâu xa hơn có thể là thực tế là Java có các kiểu nguyên thủy của nó, do đó hệ thống kiểu của nó bị xé giữa các đối tượng và nguyên thủy. Có lẽ, nếu họ đã tránh những thứ đó, mọi thứ sẽ diễn ra theo một cách khác. Với các quy tắc được đưa ra trong phần trước, họ sẽ phải xác định tính trung thực của từng nguyên thủy một cách rõ ràng (vì người nguyên thủy không chia sẻ một siêu hạng, và không có định nghĩa rõ ràng nullcho nguyên thủy). Điều này sẽ biến thành một cơn ác mộng, nhanh chóng.

Triển vọng

Chà, và cuối cùng, có lẽ đó chỉ là sở thích của các nhà thiết kế ngôn ngữ. Mỗi ngôn ngữ dường như quay theo cách riêng của họ ở đó ...

Ví dụ, Ruby không có loại nguyên thủy. Tất cả mọi thứ, nghĩa đen là tất cả, là một đối tượng. Họ có một thời gian rất dễ dàng để đảm bảo rằng mọi đối tượng đều có một phương thức nhất định.

Ruby tìm kiếm sự trung thực trên tất cả các loại đối tượng bạn có thể ném vào nó. Thật thú vị, nó vẫn không có booleanloại (vì nó không có nguyên thủy), nó cũng không có Booleanlớp. Nếu bạn hỏi giá trị của lớp đó là gì true(có sẵn với true.class), bạn sẽ nhận được TrueClass. Lớp đó thực sự có các phương thức, cụ thể là 4 toán tử cho booleans ( | & ^ ==). Ở đây, ifxem xét giá trị của nó falsey khi và chỉ khi nó là falsehoặc nil( nullcủa Ruby). Mọi thứ khác đều đúng. Vì vậy, 0hoặc ""là cả hai sự thật.

Việc họ tạo ra một phương thức Object#truthy?có thể được thực hiện cho bất kỳ lớp nào và trả lại một sự thật riêng lẻ là điều không quan trọng. Ví dụ, String#truthy?có thể đã được triển khai là đúng với các chuỗi không trống hoặc không có gì. Họ đã không, mặc dù Ruby là phản đề của Java trong hầu hết các phòng ban (gõ vịt động với mixin, mở lại các lớp và tất cả những thứ đó).

Điều này có thể gây ngạc nhiên cho một lập trình viên Perl, người đã từng là $value <> 0 || length($value)>0 || defined($value)sự thật. Và như vậy.

Nhập SQL với quy ước rằng nullbên trong bất kỳ biểu thức nào tự động làm cho nó sai, không có vấn đề gì. Vì vậy (null==null) = false. Trong Ruby , (nil==nil) = true. Thời gian hạnh phúc


Trên thực tế, ((int)3) * ((float)2.5)được định nghĩa khá rõ trong Java (nó là 7.5f).
Paŭlo Ebermann

Bạn nói đúng, @ PaŭloEbermann, tôi đã xóa ví dụ đó.
AnoE

Woah ở đó ... sẽ đánh giá cao ý kiến ​​từ những người downvoters và người đã bỏ phiếu để thực sự xóa câu trả lời.
AnoE

Trên thực tế chuyển đổi từ inttới floatcũng mất thông tin nói chung. Có phải Java cũng cấm các diễn viên ngầm như vậy?
Ruslan

@Ruslan no (giống nhau trong thời gian dài → gấp đôi) - Tôi đoán ý tưởng là sự mất thông tin tiềm năng chỉ có ở những nơi ít quan trọng nhất và chỉ xảy ra trong những trường hợp được coi là không quá quan trọng (giá trị số nguyên khá lớn).
Paŭlo Ebermann

1

Ngoài các câu trả lời hay khác, tôi muốn nói về tính nhất quán giữa các ngôn ngữ.

Khi chúng ta nghĩ về một câu lệnh if thuần túy về mặt toán học, chúng ta hiểu rằng điều kiện này có thể đúng hoặc sai, không có giá trị nào khác. Mỗi ngôn ngữ lập trình chính đều tôn trọng lý tưởng toán học này; nếu bạn đưa giá trị Boolean đúng / sai cho câu lệnh if, thì bạn có thể mong đợi thấy hành vi nhất quán, trực quan mọi lúc.

Càng xa càng tốt. Đây là những gì Java thực hiện và chỉ những gì Java thực hiện.

Các ngôn ngữ khác cố gắng mang lại sự tiện lợi cho các giá trị không phải Boolean. Ví dụ:

  • Giả sử nlà một số nguyên. Bây giờ xác định if (n)là tốc ký cho if (n != 0).
  • Giả sử xlà một số dấu phẩy động. Bây giờ xác định if (x)là tốc ký cho if (x != 0 && !isNaN(x)).
  • Giả sử plà một loại con trỏ. Bây giờ xác định if (p)là tốc ký cho if (p != null).
  • Giả sử slà một loại chuỗi. Bây giờ xác định if (s)if (s != null && s != "").
  • Giả sử alà một kiểu mảng. Bây giờ xác định if (a)if (a != null && a.length > 0).

Ý tưởng cung cấp tốc ký if-tests có vẻ tốt trên bề mặt ... cho đến khi bạn gặp phải sự khác biệt trong thiết kế và ý kiến:

  • if (0)được coi là sai trong C, Python, JavaScript; nhưng được đối xử như thật trong Ruby.
  • if ([]) được coi là sai trong Python nhưng đúng trong JavaScript.

Mỗi ngôn ngữ có lý do chính đáng để xử lý biểu thức theo cách này hay cách khác. (Ví dụ: các giá trị giả mạo duy nhất trong Ruby là falsenildo đó 0là sự thật.)

Java đã thông qua một thiết kế rõ ràng để buộc bạn cung cấp giá trị Boolean cho câu lệnh if. Nếu bạn vội vàng dịch mã từ C / Ruby / Python sang Java, bạn không thể giữ bất kỳ sự lỏng lẻo nào nếu các bài kiểm tra không thay đổi; bạn cần viết ra điều kiện một cách rõ ràng bằng Java. Dành một chút thời gian để tạm dừng và suy nghĩ có thể cứu bạn khỏi những sai lầm cẩu thả.


1
Bạn có biết đó x != 0là giống như x != 0 && !isNaN(x)? Ngoài ra, nó thường s != nullcho con trỏ, nhưng một cái gì đó khác cho con trỏ.
Ded repeatator

@Ded repeatator trong ngôn ngữ nào giống nhau?
Paŭlo Ebermann

1
Sử dụng IEEE754, NaN ≠ 0. NaN ≠ mọi thứ. Vì vậy, nếu (x) sẽ thực thi và nếu (! X) cũng sẽ thực thi ...
gnasher729

0

Chà, mọi kiểu vô hướng trong C, con trỏ, boolean (từ C99), số (dấu phẩy động hay không) và phép liệt kê (do ánh xạ trực tiếp vào số) có giá trị falsey "tự nhiên", do đó đủ tốt cho bất kỳ biểu thức điều kiện nào .

Java cũng có những thứ đó (ngay cả khi các con trỏ Java được gọi là tài liệu tham khảo và bị hạn chế rất nhiều), nhưng nó đã giới thiệu tính năng tự động trong Java 5.0, làm vấy bẩn vùng nước không thể chấp nhận được. Ngoài ra, các lập trình viên Java khuyến khích giá trị nội tại của việc gõ nhiều hơn.

Một trong những lỗi mà sinh ra các cuộc tranh luận cho dù hạn chế biểu thức có điều kiện để kiểu boolean là typo viết một bài tập mà so sánh được dự định, mà là không giải quyết bằng cách hạn chế các biểu thức có điều kiện loại ở tất cả , nhưng bằng cách không cho phép sử dụng một phân thể hiện khỏa thân cho giá trị của nó.

Bất kỳ trình biên dịch C hoặc C ++ hiện đại nào xử lý dễ dàng, đưa ra cảnh báo hoặc lỗi cho các cấu trúc nghi vấn đó nếu được hỏi.
Đối với những trường hợp chính xác là những gì đã được dự định, việc thêm dấu ngoặc đơn sẽ giúp.

Tóm lại, việc giới hạn boolean (và tương đương được đóng hộp trong Java) trông giống như một nỗ lực thất bại trong việc tạo ra một lớp lỗi chính tả gây ra bằng cách chọn =cho các lỗi biên dịch gán.


Sử dụng ==với các toán hạng boolean, trong đó toán hạng đầu tiên là một biến (mà sau đó có thể do lỗi đánh máy =) bên trong ifxảy ra ít thường xuyên hơn so với các loại khác, tôi nói, vì vậy đây chỉ là một nỗ lực bán thất bại.
Paŭlo Ebermann

Có 0,0 -> sai và bất kỳ giá trị nào ngoài 0,0 -> đúng không hoàn toàn trông "tự nhiên" đối với tôi.
gnasher729

@ PaŭloEbermann: Một phần kết quả với các tác dụng phụ đáng tiếc, trong khi có một cách dễ dàng để đạt được mục tiêu mà không có tác dụng phụ, là một thất bại rõ ràng trong cuốn sách của tôi.
Ded repeatator

Bạn đang thiếu những lý do khác. Còn về giá trị truthy của "", (Object) "", 0.0, -0.0, NaN, mảng trống rỗng, và Boolean.FALSE? Đặc biệt là cái cuối cùng là buồn cười, vì nó là con trỏ không null (true) mà bỏ hộp thành false. +++ Tôi cũng ghét viết lách if (o != null), nhưng tiết kiệm cho tôi một vài ký tự mỗi ngày và để tôi dành nửa ngày để gỡ lỗi biểu hiện "thông minh" của tôi không phải là vấn đề tốt. Điều đó nói rằng, tôi rất muốn thấy một số cách trung gian cho Java: Các quy tắc hào phóng hơn nhưng không để lại sự mơ hồ nào cả.
maaartinus

@maaartinus: Như tôi đã nói, việc giới thiệu tính năng tự động mở hộp trong Java 5.0 có nghĩa là nếu họ đã gán một giá trị sửa đổi giá trị thật cho null-ness cho các con trỏ, chúng sẽ có một vấn đề. Nhưng đó là một vấn đề với quyền anh tự động (không phải), không phải bất cứ điều gì khác. Một ngôn ngữ không có quyền tự động- (un-) như C hoàn toàn miễn phí.
Ded repeatator

-1

Câu hỏi của tôi không liên quan đến phong cách mã hóa xấu. Tôi biết tính xấu của nó, nhưng tôi xen vào lý do tại sao C không cho phép và java thì không.

Hai trong số các mục tiêu thiết kế của Java là:

  1. Cho phép nhà phát triển tập trung vào vấn đề kinh doanh. Làm cho mọi thứ đơn giản hơn và ít bị lỗi hơn, ví dụ như bộ sưu tập rác để các nhà phát triển không cần phải tập trung vào rò rỉ bộ nhớ.

  2. Di động giữa các nền tảng, ví dụ chạy trên mọi máy tính với bất kỳ CPU nào.

Việc sử dụng chuyển nhượng như một biểu thức đã được biết là gây ra rất nhiều lỗi do lỗi chính tả, vì vậy theo mục tiêu số 1 ở trên, nó không được phép theo cách bạn đang cố gắng sử dụng.

Ngoài ra, suy ra rằng mọi giá trị khác 0 = đúng và mọi giá trị 0 = false không nhất thiết phải là di động (có, tin hay không, một số hệ thống coi 0 là đúng và 1 là sai ), do đó, theo mục tiêu số 2 ở trên, không được phép ngầm . Tất nhiên bạn vẫn có thể sử dụng.


4
Trừ khi nó được thêm vào trong Java 8, không có sự phân tách rõ ràng giữa các kiểu số và Booleans. Để chuyển đổi một giá trị số thành Boolean, bạn phải sử dụng toán tử so sánh; để chuyển đổi giá trị Boolean thành giá trị số mà bạn thường sử dụng toán tử ternary.
Peter Taylor

Bạn có thể tạo ra một trường hợp không cho phép sử dụng một bài tập cho giá trị của nó do những lỗi chính tả đó. Nhưng xem xét mức độ thường xuyên bạn thấy == true và == false trong Java, rõ ràng việc giới hạn biểu thức kiểm soát đối với loại boolean (được đóng hộp tùy chọn) không giúp ích nhiều.
Ded repeatator

Java sẽ đảm bảo tầm quan trọng một cách tầm thường cho "một số hệ thống coi 0 là đúng và 1 là sai" vì Java là 0 và Java là sai. Nó thực sự không quan trọng những gì hệ điều hành nghĩ về nó.
maaartinus

-1

Như một ví dụ về những ngôn ngữ khác làm: Swift yêu cầu một biểu thức của loại hỗ trợ giao thức "BooleanType", có nghĩa là nó phải có phương thức "boolValue". Loại "bool" rõ ràng hỗ trợ giao thức này và bạn có thể tạo các loại của riêng mình hỗ trợ nó. Các kiểu số nguyên không hỗ trợ giao thức này.

Trong các phiên bản cũ hơn của ngôn ngữ, các loại tùy chọn được hỗ trợ "BooleanType" để bạn có thể viết "if x" thay vì "if x! = Nil". Mà thực hiện bằng cách sử dụng một "Bool tùy chọn" rất khó hiểu. Một bool tùy chọn có các giá trị nil, false hoặc true và "if b" sẽ không được thực thi nếu b là nil và được thực thi nếu b là true hoặc false. Điều này không được phép nữa.

Và dường như có một anh chàng thực sự không thích mở ra chân trời của 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.