2011-01-07 4 views
11
public void testFinally(){ 
System.out.println(setOne().toString()); 

} 

protected StringBuilder setOne(){ 
StringBuilder builder=new StringBuilder(); 
try{ 
builder.append("Cool"); 
return builder.append("Return"); 
}finally{ 
builder=null; /* ;) */ 
} 
}

¿por qué la salida es CoolReturn, no nula?conjunto de referencia de objeto a nulo en el bloque final

Saludos,
Mahendra Athneria

Respuesta

14

La expresión se evalúa a un valor en la instrucción de retorno, y ese es el valor que será devuelto. El bloque finally se ejecuta después de la parte de evaluación de expresión de la declaración de devolución.

Por supuesto, el bloque finally podría modificar el contenido del objeto que hace referencia el valor de retorno - por ejemplo:

finally { 
    builder.append(" I get the last laugh!"); 
} 

en cuyo caso la salida de la consola sería "CoolReturn tengo la última palabra! " - pero no puede cambiar el valor que realmente se devuelve.

+0

@Jon, pero ¿por qué 'builder.append (" some value ");' modifica el valor real devuelto mientras 'builder = null' no? –

+2

@Darin: Porque 'builder' es una referencia. Establecer una referencia a nulo desactivó dicha referencia, pero el objeto al que hizo referencia todavía existe hasta que se recolecta basura. 'append', por otro lado, modifica el objeto (o una de sus propiedades) – Powerlord

+3

@Darin: el método de adición devuelve el enlace a la variable a la que se llamó. Así que devuelve builder.append ("algún valor"); en realidad añade "algún valor" al constructor y devuelve el enlace al constructor como objeto, que usted cambia en bloque finalmente. Cuando escribes builder = null, solo cambias los puntos del generador, pero no el valor que se encuentra debajo del enlace anterior. – Maxym

0

El bloque finally se utiliza para "limpieza", después de la ejecución del bloque try. Como ya devolvió la referencia, no puede cambiarla de esta manera.

+0

Creo que es un poco engañoso - si el bloque finally arroja una excepción, por ejemplo, eso terminará siendo lanzado. Creo que es más claro separar la evaluación del valor de retorno (que ocurre antes del bloque finally) y la transferencia de control del método de regreso al llamador (que ocurre después del bloque finally). –

+0

tienes razón, voy a cambiar mi redacción. Pero tu respuesta es buena de todos modos ;-) – morja

2

aparentemente se ve que debe ser nula, pero con el concepto de pase por referencia en java aquí es cómo va:

1> Vuelta builder.append("Return") ... línea es ejecutado y la copia de constructor de referencia es vuelto a la testFinally() método por el pase por referencia

2> Durante la ejecución de builder=null en finalmente bloque de la constructor referencia se elimina la referencia pero el objeto real que está en el montón que se hace referencia en la constructor referencia todavía anteriormente presente en el montón y el copia de regresar de la referencia constructor (que es también una referencia que apunta a la misma objeto) todavía existe y eso mantiene el valor "CoolReturn", por eso está imprimiendo el valor devuelto.

Cuestiones relacionadas