IMO, eles estão incluídos em Java e C # principalmente porque já existiam em C ++. A verdadeira questão, então, é por que o C ++ é assim. De acordo com o Design e a evolução do C ++ (§16.3):
A try
palavra-chave é completamente redundante e os { }
colchetes, exceto quando várias instruções são realmente usadas em um bloco de tentativa ou manipulador. Por exemplo, teria sido trivial permitir:
int f()
{
return g() catch(xxii) { // not C++
error("G() goofed: xxii");
return 22;
};
}
No entanto, achei tão difícil explicar que a redundância foi introduzida para salvar a equipe de suporte de usuários confusos.
Edit: Por que isso seria confuso, acho que é preciso apenas olhar para as afirmações incorretas na resposta de Tom Jeffery (e, principalmente, o número de votos recebidos) para perceber que haveria um problema. Para o analisador, isso realmente não é diferente de combinar else
s com if
s - faltando chaves para forçar outro agrupamento, todas as catch
cláusulas corresponderiam às mais recentes throw
. Para aqueles idiomas desonestos que o incluem, as finally
cláusulas fazem o mesmo. Do ponto de vista do analisador, isso dificilmente é diferente da situação atual para notar - em particular, como as gramáticas estão atualmente, não há realmente nada para agrupar as catch
cláusulas - os colchetes agrupam as declarações controladas pelocatch
cláusulas catch, não as próprias cláusulas catch.
Do ponto de vista de escrever um analisador, a diferença é quase pequena demais para se notar. Se começarmos com algo assim:
simple_statement: /* won't try to cover all of this */
;
statement: compound_statement
| simple_statement
;
statements:
| statements statement
;
compound_statement: '{' statements '}'
catch_arg: '(' argument ')'
Então a diferença seria entre:
try_clause: 'try' statement
e:
try_clause: 'try' compound_statement
Da mesma forma, para cláusulas de captura:
catch_clause: 'catch' catch_arg statement
vs.
catch_clause: 'catch' catch_arg compound_statement
A definição de um bloco completo de tentativa / captura não precisaria ser alterada. De qualquer forma, seria algo como:
catch_clauses:
| catch_clauses catch_clause
;
try_block: try_clause catch_clauses [finally_clause]
;
[Aqui estou usando [whatever]
para indicar algo opcional, e estou deixando de fora a sintaxe por um tempo, finally_clause
pois acho que isso não tem nenhuma relação com a questão.]
Mesmo se você não tentar seguir toda a definição gramatical semelhante ao Yacc, o ponto pode ser resumido com bastante facilidade: essa última declaração (começando com try_block
) é aquela em que as catch
cláusulas são correspondidas às try
cláusulas - e permanece exatamente o mesmo se as chaves são necessárias ou não.
Para reiterar / resumir: o grupo de chaves em conjunto as declarações controladas por os catch
s, mas fazer não agrupar a catch
si s. Como tal, esses aparelhos não têm absolutamente nenhum efeito sobre a decisão de qual catch
vai com qual try
. Para o analisador / compilador, a tarefa é igualmente fácil (ou difícil) de qualquer maneira. Apesar disso, @ resposta de Tom (e o número de up-votos é recebido) fornece ampla demonstração do fato de que tal mudança um faria usuários quase certamente Confuse.
for
as partes deve ser nomeado algo comoinitial
,condition
estep
comoinitial
não precisa definir uma variável estep
não precisa ser um incremento.