IMO, chúng được bao gồm trong Java và C # chủ yếu vì chúng đã tồn tại trong C ++. Câu hỏi thực sự là tại sao C ++ lại như vậy. Theo Thiết kế và tiến hóa của C ++ (§16.3):
Các try
từ khóa là hoàn toàn không cần thiết và như vậy là { }
dấu ngoặc trừ trường hợp nhiều câu lệnh đang thực sự được sử dụng trong một thử khối hoặc một handler. Ví dụ, việc cho phép:
int f()
{
return g() catch(xxii) { // not C++
error("G() goofed: xxii");
return 22;
};
}
Tuy nhiên, tôi thấy điều này rất khó để giải thích rằng sự dư thừa đã được đưa ra để cứu nhân viên hỗ trợ khỏi những người dùng bối rối.
Chỉnh sửa: Về lý do tại sao điều này sẽ gây nhầm lẫn, tôi nghĩ rằng người ta chỉ cần nhìn vào các xác nhận không chính xác trong câu trả lời của @Tom Jeffery (và đặc biệt là số lượng phiếu bầu đã nhận được) để nhận ra rằng sẽ có vấn đề. Đối với trình phân tích cú pháp, điều này thực sự không khác gì so với khớp else
s với if
thiếu niềng răng để buộc các nhóm khác, tất cả catch
các mệnh đề sẽ khớp với gần đây nhất throw
. Đối với những kẻ lạc lõng bao gồm nó, finally
các mệnh đề cũng sẽ làm như vậy. Từ quan điểm của trình phân tích cú pháp, điều này hầu như không đủ khác biệt với tình huống hiện tại cần chú ý - đặc biệt, vì các ngữ pháp hiện nay, thực sự không có gì để nhóm các catch
mệnh đề lại với nhau - các dấu ngoặc đơn nhóm các câu lệnh được điều khiển bởicatch
mệnh đề, không phải là mệnh đề bắt chính chúng.
Từ quan điểm viết một trình phân tích cú pháp, sự khác biệt gần như quá nhỏ để nhận thấy. Nếu chúng ta bắt đầu với một cái gì đó như thế này:
simple_statement: /* won't try to cover all of this */
;
statement: compound_statement
| simple_statement
;
statements:
| statements statement
;
compound_statement: '{' statements '}'
catch_arg: '(' argument ')'
Sau đó, sự khác biệt sẽ là giữa:
try_clause: 'try' statement
và:
try_clause: 'try' compound_statement
Tương tự như vậy, đối với các mệnh đề bắt:
catch_clause: 'catch' catch_arg statement
so với
catch_clause: 'catch' catch_arg compound_statement
Định nghĩa của một khối thử / bắt hoàn chỉnh hoàn toàn không cần phải thay đổi. Dù bằng cách nào, nó sẽ là một cái gì đó như:
catch_clauses:
| catch_clauses catch_clause
;
try_block: try_clause catch_clauses [finally_clause]
;
[Ở đây tôi đang sử dụng [whatever]
để chỉ ra một cái gì đó tùy chọn và tôi bỏ qua cú pháp finally_clause
vì tôi không nghĩ nó có liên quan gì đến câu hỏi.]
Ngay cả khi bạn không cố gắng tuân theo tất cả các định nghĩa ngữ pháp giống như Yacc ở đó, điểm có thể được tóm tắt khá dễ dàng: câu lệnh cuối cùng (bắt đầu bằng try_block
) là catch
mệnh đề khớp với try
mệnh đề - và nó vẫn chính xác là giống nhau cho dù niềng răng có cần thiết hay không.
Để nhắc lại / tóm tắt: các dấu ngoặc nhóm lại với nhau những điều khoản kiểm soát bởi các catch
s, nhưng làm không nhóm catch
là bản thân họ. Như vậy, những cái niềng răng đó hoàn toàn không có tác dụng gì khi quyết định cái nào catch
đi với cái nào try
. Đối với trình phân tích cú pháp / trình biên dịch, tác vụ cũng dễ dàng (hoặc khó) như nhau. Mặc dù vậy, câu trả lời của @ Tom (và số lượng phiếu bầu tăng lên mà nó nhận được) cung cấp bằng chứng rộng rãi về thực tế rằng một sự thay đổi như vậy gần như chắc chắn sẽ gây nhầm lẫn cho người dùng.
for
các bộ phận nên được đặt tên giống nhưinitial
,condition
vàstep
vìinitial
không cần xác định một biến vàstep
không cần phải là một số gia.