2012-07-11 12 views
6

me preguntaron en una entrevista qué sucede si ponemos finalmente el bloque entre try y catch block respondí en ese caso el compilador pensará que no hay catch block y ejecutará finalmente finally block. Luego preguntó por qué no es posible poner el código entre try y catch block?¿por qué no es posible insertar código entre try y catch block?

¿Me podría ayudar a ...

+8

Tu respuesta a la primera pregunta es incorrecta. El compilador no va a pensar que no hay un bloque 'catch'. Obviamente sigue ahí en su código, y el hecho de que luego viene justo después del bloque 'finally' causará un error en tiempo de compilación. – BoltClock

+0

BoltClock es correcto, se obtiene un error de compilación en su primera pregunta. * catch * debe estar precedido inmediatamente por * try * – StuartLC

+1

El bloque catch debe estar sintácticamente inmediatamente después del bloque try. No hay otras razones – Sabbath

Respuesta

4

Bueno, eso significaría algo como esto:

try 
{ 
    somCode(); 
} 
someMoreCode(); 
catch 
{ 
} 

Lo que debe significar esto? Esto no es posible porque no tiene semántica, y por lo tanto, los diseñadores de idiomas han decidido que es sintaxis incorrecta.

+1

Sí, es ... uno corto, uno más corto que el tuyo es cierto, pero lo es. Lo que dije es totalmente correcto: esto no pudo ser analizado por el compilador porque los diseñadores de Java decidieron que no tendría sentido, por lo que ha sido prohibido por la sintaxis. exactamente como si dijera "car turkey a come": no tiene semántica y por lo tanto, ha sido prohibido por la sintaxis – Kek

0

tratar de atrapar como .. si .. y demás lo que no hay necesidad de añadir código entre tratar de atrapar bloque

11

Bien, primero lo primero: el compilador no ejecuta el código, simplemente lo compila, lo que le permite ser ejecutado por la JVM.

Empíricamente hablando, eso no tendría demasiado sentido, ya que si tienes algún código que quieras colocar fuera del bloque try pero antes del bloque catch, el código podría ser colocado en el bloque try . La cuestión es que, de todos modos, se comportaría como en el bloque try si piensas en ello.

Vamos asumen esto es válido de Java (esto no compila):

try { 
    throw new Exception(); 
} 
System.out.println("Sup!"); 
catch(Exception e) { } 

Cuando la excepción se tira, esa línea que imprime Sup! seguirá recibiendo saltado como la JVM está buscando para pasar al manejador de excepciones apropiado para tratar Exception. Entonces, de alguna manera, el código se comporta como lo haría si estuviese en el bloque try {} en sí mismo, por lo que no importaría realmente dónde esté, y Java especifica que esto (ahora probado como inútil) construir es ilegal.

¿Qué pasaría si ese código después del intento arrojara otra excepción? Si fuera un código válido, se comportaría como un bloque de captura try ... anidado en el bloque try original. Por supuesto, una vez que las cosas empiezan a complicarse, el enfoque donde no hay una conexión clara entre un intento y un bloque catch puede ser confuso, y la JVM terminaría sin saber qué catch/finally pertenece a qué try block (especialmente dado que el controlador no tiene que estar en la misma función, ¡ni siquiera en el mismo paquete!).

+0

¡la mejor respuesta hasta ahora! (+1) – alfasin

+0

¡Gracias! Se agregaron algunas cosas más (especialmente una declaración más clara sobre la incorrección de mi pequeño fragmento de código Java) –

+1

Nota: a nivel de JVM no es necesario que los bloques try sean anidados. Puedes tener 'foo(); bar(); baz(); ', y tienen ambas excepciones de captura' foo() 'y' baz() 'y saltan al código _same_ catch, mientras que' bar() 'pasa a una diferente. Todo lo que sucede es que hay una tabla que muestra qué rangos de códigos de bytes van a los manejadores de captura; el compilador puede configurar esta tabla de la forma que quiera. Entonces, aunque este tipo de construcción podría confundir a 'javac', la JVM se complace en implementar cualquier semántica que defina para ella. – bdonlan

4

Bueno, la respuesta frípata es que la especificación del idioma lo prohíbe.

Pero retrocedamos un poco y piénselo de otra manera, ¿qué pasa si podría hacer esto?

try { 
    foo(); 
} 
bar(); 
catch (Exception e) { 
    baz(); 
} 

¿Cuál podría ser la semántica de esto? Si detectamos una excepción en foo(), ¿se llama baz()? ¿Qué hay de bar()?Si bar() arroja, ¿captamos la excepción en ese caso?

Si excepciones en bar() son no capturados, y excepción en foo() impiden bar() de funcionamiento, entonces el constructo es equivalente a:

try { 
    foo(); 
} catch (Exception e) { 
    baz(); 
} 
bar(); 

Si excepciones en bar()son capturados, y excepción en foo() evitar que se ejecute bar(), entonces la construcción es equivalente a:

try { 
    foo(); 
    bar(); 
} catch (Exception e) { 
    baz(); 
} 

Si excepciones en bar() son no capturados, y la excepción en foo()No evitar bar() se ejecute (bar() siempre se ejecuta), entonces la construcción es equivalente a:

try { 
    foo(); 
} catch (Exception e) { 
    baz(); 
} finally { 
    bar(); 
} 

Como se puede ver , cualquier semántica razonable para esta construcción entre-prueba-captura ya se puede expresar sin la necesidad de una construcción nueva, y bastante confusa. Es difícil idear un significado para esta construcción que no sea redundante.

Como acotación al margen, una razón potencial que no podemos hacer:

try { 
    foo(); 
} finally { 
    bar(); 
} catch (Exception e) { 
    baz(); 
} 

podría ser que no refleja el orden de ejecución real - bloques catch se ejecutan antes el bloque finally. Esto permite que los bloques catch utilicen los recursos que el bloque finally pueda liberar más tarde (por ejemplo, para solicitar información de diagnóstico adicional de un objeto RPC o algo así). ¿Podría hacerse que funcione también para el otro lado? Por supuesto. ¿Vale la pena? Probablemente no.