Solución:
Restringen el alcance variable.
public void foo()
{
{
int i = 10;
}
System.out.println(i); // Won't compile.
}
En la práctica, sin embargo, si se encuentra utilizando un bloque de código de este tipo, probablemente sea una señal de que desea refactorizar ese bloque en un método.
La respuesta de @David Seiler es correcta, pero yo diría que los bloques de código son muy útiles y deben usarse con frecuencia y no necesariamente indican la necesidad de factorizar en un método. Encuentro que son particularmente útiles para construir árboles de componentes de swing, por ejemplo:
JPanel mainPanel = new JPanel(new BorderLayout());
{
JLabel centerLabel = new JLabel();
centerLabel.setText("Hello World");
mainPanel.add(centerLabel, BorderLayout.CENTER);
}
{
JPanel southPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0,0));
{
JLabel label1 = new JLabel();
label1.setText("Hello");
southPanel.add(label1);
}
{
JLabel label2 = new JLabel();
label2.setText("World");
southPanel.add(label2);
}
mainPanel.add(southPanel, BorderLayout.SOUTH);
}
Los bloques de código no solo limitan el alcance de las variables lo más estrictamente posible (lo que siempre es bueno, especialmente cuando se trata de variables de estado mutable y no finales), sino que también ilustran la jerarquía de componentes de forma muy similar a la creación de XML / HTML. el código es más fácil de leer, escribir y mantener.
Mi problema al factorizar cada instancia de componente en un método es que
- El método solo se utilizará una vez y se expondrá a una audiencia más amplia, incluso si es un método de instancia privada.
- Es más difícil de leer, imaginando un árbol de componentes más profundo y complejo, tendrías que profundizar para encontrar el código que te interesa y luego perder el contexto visual.
En este ejemplo de Swing, encuentro que cuando la complejidad realmente crece más allá de la capacidad de administración, indica que es hora de factorizar una rama del árbol en una nueva clase en lugar de un montón de métodos pequeños.
Por lo general, es mejor hacer que el alcance de las variables locales sea lo más pequeño posible. Los bloques de código anónimos pueden ayudar con esto.
Encuentro esto especialmente útil con switch
declaraciones. Considere el siguiente ejemplo, sin bloques de código anónimos:
public String manipulate(Mode mode) {
switch(mode) {
case FOO:
String result = foo();
tweak(result);
return result;
case BAR:
String result = bar(); // Compiler error
twiddle(result);
return result;
case BAZ:
String rsult = bar(); // Whoops, typo!
twang(result); // No compiler error
return result;
}
}
Y con bloques de código anónimos:
public String manipulate(Mode mode) {
switch(mode) {
case FOO: {
String result = foo();
tweak(result);
return result;
}
case BAR: {
String result = bar(); // No compiler error
twiddle(result);
return result;
}
case BAZ: {
String rsult = bar(); // Whoops, typo!
twang(result); // Compiler error
return result;
}
}
}
Considero que la segunda versión es más limpia y más fácil de leer. Y reduce el alcance de las variables declaradas dentro del cambio al caso en el que fueron declaradas, que en mi experiencia es lo que quieres el 99% del tiempo de todos modos.
Sin embargo, ten en cuenta que lo hace no cambiar el comportamiento para la caída del caso; aún deberá recordar incluir un break
o return
para prevenirlo!