method - new in java
Variables y miembros no inicializados en Java (7)
Aquí está el trato. Cuando usted llama
TestClass tc = new TestClass();
el new
comando realiza cuatro tareas importantes:
- Asigna memoria en el montón para el nuevo objeto.
- Inicia los campos de clase a sus valores predeterminados (numéricos a 0, booleanos a
false
, objetos anull
). - Llama al constructor (que puede reiniciar los campos, o no).
- Devuelve un puntero al nuevo objeto.
Por lo tanto, sus campos ''a'' y ''b'' se inician en null
y ''a'' se reinicia en el constructor. Este proceso no es relevante para las llamadas a métodos, por lo que la variable local ''c'' nunca se inicializa.
HTH
PD: para el insomne grave, lee this .
Considera esto:
public class TestClass {
private String a;
private String b;
public TestClass()
{
a = "initialized";
}
public void doSomething()
{
String c;
a.notify(); // This is fine
b.notify(); // This is fine - but will end in an exception
c.notify(); // "Local variable c may not have been initialised"
}
}
No lo entiendo "b" nunca se inicializa, pero dará el mismo error de tiempo de ejecución que "c", que es un error en tiempo de compilación. ¿Por qué la diferencia entre las variables locales y los miembros?
Editar : hacer que los miembros sean privados fue mi intención inicial, y la pregunta sigue en pie ...
De hecho, ha identificado uno de los agujeros más grandes en el sistema de Java que generalmente intenta encontrar errores en edición / compilación en lugar de tiempo de ejecución porque, como decía la respuesta aceptada, es difícil saber si b está inicializado o no.
Hay algunos patrones para solucionar este problema. Primero es "Final por defecto". Si tus miembros fueran finales, tendrías que completarlos con el constructor y usaría el análisis de ruta para asegurarte de que todos los caminos posibles llenan las finales (aún podrías asignarle un valor "nulo", lo que vencería el propósito pero al menos te verías obligado a reconocer que lo estabas haciendo intencionalmente).
Un segundo enfoque es la estricta verificación nula. Puede activarlo en configuraciones de eclipse ya sea por proyecto o en propiedades predeterminadas. Creo que te obligaría a anular tu b.notify () antes de llamarlo. Esto puede salirse de control rápidamente, por lo que tiende a ir con un conjunto de anotaciones para simplificar las cosas:
Las anotaciones pueden tener diferentes nombres, pero en concepto una vez que active la verificación nula estricta y las anotaciones, los tipos de variables son "nulables" y "NotNull". Si intenta colocar un Nullable en una variable no nula, primero debe verificarlo para nulo. Los parámetros y los tipos de devolución también se anotan, por lo que no es necesario comprobar el nulo cada vez que se asigna a una variable no nula.
También hay una anotación de nivel de paquete "NotNullByDefault" que hará que el editor asuma que ninguna variable puede tener un valor nulo a menos que lo etiquete Nullable.
Estas anotaciones se aplican principalmente a nivel de editor: puede activarlas en eclipse y probablemente en otros editores, por lo que no están necesariamente estandarizadas. (Al menos la última vez que revisé, Java 8 podría tener algunas anotaciones que aún no he encontrado)
El compilador puede darse cuenta de que nunca se establecerá c. La variable b podría ser establecida por otra persona después de que se llame al constructor, pero antes de hacer algo (). Haga b privado y el compilador puede ayudar.
El compilador puede decir desde el código de doSomething () que c se declara allí y nunca se inicializa. Debido a que es local, no hay posibilidad de que se inicialice en otro lugar.
No puede decir cuándo o dónde llamará a DoSomething (). b es un miembro público. Es muy posible que lo inicie en otro código antes de llamar al método.
El lenguaje lo define de esta manera.
Las variables de instancia del tipo de objeto se inicializan por defecto a nulo. Las variables locales del tipo de objeto no se inicializan de manera predeterminada y es un error de tiempo de compilación acceder a una variable indefinida.
Consulte la sección 4.5.5 aquí http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.12.5
Las reglas para una asignación definida son bastante difíciles (lea el capítulo 16 de JLS 3rd Ed). No es práctico imponer asignaciones definidas en los campos. Tal como está, incluso es posible observar los campos finales antes de que se inicialicen.
Las variables de miembro se inicializan a nulo o a sus valores primitivos predeterminados, si son primitivos.
Las variables locales están INDEFINIDAS y no se inicializan, y usted es responsable de establecer el valor inicial. El compilador le impide usarlos.
Por lo tanto, b se inicializa cuando se crea una instancia de la clase TestClass mientras que c no está definido.
Nota: null es diferente de indefinido.