Mũi tên (->) ưu tiên / ưu tiên của toán tử là thấp nhất, hoặc mức ưu tiên của gán / gán kết hợp là thấp nhất?


18

JLS :

Các nhà khai thác ưu tiên thấp nhất là mũi tên của một biểu thức lambda (->) , sau đó bởi các nhà khai thác chuyển nhượng.

Theo hướng nào (tăng ưu tiên, giảm ưu tiên)? - "theo sau" có nghĩa là gán có mức ưu tiên cao hơn hoặc mức ưu tiên thấp hơn (đối với toán tử mũi tên)? Tôi đoán, khi tăng, bởi vì "thấp nhất" (đối với mũi tên) có nghĩa là hoàn toàn thấp nhất.

Theo tôi hiểu, mũi tên (->) phải ở dưới cùng của bảng ưu tiên toán tử Princeton này (nằm dưới tất cả các toán tử gán), do đó mũi tên (->) có Mức ưu tiên 0 (không) (theo bảng đó).

Tôi có đúng theo cách hiểu của tôi không?

TestTray dường như nói rằng mức độ ưu tiên của mũi tên ít nhất giống với phép gán ... Thêm vào đó, làm rõ rằng tính kết hợp của mũi tên là Trái-> Tới-> Phải (không giống như gán). Tôi đã không tìm thấy bất kỳ trích dẫn JLS cho tính kết hợp mũi tên.

Tôi luôn luôn nghĩ rằng ưu tiên chuyển nhượng chủ yếu là thấp nhất vì một lý do.


5
The lowest precedence operator is the arrow of a lambda expression.
Kayaman

2
Vâng, sự hiểu biết của bạn là chính xác.
Eran

4
Nếu ->là thấp est , toán tử gán không thể có thấp er được ưu tiên.
Andy Turner

IntFunction fo = a->b->a-b; // in test Ngụ ý ưu tiên / kết hợp của -> nói chung. Vì vậy, tôi quyết định làm rõ -> vị trí ưu tiên / kết hợp trong toàn bộ bảng ưu tiên / kết hợp vì cảm thấy không chắc chắn về nó.
Mã hoàn thành

1
@glglgl ví dụ của bạn IntUnaryOperator op; op = x -> x;là thú vị. Có lẽ (op = x) -> xkhông được xem xét bởi vì op = xkhông phải là một ví dụ hợp lệ của LambdaParameterssản xuất?
Andy Turner

Câu trả lời:


13

Lưu ý câu trước văn bản JLS được trích dẫn :

Ưu tiên giữa các nhà khai thác được quản lý bởi một hệ thống phân cấp các sản phẩm ngữ pháp.

Ngữ pháp của ngôn ngữ Java xác định cấu trúc nào là có thể và mặc nhiên, ưu tiên toán tử.

Ngay cả bảng hoàng tử bạn đã liên kết trạng thái:

Không có bảng ưu tiên toán tử rõ ràng trong Đặc tả ngôn ngữ Java. Các bảng khác nhau trên web và trong sách giáo khoa không đồng ý theo một số cách nhỏ.

Vì vậy, ngữ pháp của ngôn ngữ Java không cho phép các biểu thức lambda ở bên trái của toán tử gán và tương tự, không cho phép các phép gán ở bên trái của ->. Vì vậy, không có sự mơ hồ giữa các toán tử này có thể và quy tắc ưu tiên, mặc dù được quy định rõ ràng trong JLS, trở nên vô nghĩa.

Điều này cho phép biên dịch, ví dụ như một viên ngọc, không có sự mơ hồ:

static Consumer<String> C;
static String S;
public static void main(String[] args)
{
  Runnable r;
  r = () -> C = s -> S = s;
}

10

Đầu tiên, hãy giải thích vấn đề thực tế ở đây.

Giả sử bạn có một định nghĩa như

IntUnaryOperator op;

Sau đây được chấp nhận về mặt cú pháp và hoạt động như mong đợi:

op = x -> x;

Đó là, chúng ta có một hàm nhận dạng trên intđược gán cho opbiến. Nhưng nếu =có mức độ ưu tiên cao hơn, chúng tôi hy vọng Java sẽ hiểu điều này là

(op = x) -> x;

Điều này không hợp lệ về mặt cú pháp, do đó sẽ là một lỗi biên dịch. Do đó, sự phân công không, trong thực tế, có độ ưu tiên cao hơn mũi tên.

Nhưng sau đây cũng OK (giả sử tlà một biến lớp / thể hiện của loại int):

op = x -> t = x;

Điều này biên dịch và hàm, nếu được áp dụng, gán giá trị của toán hạng cho t và cũng trả về nó.

Điều này có nghĩa là mũi tên không có quyền ưu tiên cao hơn nhiệm vụ t = x. Nếu không, nó đã được hiểu là

op = ( x -> t ) = x

và rõ ràng, đây không phải là những gì xảy ra.

Vì vậy, có vẻ như các hoạt động có quyền ưu tiên như nhau. Hơn nữa, họ là liên kết đúng. Điều này được ngụ ý từ ngữ pháp tại JLS chương 19 :

Expression:
  LambdaExpression
  AssignmentExpression

LambdaExpression:
  LambdaParameters -> LambdaBody

...

LambdaBody:
  Expression
  Block

Vì vậy, phía bên phải của cơ thể lambda đưa chúng ta trở lại Expression , điều đó có nghĩa là chúng ta có thể có một lambda (ưu tiên cao hơn) bên trong nó, hoặc một nhiệm vụ (ưu tiên cao hơn) trong đó. Ý tôi là "ưu tiên cao hơn" là bạn càng đi sâu vào các quy tắc sản xuất, biểu thức sẽ được đánh giá càng sớm.

Điều này cũng đúng với toán tử gán:

AssignmentExpression:
  ConditionalExpression
  Assignment

Assignment:
  LeftHandSide AssignmentOperator Expression

Một lần nữa, phía bên phải của bài tập đưa chúng ta trở lại Expression , vì vậy chúng ta có thể có biểu thức lambda hoặc một bài tập ở đó.

Vì vậy, thay vì dựa vào văn bản JLS, ngữ pháp cho chúng ta một mô tả rõ ràng về tình huống.

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.