Toán tử Java là gì ?: Được gọi là gì và nó làm gì?


161

Tôi đã làm việc với Java một vài năm, nhưng cho đến gần đây tôi vẫn chưa chạy qua cấu trúc này:

int count = isHere ? getHereCount(index) : getAwayCount(index);

Đây có lẽ là một câu hỏi rất đơn giản, nhưng ai đó có thể giải thích nó? Làm thế nào để tôi đọc nó? Tôi khá chắc chắn rằng tôi biết làm thế nào nó hoạt động.

  • nếu isHerelà đúng, getHereCount()được gọi là,
  • nếu isHerelà sai getAwayCount()được gọi.

Chính xác? Cấu trúc này được gọi là gì?


2
Xem thêm stackoverflow.com/questions/795286/what-does-do-in-c cho phiên bản C ++ của câu hỏi này (thực tế chỉ hỏi ngày hôm qua).
Michael Myers

2
Hãy nhớ rằng thế giới C / C ++ / Java được phân chia khá đồng đều giữa những người cho rằng nó xấu xí và khó hiểu và sẽ tránh nó như bệnh dịch và những người nghĩ rằng bạn thực sự không thể yêu cầu biết C, C ++ hoặc Java nếu bạn không thể nhận ra nó và sử dụng nó mà không dừng lại để suy nghĩ.
Paul Tomblin

3
Nó thường được coi là hình thức xấu trong Java để sử dụng nó vượt ra ngoài các trường hợp rõ ràng và đơn giản nhất. Nếu bạn thấy mình làm tổ chúng, bạn sẽ thoát ra. Mặt khác, trong văn hóa C nơi mã nhanh và thông minh được đánh giá cao trên mức rõ ràng, nó được coi là chấp nhận được.
Yishai

17
answer_to_question = (Recogn_operator)? (social_acceptance): (condesceinating_finger_wag)
Dan

Bạn có thể tham khảo tài nguyên này để biết thêm thông tin.
Shiva

Câu trả lời:


189

Vâng, nó là một hình thức tốc ký của

int count;
if (isHere)
    count = getHereCount(index);
else
    count = getAwayCount(index);

Nó được gọi là toán tử có điều kiện . Nhiều người (gọi nhầm) là toán tử ternary , bởi vì nó là toán tử ternary (ba đối số) duy nhất trong Java, C, C ++ và có lẽ nhiều ngôn ngữ khác. Nhưng về mặt lý thuyết có thể có một toán tử ternary khác, trong khi chỉ có thể có một toán tử có điều kiện .

Tên chính thức được nêu trong Đặc tả ngôn ngữ Java :

§15.25 Toán tử có điều kiện? :

Toán tử điều kiện ? :sử dụng giá trị boolean của một biểu thức để quyết định biểu thức nào trong hai biểu thức khác sẽ được ước tính.

Lưu ý rằng cả hai nhánh phải dẫn đến các phương thức có giá trị trả về:

Đó là một lỗi thời gian biên dịch cho biểu thức toán hạng thứ hai hoặc thứ ba là một lời gọi của một phương thức void.

Trong thực tế, theo ngữ pháp của các câu lệnh biểu thức ( §14.8 ), không được phép xuất hiện một biểu thức có điều kiện trong bất kỳ ngữ cảnh nào mà việc gọi một phương thức void có thể xuất hiện.

Vì vậy, nếu doSomething()doSomethingElse()là các phương thức void, bạn không thể nén điều này:

if (someBool)
    doSomething();
else
    doSomethingElse();

vào đây:

someBool ? doSomething() : doSomethingElse();

Từ ngữ đơn giản:

booleanCondition ? executeThisPartIfBooleanConditionIsTrue : executeThisPartIfBooleanConditionIsFalse 

Tôi không hiểu những gì phía dưới làm điều đó là sai. Tôi tin bạn và tất cả. Nó chỉ giống với bản gốc của tôi. Có phải vì họ chỉ gọi một hàm khác có thể hoặc không trả về giá trị và cho phép mã tiếp theo được đặt?
johnny

8
Tôi giả sử doS Something () và doS SomethingElse () là các phương thức void. Điều cuối cùng của thông số kỹ thuật nói là toán tử ternary phải trả về một giá trị, vì vậy không có toán hạng nào có thể là các phương thức void.
Michael Myers

Nó nói nhiều hơn một chút. Nó nói toán tử điều kiện không được phép khi phương thức void COULD xuất hiện. Vì vậy, ví dụ, các câu lệnh sau: VALID: Chuỗi x = (false)? "X": "Y"; KHÔNG CÓ GIÁ TRỊ: (sai)? "X": "Y";
kenj0418

4
Không có gì sai khi gọi nó là "nhà điều hành ternary", cũng như không có gì sai sót (năm 2016) khi gọi Obama là "Tổng thống", mặc dù có thể sẽ có những tổng thống khác trong tương lai.
Dawood ibn Kareem

2
@DawoodibnKareem Tôi nghĩ Michael cố tình đưa thevào phần in nghiêng the ternary operatorđó là những gì anh ta nói là sai lầm, không phải ternary operatorlà sai lầm. Các nhà điều hành ternary ngụ ý rằng, như Michael nói, nó là duy nhất, do đó có thể dẫn một giả định không thể có nhà khai thác ternary khác, đó là những gì Michael nói là sai lầm, và tôi muốn đồng ý, nó sẽ được một giả định sai lầm.
Ghoti và Chips

32

Những người khác đã trả lời điều này ở mức độ hợp lý, nhưng thường với tên "toán tử ternary".

Là người bán hàng cho tôi, tôi muốn nói rõ rằng tên của toán tử là toán tử có điều kiện hay "toán tử có điều kiện ?:". Đó là một toán tử ternary (trong đó nó có ba toán hạng) và nó là toán tử ternary duy nhất trong Java tại thời điểm này.

Tuy nhiên, thông số kỹ thuật khá rõ ràng rằng tên của nó là toán tử có điều kiện hoặc "toán tử có điều kiện ?:" Hoàn toàn không rõ ràng. Tôi nghĩ rõ ràng hơn khi gọi nó bằng tên đó, vì nó chỉ ra hành vi của toán tử ở một mức độ nào đó (đánh giá một điều kiện) thay vì chỉ có bao nhiêu toán hạng.


3
Câu trả lời này là đúng kỹ thuật. Tuy nhiên, vì chỉ có một toán tử ternary mà bạn thường thấy nó được gọi là toán tử ternary. Mặc dù tên này không truyền đạt ý nghĩa hoàn chỉnh của toán tử, nó là một tên đã bị mắc kẹt. Nếu bạn đề cập đến tên "toán tử ternary", lập trình viên sẽ biết bạn đang nói về cái gì. Thông số kỹ thuật bạn đề cập cũng đề cập đến toán tử này là "Điều kiện Ternary" có vẻ nhiều thông tin hơn. java.sun.com/docs/books/jls/third_edition/html/ Kẻ
Gary

17
Tôi chỉ nghĩ rằng nó đáng để gọi một cái gì đó bằng tên được xác định của nó. Cụ thể, nếu Java từng có một toán tử ternary khác, những người sử dụng thuật ngữ "toán tử có điều kiện" vẫn sẽ chính xác và không mơ hồ - không giống như những người chỉ nói "toán tử ternary". Đúng, cụm từ "toán tử ternary" đã bị mắc kẹt - câu trả lời của tôi là một phần trong nỗ lực "gỡ bỏ" nó, giống như tôi cố gắng sửa lỗi cho rằng "các đối tượng được thông qua tham chiếu".
Jon Skeet

1
Tôi có thể hướng bạn đến trang này từ Oracle nói về ba "toán tử có điều kiện" nhưng chỉ có một "toán tử ternary" không? Nếu bạn muốn làm rõ nghĩa của bạn về toán tử nào, có lẽ tốt hơn là sử dụng tên mà hầu hết mọi người sử dụng. (Vâng, tôi biết tôi sẽ xuất hiện tại bữa tiệc giống như chủ nhà đang rửa chén đĩa cuối cùng).
Dawood ibn Kareem

@DavidWallace: Sử dụng "toán tử có điều kiện ?:" Thì tốt hơn, IMO - sẽ chỉnh sửa để làm rõ điều đó. Nhưng tôi nghĩ rằng đáng để thuyết phục mọi người sử dụng tên thật của toán tử thay vì tập trung vào một khía cạnh của nó (có bao nhiêu toán hạng) không liên quan gì đến hành vi của nó. (Nó cũng không phải là hiếm đối với hướng dẫn để được ít chính xác hơn so với đặc điểm kỹ thuật, trong đó kêu gọi &&các điều kiện và điều hành, và ||các điều kiện-hoặc nhà điều hành, nhưng sử dụng chỉ là "các nhà điều hành có điều kiện" cho ?:.
Jon Skeet

Tôi không biết. Nếu ai đó nói "nhà điều hành có điều kiện" với tôi, tôi sẽ không chắc họ có ý gì. Nơi tôi đến (nơi đối diện của thế giới từ bạn) mọi người đừng gọi nó là thế này. Nếu họ nói "toán tử ternary" hoặc "toán tử hook", thì tôi hiểu. Tôi ngưỡng mộ tham vọng của bạn, muốn thay đổi cách mọi người nói chuyện. Nếu bất cứ ai có thể làm điều đó, đó là bạn. Nhưng tôi không giữ nhiều hy vọng cũng không thấy nhiều điểm.
Dawood ibn Kareem

17

Theo Đặc tả Sun Java , nó được gọi là Toán tử có điều kiện. Xem phần 15.25. Bạn đúng như những gì nó làm.

Toán tử có điều kiện? : sử dụng giá trị boolean của một biểu thức để quyết định biểu thức nào trong hai biểu thức khác sẽ được ước tính.

Toán tử điều kiện có liên kết cú pháp phải (nó nhóm từ phải sang trái), do đó a? B: c? D: e? F: g có nghĩa giống như a? B: (c? D: (e? F : g)).

ConditionalExpression:
        ConditionalOrExpression
        ConditionalOrExpression ? Expression : ConditionalExpression

Toán tử điều kiện có ba biểu thức toán hạng; ? xuất hiện giữa biểu thức thứ nhất và thứ hai và: xuất hiện giữa biểu thức thứ hai và thứ ba.

Biểu thức đầu tiên phải là kiểu boolean hoặc Boolean, hoặc xảy ra lỗi thời gian biên dịch.


5
int count = isHere ? getHereCount(index) : getAwayCount(index);

có nghĩa :

if (isHere) {
    count = getHereCount(index);
} else {
    count = getAwayCount(index);
}

5

Không chính xác, chính xác:

  1. nếu isHere là true, kết quả của getHereCount () được trả về
  2. khác, kết quả của getAwayCount () được trả về

Điều đó "trở lại" là rất quan trọng. Nó có nghĩa là các phương thức phải trả về một giá trị và giá trị đó phải được gán ở đâu đó.

Ngoài ra, nó không chính xác về mặt cú pháp với phiên bản if-other. Ví dụ:

String str1,str2,str3,str4;
boolean check;
//...
return str1 + (check ? str2 : str3) + str4;

Nếu được mã hóa bằng if-other sẽ luôn dẫn đến nhiều mã byte hơn.


Tôi tin rằng javac là tự do để tạo ra mã byte tương tự. Mặc dù bạn đúng rằng có những trường hợp góc tối mà chúng không tương đương.
Tom Hawtin - tackline

Phải, tất nhiên. Đối với tôi, công lao thực sự của toán tử điều kiện là ví dụ tôi đã đưa ra. Thay thế là: // gasp !! Chuỗi temp = str1; if (kiểm tra) temp + = str2; khác temp + = str3; nhiệt độ + = str4; trở lại tạm thời; hoặc mã hóa thao tác nối thêm StringBuilder. Người thứ nhất phải chịu vấn đề hiệu quả nghiêm trọng trong khi người thứ hai quá dài dòng và là một nỗ lực miệt mài mà không đạt được nhiều kết quả.
RichN

4

Ternary, có điều kiện; cà chua, cà chua. Những gì nó thực sự có giá trị là khởi tạo biến. Nếu (như tôi) bạn thích khởi tạo các biến nơi chúng được xác định, toán tử ternary có điều kiện (cho cả hai) cho phép bạn làm điều đó trong trường hợp có điều kiện về giá trị của nó. Đặc biệt đáng chú ý trong các lĩnh vực cuối cùng, nhưng cũng hữu ích ở nơi khác.

ví dụ:

public class Foo {
    final double    value;

    public Foo(boolean positive, double value) {
        this.value = positive ? value : -value;
    }
}

Nếu không có toán tử đó - bằng bất kỳ tên nào - bạn sẽ phải làm cho trường không phải là cuối cùng hoặc viết một hàm đơn giản để khởi tạo nó. Trên thực tế, điều đó không đúng - nó vẫn có thể được khởi tạo bằng if / other, ít nhất là trong Java. Nhưng tôi thấy cái này sạch hơn.



3

Cấu trúc này được gọi là Toán tử Ternary trong các kỹ thuật lập trình và khoa học máy tính.
Wikipedia gợi ý giải thích sau:

Trong khoa học máy tính, một toán tử ternary (đôi khi được gọi không chính xác là toán tử bậc ba) là một toán tử có ba đối số. Các đối số và kết quả có thể có các loại khác nhau. Nhiều ngôn ngữ lập trình sử dụng cú pháp giống như C có một toán tử ternary,?:, Định nghĩa một biểu thức điều kiện.

Không chỉ trong Java, cú pháp này cũng có sẵn trong PHP, Objective-C.

Trong liên kết sau đây, nó đưa ra lời giải thích sau, rất tốt để hiểu nó:

Một toán tử ternary là một số hoạt động hoạt động trên 3 đầu vào. Đó là một lối tắt cho một câu lệnh if-other và còn được gọi là toán tử có điều kiện.

Trong Perl / PHP, nó hoạt động như:
boolean_condition ? true_value : false_value

Trong C / C ++, nó hoạt động như:
logical expression ? action for true : action for false

Điều này có thể dễ đọc đối với một số điều kiện logic không quá phức tạp nếu không sử dụng khối If-Else tốt hơn với sự kết hợp dự định của logic điều kiện.

Chúng ta có thể đơn giản hóa các khối If-Else với toán tử Ternary này cho một dòng lệnh mã.
Ví dụ:

if ( car.isStarted() ) {
     car.goForward();
} else {
     car.startTheEngine();
}

Có thể bằng như sau:

( car.isStarted() ) ? car.goForward() : car.startTheEngine();

Vì vậy, nếu chúng tôi đề cập đến tuyên bố của bạn:

int count = isHere ? getHereCount(index) : getAwayCount(index);

Nó thực sự tương đương 100% với khối If-Else sau:

int count;
if (isHere) {
    count = getHereCount(index);
} else {
    count = getAwayCount(index);
}

Đó là nó!
Hy vọng điều này hữu ích cho ai đó!
Chúc mừng!


2

Chính xác. Nó được gọi là các nhà điều hành ternary . Một số người cũng gọi nó là toán tử có điều kiện .


9
Để trích dẫn Alice In Wonderland, nó được gọi là toán tử ternary, nhưng tên của nó là Toán tử có điều kiện.
Paul Tomblin

Nhưng tên của nó được gọi là toán tử dấu hai chấm.
Michael Myers

1
Đặt tên âm thanh một chút C ++ ish. Toán tử dấu chấm hỏi ?: (Một mã thông báo) được gọi là toán tử Elvis.
Tom Hawtin - tackline

2

Toán tử Ternary của nó (? :)

The ternary operator is an operator that takes three arguments. The first 
argument is a comparison argument, the second is the result upon a true 
comparison, and the third is the result upon a false comparison.

1

Bạn có thể quan tâm đến một đề xuất cho một số toán tử mới tương tự như toán tử có điều kiện. Các toán tử an toàn null sẽ kích hoạt mã như thế này:

String s = mayBeNull?.toString() ?: "null";

Nó sẽ đặc biệt thuận tiện khi diễn ra tự động unboxing.

Integer ival = ...;  // may be null
int i = ival ?: -1;  // no NPE from unboxing

Nó đã được chọn để xem xét thêm theo "Project Coin" của JDK 7.


Toán tử đó không phải là một trong những mục yêu thích của tôi từ Project Coin. Tính hữu dụng hạn chế, không trực quan để đọc, và chỉ đơn giản là xấu xí như tất cả thoát ra. Có lẽ nó sẽ phát triển trên tôi, mặc dù.
Michael Myers

Tôi thực sự không phải là một fan hâm mộ lớn. Đó là một đề xuất của Neal Gafter và anh ta có xu hướng nhìn mọi thứ rất khác với lập trình viên Java trung bình của bạn, người có xu hướng nhìn mọi thứ khác với con người bình thường của bạn. Những nơi duy nhất tôi có thể muốn một chút trợ giúp với null là trong vòng lặp foreach, kiểm tra xem iterable có null hay không và tự động hủy hộp.
erickson

IIRC <Neal đã không đề xuất nó. Ông chỉ sử dụng nó như một ví dụ đơn giản về cách viết một đề xuất. Thêm chi tiết về lưu trữ danh sách gửi thư dự án.
Tom Hawtin - tackline

Tôi chỉ đọc phần giới thiệu cho lời đề nghị, và bạn đã đúng. Đó là Stephen Colebourne của Joda và "không có Java 7" nổi tiếng.
erickson

1

Trên thực tế, nó có thể mất hơn 3 đối số. Chẳng hạn, nếu chúng ta muốn kiểm tra thời tiết một số dương, âm hay bằng 0, chúng ta có thể làm điều này:

String m= num > 0 ? "is a POSITIVE NUMBER.": num < 0 ?"is a NEGATIVE NUMBER." :"IT's ZERO.";

tốt hơn là sử dụng if, other if, other.


0

Đó là toán tử có điều kiện và nó không chỉ là một cách viết ngắn gọn nếu viết.

Vì nó là một biểu thức trả về một giá trị, nó có thể được sử dụng như một phần của các biểu thức khác.


0

Ư, bạn đung. ?: thường được gọi là "toán tử điều kiện ternary", thường được gọi đơn giản là "toán tử ternary". Nó là phiên bản tốc ký của tiêu chuẩn nếu / khác có điều kiện.

Toán tử điều kiện Ternary


0

Tôi thực sự thích toán tử này, nhưng người đọc nên được xem xét.

Bạn luôn phải cân bằng sự gọn nhẹ của mã với thời gian đọc nó, và trong đó nó có một số sai sót khá nghiêm trọng.

Trước hết, đó là trường hợp của Người hỏi gốc. Ông chỉ dành một giờ để đăng về nó và đọc các phản hồi. Mất bao lâu để tác giả viết mỗi lần ?: Như một / sau đó trong suốt cuộc đời của mình. Không một giờ để chắc chắn.

Thứ hai, trong các ngôn ngữ giống như C, bạn có thói quen chỉ đơn giản là biết rằng các điều kiện là điều đầu tiên trong dòng. Tôi nhận thấy điều này khi tôi đang sử dụng Ruby và bắt gặp những dòng như:

callMethodWhatever(Long + Expression + with + syntax) if conditional

Nếu tôi là người dùng Ruby lâu năm, có lẽ tôi sẽ không gặp vấn đề gì với dòng này, nhưng đến từ C, khi bạn thấy "callMethodWhthing" là điều đầu tiên trong dòng, bạn mong đợi nó sẽ được thực thi. ?: Ít khó hiểu hơn, nhưng vẫn đủ bất thường để ném độc giả đi.

Tuy nhiên, ưu điểm là một cảm giác thực sự tuyệt vời trong bụng của bạn khi bạn có thể viết một câu lệnh 3 dòng trong khoảng trống của 1 dòng. Không thể phủ nhận điều đó :) Nhưng thành thật mà nói, không nhất thiết phải dễ đọc hơn 90% bởi những người ngoài kia chỉ đơn giản vì sự hiếm có của nó.

Khi nó thực sự là một bài tập dựa trên Boolean và các giá trị tôi không gặp vấn đề gì với nó, nhưng nó có thể dễ dàng bị lạm dụng.


0

Biểu thức điều kiện là trong một phong cách hoàn toàn khác nhau, không có rõ ràng nếu trong câu lệnh.

Cú pháp là: boolean-biểu thức? biểu thức1: biểu thức2;

Kết quả của biểu thức điều kiện này là

biểu thức1 nếu biểu thức boolean là đúng;

nếu không thì kết quả là biểu thức2.

Giả sử bạn muốn gán số lượng lớn hơn của biến num1 và num2 cho tối đa. Bạn có thể chỉ cần viết một câu lệnh bằng cách sử dụng biểu thức điều kiện: max = (num1> num2)? num1: num2;

Lưu ý: Các ký hiệu? và: xuất hiện cùng nhau trong một biểu thức điều kiện. Chúng tạo thành một toán tử có điều kiện và còn được gọi là toán tử ternary vì nó sử dụng ba toán hạng. Nó là toán tử ternary duy nhất trong Java.

được trích dẫn từ: Giới thiệu về lập trình Java phiên bản thứ 10 của Y. Daniel Liang trang 126 - 127

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.