2009-02-08 16 views
50

Tengo una pregunta acerca de los constructores predeterminados y la herencia en Java.Constructores y herencia predeterminados en Java

Generalmente, si escribe una clase y no incluye ningún constructor, Java proporciona automáticamente un constructor predeterminado (uno sin parámetros) que inicializa todas las variables de instancia de la clase (si hay alguna) con algunos valores predeterminados (0, nulo o falso). Sin embargo, si escribe un constructor con algunos parámetros y no escribe ningún constructor predeterminado, entonces Java no proporciona un constructor predeterminado. Mi pregunta es: ¿cuál es el caso de las clases, que heredan de otras clases? Si escribo un constructor con algunos parámetros en ellas, pero no incluyo un constructor predeterminado, ¿heredan el constructor predeterminado de la superclase?

+1

hace la necesidad de post una edición de la línea que asume que "Constructor inicializa todas las variables de instancia de la clase (si hay alguna) con algunos valores predeterminados (0, nulo o falso)". engañando al lector? –

Respuesta

51

Los constructores no se heredan.

Además, la inicialización de los campos la realiza la máquina virtual, no el constructor predeterminado. El constructor predeterminado solo invoca el constructor predeterminado de la superclase, y el constructor predeterminado de Object está vacío. El buen punto de este diseño es que no hay forma de acceder a campos no inicializados.

+1

Sí, acabo de entender esto, Potyl a continuación ha señalado esto. ¿Pero cómo (y cuándo) son los campos inicializados entonces? (por favor, vea mi comentario sobre la respuesta del potyl). – user42155

+0

¿Es el caso que cuando creo el objeto, Java da automáticamente los valores predeterminados? Pero, de nuevo, creamos objetos con constructores, ¿verdad? – user42155

+0

Sí, tomó un tiempo para hacer la investigación w.r.t. inicialización – starblue

10

A menos que use super (...) un constructor llama al constructor vacío de su elemento primario. Nota: Lo hace en todas sus clases, incluso las que extienden Object.

Esto no hereda, las subclases no obtienen los mismos constructores con los mismos argumentos. Sin embargo, puede agregar constructores que llamen a uno de los constructores de la superclase.

+0

Con "constructor vacío" te refieres al constructor predeterminado, ¿verdad? – user42155

+0

¿Y qué ocurre si el padre no tiene un constructor predeterminado? – user42155

+0

Aquí me refiero a un constructor sin argumentos. Normalmente, el constructor predeterminado es uno que no está definido en absoluto. Puedes definir un constructor sin argumentos. –

3

Si proporciona un constructor, Java no generará un constructor vacío predeterminado. Entonces su clase derivada solo podrá llamar a su constructor.

El constructor predeterminado no inicializa sus variables privadas a los valores predeterminados. La prueba es que es posible escribir una clase que no tiene un constructor predeterminado y tiene sus miembros privados inicializados a los valores predeterminados. He aquí un ejemplo:

public class Test { 

    public String s; 
    public int i; 

    public Test(String s, int i) { 
     this.s = s; 
     this.i = i; 
    } 

    public Test(boolean b) { 
     // Empty on purpose! 
    } 

    public String toString() { 
     return "Test (s = " + this.s + ", i = " + this.i + ")"; 
    } 

    public static void main (String [] args) { 
     Test test_empty = new Test(true); 
     Test test_full = new Test("string", 42); 
     System.out.println("Test empty:" + test_empty); 
     System.out.println("Test full:" + test_full); 
    } 
} 
+0

¡Eso es interesante! He vivido bastante tiempo con la suposición de que si no inicializas las variables de instancia en un constructor, entonces Java hace esto en el constructor predeterminado. Entonces, en este caso, ¿cómo se inicializan las variables? – user42155

+0

Aquí he encontrado un buen artículo sobre la inicialización en Java, respondiendo a mi pregunta: http://www.javaworld.com/javaworld/jw-03-1998/jw-03-initialization.html?page=1 – user42155

+0

Creando un objeto instancia requiere que el operador "nuevo" asigna memoria e invoca un constructor (utilizado para la lógica inicial). Nuestros constructores se ocupan solo de este último. Supongo que la primera parte se encarga de la inicialización predeterminada de los miembros de los datos mientras se asigna la memoria. – potyl

59
  1. Si usted no hace un constructor, the default empty constructor is automatically created.

  2. Si cualquier constructor no llama explícitamente un super o este constructor como su primera instrucción, a call to super() is automatically added.

Always.

+2

Los enlaces están rotos (gracias, Oracle), aquí están los nuevos: http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.8.9 y http : //docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.8.7 – Stoffe

+1

@Stoffe: He sugerido una edición para corregir los enlaces gracias a sus comentarios. Puede ganar reputación sugiriendo ediciones, entonces ¿por qué no hacer eso en el futuro? – Flimm

+0

Añadiría que, en el caso 2, la llamada a super no tiene parámetros. – LuxDie

1

Cuando no creamos un constructor, Java crea un constructor predeterminado automáticamente. Pero cuando creamos uno o más constructores personalizados con argumentos, Java no crea ningún constructor predeterminado. Si creamos uno o más constructores y queremos crear un objeto sin ningún argumento de constructor, tenemos que declarar un constructor vacío.

+0

"... crear un objeto sin ningún constructor Tenemos que declarar ..." => "... crear un objeto sin ningún constructor ** argumentos **, tenemos que declarar ..." –

2

Regla de pulgar es que la Subclase debe llamar a cualquier constructor de la clase base. así que si no tiene la configuración predeterminada, llame al existente de la subclase.de otra forma poner en práctica la const vacío en la clase base para evitar el problema de compilación

6

La regla básica es una llamada (o invocación) a un constructor debe ser la primera instrucción que JVM tiene que ejecutar,

Así que cuando se tener una superclase con solo constructor parametrizado y sin constructor predeterminado, y la clase base no tiene una llamada explícita al constructor parametrizado de la superclase, JVM proporciona el super(); llamada que arroja error ya que no hay un constructor predeterminado para la superclase, por lo tanto, proporcionamos un constructor predeterminado en la superclase o llamamos explícitamente al constructor parametrizado de la superclase en el constructor de la clase base. cuando damos la llamada explícita, entonces JVM no se molesta en poner la línea super(); como la invocación del constructor debería ser la primera declaración del método, lo que no puede suceder (debido a nuestra llamada explícita).

+0

supongo que debería sea ​​una buena práctica poner siempre el constructor por defecto allí, si quiere constructores "sobrecargados". – lwpro2

5

Sección 8.8.9 de la especificación del lenguaje Java explica en detalle lo que está pasando:

Si una clase no contiene declaraciones constructor, a continuación, un constructor por defecto se declara implícitamente . La forma de la constructor predeterminado para una clase de nivel superior, clase de miembro, o clase local es el siguiente:

  • El constructor por defecto tiene el mismo accesibilidad como la clase (§6.6).
  • El constructor por defecto no tiene parámetros formales, excepto en un clase miembro interior no privada, donde el constructor predeterminado declara implícitamente una parámetro formal que representa la instancia inmediatamente circundante de la clase (§8.8.1, §15.9. 2, §15.9.3).
  • El constructor predeterminado no tiene cláusulas throws.
  • Si la clase que se declara es el objeto de la clase primordial, el constructor predeterminado tiene un cuerpo vacío. De lo contrario, el constructor predeterminado simplemente invoca el constructor de la superclase sin argumentos.

Se puede ver que no hay herencia pasando aquí: todo lo que hay es la "magia compilador" con el constructor por defecto declarado implícitamente. La especificación también deja en claro que el constructor predeterminado se agrega solo cuando la clase no tiene constructores en absoluto, lo que significa que la respuesta a su pregunta es "no": una vez que le da a la clase un constructor, el acceso al constructor predeterminado de su superclase se pierde.

+0

vínculo de referencia: https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.8.9 – cellepo

2

La respuesta a su pregunta es muy simple. Implícitamente (Invisible), la primera declaración en cualquier constructor es 'super();' es decir, la llamada al constructor sin parámetros de la superclase, hasta que la cambie explícitamente a algo como 'this();', 'this (int)', 'this (String)', 'super (int)', 'super (String)) 'etc. ' this(); ' es el constructor de la clase actual.

0

Habrá error de compilación tiempo ... porque compilador busca por defecto Constructor que superclase y si su no existe ... es un error ... y programa no compila ...