Menú
Está libre
registro
hogar  /  Educación/ Constructores de Java. Constructores

Constructores de Java. Constructores

Un constructor es una estructura similar a un método cuyo propósito es crear una instancia de una clase. Características del constructor:
  • El nombre del constructor debe coincidir con el nombre de la clase (por convención, la primera letra está en mayúscula, generalmente un sustantivo);
  • Cualquier clase tiene un constructor. Incluso si no lo ha escrito, el compilador de Java creará por sí mismo un constructor predeterminado que está vacío y no hace nada más que llamar al constructor de superclase.
  • Un constructor es similar a un método, pero no es un método, ni siquiera se considera un miembro de la clase. Por lo tanto, no se puede heredar ni anular en una subclase;
  • Los constructores no se heredan;
  • Puede haber varios constructores en una clase. En este caso, se dice que los constructores están sobrecargados;
  • Si no se describe ningún constructor en la clase, el compilador agrega automáticamente un constructor sin parámetros al código;
  • Un constructor no tiene un tipo de retorno, ni siquiera puede ser un tipo void, si se devuelve el tipo void, entonces ya no es un constructor sino un método, a pesar de la coincidencia con el nombre de la clase.
  • Se permite una declaración de retorno en el constructor, pero solo vacía, sin ningún valor de retorno;
  • Los modificadores de acceso se pueden usar en el constructor; puede establecer uno de los modificadores: público, protegido, privado o sin un modificador.
  • Un constructor no puede tener modificadores abstractos, finales, nativos, estáticos o sincronizados;
  • La palabra clave this se refiere a otro constructor de la misma clase. Si se usa, una llamada debe ser la primera línea del constructor;
  • La palabra clave super llama al constructor de la clase padre. Si se usa, se debe acceder a él en la primera línea del constructor;
  • Si el constructor no llama al constructor de la superclase de la clase principal (con o sin argumentos), el compilador agrega automáticamente el código para llamar al constructor de la clase principal sin argumentos;

Constructor predeterminado

Cualquier clase tiene un constructor. Incluso si no lo ha escrito, el compilador de Java creará un constructor predeterminado por sí mismo. Este constructor está vacío y no hace más que llamar al constructor de la superclase. Aquellos. si escribe: ejemplo de clase pública (), entonces esto es equivalente a escribir: ejemplo de clase pública (Ejemplo () (super;)) En este caso, la clase ancestro no se especifica explícitamente, y por defecto todas las clases de Java heredan el Objeto class, por lo que se llama al constructor de la clase Object. Si un constructor con parámetros está definido en la clase, pero no hay un constructor sobrecargado sin parámetros, entonces llamar al constructor sin parámetros es un error. Sin embargo, en Java desde la versión 1.5, puede utilizar constructores con argumentos de longitud variable. Y si hay un constructor que tiene un argumento de longitud variable, llamar al constructor predeterminado no será un error. No lo hará porque el argumento de longitud variable puede estar vacío. Por ejemplo, el siguiente ejemplo no se compilará, pero si descomenta el constructor con un argumento de longitud variable, la compilación y el lanzamiento serán exitosos y como resultado de la línea de código DefaultDemo dd = new DefaultDemo (); se llamará al constructor DefaultDemo (int ... v). Naturalmente, en este caso es necesario utilizar JSDK 1.5. Archivo DefaultDemo.java class DefaultDemo (DefaultDemo (String s) (System.out.print ("DefaultDemo (String)");) / * DefaultDemo (int ... v) (System.out.println ("DefaultDemo (int ...)");) * / public static void main (String args) (DefaultDemo dd = new DefaultDemo ();)) Salida del programa con el constructor sin comentar: DefaultDemo (int ...) Sin embargo, en el caso común cuando no hay ningún constructor definido en la clase en all, se requerirá la llamada al constructor predeterminado (sin parámetros) porque la sustitución del constructor predeterminado ocurre automáticamente.

Al crear un objeto, las siguientes acciones se realizan de forma secuencial:
  • La clase de objeto se busca entre las clases ya utilizadas en el programa. Si no existe, se busca en todos los directorios y bibliotecas disponibles para el programa. Una vez que se encuentra una clase en un directorio o biblioteca, los campos estáticos de la clase se crean e inicializan. Aquellos. para cada clase, los campos estáticos se inicializan solo una vez.
  • Se asigna memoria para el objeto.
  • Se inicializan los campos de clase.
  • Ejecuta el constructor de la clase.
  • Se forma un enlace al objeto creado e inicializado. Esta referencia es el valor de la expresión que crea el objeto. El objeto también se puede crear llamando al método newInstance () de la clase java.lang.Class. En este caso, se utiliza un constructor sin una lista de parámetros.

Sobrecarga de constructores

Los constructores de la misma clase pueden tener mismo nombre y una firma diferente. Esta propiedad se llama sobrecarga. Si una clase tiene varios constructores, entonces hay una sobrecarga de constructores.

Constructores parametrizados

La firma de un constructor es el número y los tipos de parámetros, así como la secuencia de sus tipos en la lista de parámetros del constructor. Se ignora el tipo de retorno. El constructor no devuelve ningún parámetro. Esta declaración explica, en cierto sentido, cómo Java distingue entre constructores o métodos sobrecargados. Java distingue entre métodos sobrecargados no por tipo de retorno, sino por número, tipos y secuencia de tipos de parámetros de entrada. Un constructor ni siquiera puede devolver un tipo vacío, de lo contrario se convertirá en un método ordinario, aunque se parezca al nombre de la clase. El siguiente ejemplo demuestra esto. El archivo VoidDemo.java class VoidDemo ( / ** * Este es un constructor * / VoidDemo () (System. Out. Println ("Constructor");) void VoidDemo () (System. Out. Println ("Método");) public static void main (String s) (VoidDemo m = new VoidDemo (); )) Como resultado, el programa mostrará: Constructor Esto demuestra una vez más que el constructor es un método sin parámetros de retorno. Sin embargo, el constructor se puede establecer en uno de los tres modificadores públicos, privados o protegidos. Y el ejemplo ahora se verá así: Archivo VoidDemo2.java class VoidDemo2 ( / ** * Este es un constructor * / public VoidDemo2 () (System.out.println ("Constructor");) / ** * Y este ya es un método ordinario, aunque se parece * al nombre de la clase, ya que hay un tipo de retorno vacío * / private void VoidDemo2 () (System. out. println ("Método");) public static void main (String s) (VoidDemo2 m = new VoidDemo2 ();)) Se permite escribir una declaración de retorno en el constructor, pero solo vacío, sin ningún valor de retorno. Archivo ReturnDemo.java clase ReturnDemo ( / ** * Se permite usar el operador * return sin parámetros en el constructor. * / public ReturnDemo () (System. out. println ("Constructor"); return;) public static void main (String s) (ReturnDemo r = new ReturnDemo ();))

Constructores parametrizados con argumentos de longitud variable

Java SDK 1.5 presenta una herramienta esperada desde hace mucho tiempo: argumentos de longitud variable para constructores y métodos. Antes de esto, se procesaba un número variable de documentos de dos formas inconvenientes. El primero de ellos se calculó sobre el hecho de que el número máximo de argumentos se limita a un número pequeño y se conoce de antemano. En este caso, fue posible crear versiones sobrecargadas del método, una para cada variante de la lista de argumentos pasados ​​al método. El segundo método está diseñado para lo desconocido de antemano y una gran cantidad de argumentos. En este caso, los argumentos se colocaron en una matriz y esta matriz se pasó al método. Los argumentos de longitud variable se utilizan con mayor frecuencia en manipulaciones posteriores con inicializaciones de variables. La ausencia de algunos de los argumentos esperados para un constructor o método se reemplaza convenientemente con valores predeterminados. El argumento de longitud variable es una matriz y se trata como una matriz. Por ejemplo, un constructor para una clase Checking con un número variable de argumentos se vería así: class Checking (public Checking (int ... N) ()) Combinación simbólica ... le dice al compilador que un número variable de argumentos ser utilizado y que estos argumentos se almacenarán en la matriz, el valor de la referencia a la que está contenido en la variable n. Se puede llamar a un constructor con un número diferente de argumentos, sin incluir ninguno. Los argumentos se colocan automáticamente en una matriz y se pasan a través de n. Si no hay argumentos, la longitud de la matriz es 0. Además de los argumentos de longitud variable, se pueden incluir parámetros obligatorios en la lista de parámetros. En este caso, el parámetro que contiene un número variable de argumentos debe ser necesariamente el último en la lista de parámetros. Por ejemplo: Class Checking (Public Checking (String s, int ... N) ()) La limitación obvia se refiere al número de parámetros de longitud variable. Debe haber solo un parámetro de longitud variable en la lista de parámetros. Con dos parámetros de longitud variable, el compilador no puede decir dónde termina un parámetro y comienza el otro. Por ejemplo: class Checking (public Checking (String s, int ... N, double ... D) // ERROR! ()) File Checking.java visitó cada uno de los autos durante el día. Es necesario de la masa total de autos registrados seleccionar aquellos que han estado en dos casillas dadas durante el día, digamos 22 y 15, según el mapa de la zona. Es bastante natural que un coche pueda visitar muchas plazas durante el día, o solo una. Evidentemente, el número de plazas visitadas está limitado por la velocidad física del vehículo. Compongamos un pequeño programa donde el constructor de la clase aceptará como argumentos el número de carro como parámetro requerido y los números de los cuadrados de terreno visitados, cuyo número puede ser variable. El constructor verificará si el automóvil ha aparecido en dos cuadrados, si es así, luego mostrará su número en la pantalla.

Pasando parámetros al constructor

Básicamente, existen dos tipos de parámetros en los lenguajes de programación:
  • tipos básicos (primitivos);
  • referencias a objetos.
El término llamada por valor significa que el constructor recibe el valor que le pasa el módulo de llamada. Por el contrario, llamar por referencia significa que el constructor recibe de módulo de llamada dirección variable. En el lenguaje Java, solo se usa la llamada por valor. Por valor de parámetro y por valor de referencia de parámetro. Java no utiliza la invocación por referencia para objetos (aunque muchos programadores y autores de algunos libros lo afirman). Los parámetros al pasar objetos en Java se llevan a cabo. no por referencia, a por valor de referencia del objeto! En cualquier caso, el constructor recibe copias de los valores de todos los parámetros. El constructor no puede hacer con sus parámetros de entrada:
  • el constructor no puede cambiar los valores de los parámetros de entrada de los tipos básicos (primitivos);
  • el constructor no puede cambiar las referencias de los parámetros de entrada;
  • el constructor no puede reasignar referencias de parámetros de entrada a nuevos objetos.
El constructor puede hacer con sus parámetros de entrada:
  • cambiar el estado del objeto pasado como parámetro de entrada.
El siguiente ejemplo demuestra que en Java, los parámetros de entrada para un constructor se pasan por el valor de una referencia de objeto. Este ejemplo también refleja el hecho de que el constructor no puede cambiar las referencias de los parámetros de entrada, pero en realidad cambia las referencias de las copias de los parámetros de entrada. Empoyee.java clase de archivo Employee (Employee (String x, String y) (String temp = x; x = y; y = temp;) public static void main (String args) (String name1 = new String ("Alice"); Cadena nombre2 = nueva Cadena ("María"); Empleado a = nuevo Empleado (nombre1, nombre2); System.out.println ("nombre1 =" + nombre1); System.out.println ("nombre2 =" + nombre2); )) El resultado del programa es: name1 = Alice name2 = Mary Si en Java para pasar objetos como parámetros, se usaran llamadas por referencia, entonces el constructor intercambiaría name1 y name2 en este ejemplo. El constructor en realidad no intercambiará las referencias de objeto almacenadas en las variables name1 y name2. Esto sugiere que los parámetros del constructor se inicializan con copias de estas referencias. Luego, el constructor intercambia las copias ya existentes. Cuando se completa el constructor, las variables xey se destruyen, y las variables originales name1 y name2 continúan haciendo referencia a los objetos antiguos.

Cambiar los parámetros pasados ​​al constructor.

El constructor no puede modificar los parámetros pasados ​​de los tipos básicos. Sin embargo, el constructor puede modificar el estado del objeto pasado como parámetro. Por ejemplo, considere el siguiente programa: Archivo Salary1.java class Salary1 (Salary1 (int x) (x = x * 3; System.out.println ("x =" + x);) public static void main (String args) (valor int = 1000; Salario1 s1 = nuevo Salario1 (valor); System.out.println ("valor =" (! LANG: + valor);)) El resultado del programa es: x = 3000 valor = 1000 Obviamente, este método no cambiará el parámetro del tipo principal. Por lo tanto, después de llamar al constructor, el valor del valor de la variable permanece igual a 1000. Básicamente, están sucediendo tres cosas:
  1. La variable x se inicializa con una copia del valor del parámetro de valor (es decir, el número 1000).
  2. El valor de la variable x se triplica; ahora es igual a 3000. Sin embargo, el valor de la variable sigue siendo 1000.
  3. El constructor sale y la variable x ya no se usa.
El siguiente ejemplo triplica el salario de un empleado correctamente porque el valor de referencia del objeto se pasa como parámetro al método. Archivo Salary2.java class Salary2 (int value = 1000; Salary2 () () Salary2 (Salary2 x) (x. Value = x. Value * 3;) public static void main (String args) (Salary2 s1 = new Salary2 () ; Salario2 s2 = nuevo Salario2 (s1); System.out.println ("s1.value="+ s1. valor); Sistema. fuera. println"s2.value="+ s2. valor); )) El resultado del programa es: s1. valor = 3000 s2. valor = 1000 El valor de la referencia del objeto se utiliza como parámetro. Al ejecutar la línea Salario2 s2 = nuevo Salario2 (s1); al constructor Salary2 (Salary x) se le pasará el valor de referencia del objeto de la variable s1, y el constructor realmente triplicará el salario de s1.value, ya que incluso la copia (Salary x) creada dentro del constructor apunta al objeto variable s1 .

Constructores primitivos parametrizados.

En el caso de que se utilice una primitiva en los parámetros del constructor sobrecargado, que se puede restringir (por ejemplo, int<- double), то вызов метода со суженным значением возможен, несмотря на то, что метода, перегруженного с таким параметром нет. Например: Файл Primitive.java class Primitive { Primitive (double d) { d = d + 10 ; System. out. println (!}"d=" + d) ; } public static void main (String args ) { int i = 20 ; Primitive s1 = new Primitive (i) ; } } El resultado del programa es: d = 30.0 A pesar de que la clase Primitive no tiene un constructor que tenga un parámetro de tipo int, el constructor con un parámetro de entrada double funcionará. Antes de llamar al constructor, la variable i se expandirá del tipo int al tipo double. La variante opuesta, cuando la variable i sería de tipo double, y el constructor solo tomaría el parámetro int, en esta situación conduciría a un error de compilación.

Llamada de constructor y nuevo operador

El nuevo operador siempre llama al constructor. Cuando se llama a un constructor con el operador new, el constructor siempre genera una referencia a un nuevo objeto. Es imposible forzar al constructor a formar una referencia a un objeto existente en lugar de una referencia a un nuevo objeto, excepto por la sustitución del objeto deserializado. Y con el nuevo operador, en lugar de un vínculo a un nuevo objeto, es imposible formar un vínculo a un objeto existente. Por ejemplo: Archivo Salario3.java clase Salario3 (valor int = 1000; Salario3 () () Salario3 (Salario3 x) (x. Valor = x. Valor * 3;) public static void main (String args) (Salario3 s1 = nuevo Salario3 (); System.out.println ("Creación del primer objeto:" + s1. Valor); Salario3 s2 = nuevo Salario3 (s1); System.out.println ("Creación del segundo objeto:" + s2. Valor); Sistema .out.println (+ s1. valor); Salario3 s3 = nuevo Salario3 (s1); System.out.println ("Creación del tercer objeto:" + s3. valor); System. out.println ( "¿Qué pasó con el primer objeto?:"+ s1. valor); )) El resultado del programa es: Creación del primer objeto: 1000 Creación del segundo objeto: 1000 ¿Qué pasó con el primer objeto ?: 3000 Creación del tercer objeto: 1000 ¿Qué pasó con el primer objeto? : 9000 Primero con la línea Salario3 s1 = nuevo Salario3 (); se crea un nuevo objeto. Además, si usa la línea Salario3 s2 = nuevo Salario3 (s1); o las líneas Salario3 s3 = nuevo Salario3 (s1); sería posible crear una referencia a un objeto existente, entonces s1.value s2.value y s3.value almacenarían el mismo valor 1000. En realidad, en la línea Salario3 s2 = nuevo Salario3 (s1); se creará un nuevo objeto para la variable s2 y el estado del objeto para la variable s1 se cambiará pasando su valor a la referencia del objeto en el parámetro constructor. Esto se puede ver en los resultados de la retirada. Y al ejecutar la línea Salario3 s3 = nuevo Salario3 (s1); cree un objeto NUEVO para s3 y cambie el estado del objeto para s1 nuevamente.

Constructores y bloques de inicialización, secuencia de acciones al llamar a un constructor

La sección Creación y constructores de objetos enumera los pasos generales que se toman cuando se crea un objeto. Entre ellos, los procesos de inicialización de campos de clase y elaboración del constructor de clases están acoplados, que a su vez también tienen un orden interno:
  1. Todos los campos de datos se inicializan a sus valores predeterminados (0, falso o nulo).
  2. Todos los inicializadores de campo y los bloques de inicialización se ejecutan en el orden en que se enumeran en la declaración de clase.
  3. Si se llama a otro constructor en la primera línea de un constructor, se ejecuta el constructor llamado.
  4. Se ejecuta el cuerpo del constructor.
El constructor tiene que ver con la inicialización, porque en Java hay tres formas de inicializar un campo en una clase:
  • asignar un valor en la declaración;
  • asignar valores en el bloque de inicialización;
  • establece su valor en el constructor.
Naturalmente, debe organizar su código de inicialización de manera que sea fácil de entender. La siguiente clase se da como ejemplo: class Initialization (int i; short z = 10; static int x; static float y; static (x = 2000; y = 3.141;) Initialization () (System. Out. Println (" i = "+ i); System. out. println (" z = "+ z); z = 20; System. out. println (" z = "+ z);)) En el ejemplo anterior, las variables se inicializan en en el siguiente orden: primero las variables estáticas xey se inicializan a sus valores predeterminados. A continuación, se ejecuta un bloque de inicialización estático. Luego, la variable i se inicializa a su valor predeterminado y la variable z se inicializa. Luego viene el constructor. Los constructores de clases de llamada deben ser independientes del orden en el que se declaran los campos. Esto puede provocar errores.

Constructores y herencia

Los constructores no se heredan. Por ejemplo: clase pública Example (Example () () public void sayHi () (system. Out. Println ("Hola");)) public class SubClass amplía Example () La clase SubClass hereda automáticamente el método sayHi () definido en la clase padre. Al mismo tiempo, el constructor Example () de la clase padre no es heredado por su subclase descendiente.

La palabra clave this en constructores

Los constructores usan esto para referirse a otro constructor en la misma clase, pero con una lista de parámetros diferente. Si el constructor usa la palabra clave this, entonces debe estar en la primera línea, ignorar esta regla resultará en un error del compilador. Por ejemplo: Archivo ThisDemo.java public class ThisDemo (String name; ThisDemo (String s) (name = s; System.out.println (name);) ThisDemo () (this ("John");) public static void main (String args) (ThisDemo td1 = new ThisDemo ("María"); ThisDemo td2 = new ThisDemo ();)) El resultado del programa es: Mary John Este ejemplo tiene dos constructores. El primero recibe una cadena de argumentos. El segundo no toma argumentos, solo llama al primer constructor usando el nombre predeterminado "John". Por lo tanto, puede utilizar constructores para inicializar valores de campo de forma explícita y predeterminada, lo que a menudo es necesario en los programas.

Super palabra clave en constructores

Los constructores usan super para llamar al constructor de la superclase. Si el constructor usa super, entonces esta llamada debe estar en la primera línea; de lo contrario, el compilador arrojará un error. A continuación se muestra un ejemplo: Archivo SuperClassDemo.java public class SuperClassDemo (SuperClassDemo () ()) class Child extiende SuperClassDemo (Child () (super ();)) En este ejemplo simple, el constructor Child () contiene una llamada a super ( ) que crea una instancia de la clase SuperClassDemo, además de la clase Child. Dado que super debe ser la primera instrucción ejecutada en el constructor de la subclase, este orden es siempre el mismo, independientemente de si se usa super (). Si no se usa, entonces el constructor predeterminado (sin parámetros) de cada superclase se ejecutará primero, comenzando con la clase base. El siguiente programa demuestra cuándo se ejecutan los constructores. Archivo call.java // Crea la superclase A clase A (A () (System. out.println ("Inside A constructor.");)) // Crear subclase B ampliando la clase A la clase B se extiende A (B () (System.out.println ("Dentro del constructor B");)) // Crea una clase (C) que amplíe la clase B class C se extiende B (C () (System. out.println ("Inside C constructor.");)) class Call (public static void main (String args) (C c = new C ();)) El resultado de este programa es: Dentro de un constructor. Dentro del constructor B. Dentro del constructor de C. Los constructores se llaman en orden de jerarquía de clases. Esto tiene sentido. Dado que la superclase no tiene conocimiento de ninguna subclase, cualquier inicialización que necesite realizar está separada. Si es posible, debe preceder a cualquier inicialización realizada por la subclase. Es por eso que debe realizarse primero.

Constructores personalizables

El mecanismo de identificación de tipos en tiempo de ejecución es uno de los poderosos fundamentos del lenguaje Java que implementa el polimorfismo. Sin embargo, dicho mecanismo no asegura al desarrollador contra la conversión de tipos incompatibles en algunos casos. El caso más común es la manipulación de un grupo de objetos, cuyos diversos tipos no se conocen de antemano y se determinan en tiempo de ejecución. Dado que los errores asociados con la incompatibilidad de tipos solo pueden aparecer en la etapa de tiempo de ejecución, esto dificulta encontrarlos y eliminarlos. La introducción de tipos personalizados en Java 2 5.0 mueve algunos de estos errores del tiempo de ejecución al tiempo de compilación y proporciona seguridad de tipos faltantes. No es necesario un encasillado explícito al pasar del tipo de objeto a un tipo concreto. Tenga en cuenta que los personalizadores de tipos solo funcionan con objetos y no se aplican a tipos de datos primitivos que se encuentran fuera del árbol de herencia de clases. Gracias a los tipos personalizables, todos los lanzamientos son automáticos y están ocultos. Esto le permite estar seguro contra las discrepancias de tipos y reutilizar el código con mucha más frecuencia. Los tipos personalizados se pueden utilizar en constructores. Los constructores se pueden personalizar incluso si su clase no es un tipo personalizado. Por ejemplo: class GenConstructor (private double val;< T extends Number >GenConstructor (T arg) (val = arg. DoubleValue ();) void printValue () (System. Out.println ("val:" + val);)) class GenConstructorDemo (public static void main (String args) (GenConstructor gc1 = new GenConstructor (100); GenConstructor gc2 = new GenConstructor (123.5F); gc1. printValue (); gc2. printValue ();)) Dado que el constructor GenConstructor especifica un parámetro de tipo personalizado que debe derivarse de la clase Number, se puede llamar a cualquiera

¡Oye! Hoy analizaremos un tema muy importante que concierne a nuestras instalaciones. ¡Se puede decir sin exagerar que usará este conocimiento todos los días en el trabajo real! Hablaremos de constructores.

Es posible que hayas escuchado este término por primera vez, pero de hecho debes haber usado constructores, solo tú mismo no lo notaste :) Lo veremos más adelante.

¿Qué son los constructores y por qué se necesitan?

Veamos dos ejemplos. public class Car (modelo String; int maxSpeed; public static void main (String args) (Car bugatti = new Car (); bugatti. model = "Bugatti Veyron"; bugatti. maxSpeed ​​= 407;)) Creamos nuestro auto y establezca para él el modelo y la velocidad máxima. Sin embargo, en un proyecto real, el objeto Car obviamente no tendrá 2 campos. ¡Y, por ejemplo, 16 campos! coche de clase pública (modelo de cadena; // modelo int maxSpeed; // velocidad máxima// volumen del motor// apellido del propietario// número de asientos en la cabina String salonMaterial; // material interior seguro booleano; // esta asegurado// país del fabricante int trunkVolume; // volumen del maletero int accelerationTo100km; public static void main (String args) (Car bugatti = new Car (); bugatti. color = "blue"; bugatti. accelerationTo100km = 3; bugatti. engineVolume = 6.3; bugatti. ManufacturerCountry = "Italia"; bugatti. ownerFirstName = " Amigo "; bugatti. YearOfIssue = 2016; bugatti. Seguro = verdadero; bugatti. Precio = 2000000; bugatti. IsNew = falso; bugatti. PlacesInTheSalon = 2; bugatti. MaxSpeed ​​= 407; bugatti. Modelo =" Bugatti Veyron "; )) Hemos creado un nuevo objeto Car. Un problema: tenemos 16 campos, pero inicializamos solo 12! ¡Ahora intenta encontrar los que olvidamos por el código! No es tan fácil, ¿verdad? En tal situación, el programador puede fácilmente cometer un error y omitir la inicialización de algún campo. Como resultado, el comportamiento del programa se volverá erróneo: public class Car (String model; // model int maxSpeed; // velocidad máxima ruedas int; // ancho de disco double engineVolume; // volumen del motor Color de la cuerda; // color int yearOfIssue; // año de emisión String ownerFirstName; // nombre del propietario String ownerLastName; // apellido del propietario precio largo; // precio booleano isNew; // nuevo o no int placesInTheSalon; // número de asientos en la cabina String salonMaterial; // material interior seguro booleano; // esta asegurado String ManufacturerCountry; // país del fabricante int trunkVolume; // volumen del maletero int accelerationTo100km; // aceleración a 100 km / h en segundos public static void main (String args) (Car bugatti = new Car (); bugatti. color = "blue"; bugatti. accelerationTo100km = 3; bugatti. engineVolume = 6.3; bugatti. ManufacturerCountry = "Italia"; bugatti. ownerFirstName = " Amigo "; bugatti. YearOfIssue = 2016; bugatti. Seguro = verdadero; bugatti. Precio = 2000000; bugatti. IsNew = falso; bugatti. PlacesInTheSalon = 2; bugatti. MaxSpeed ​​= 407; bugatti. Modelo =" Bugatti Veyron "; System. Out.println ( "Modelo Bugatti Veyron. Desplazamiento -"+ bugatti. engineVolume + ", maletero -" + bugatti. troncoVolumen + ", el salón está hecho de"+ bugatti. salonMaterial + ", el ancho de los discos es"+ bugatti. ruedas + ". Fue adquirida en 2018 por el Sr.+ bugatti. ownerLastName); )) Salida de consola: Modelo Bugatti Veyron. Capacidad del motor - 6.3, maletero - 0, interior está hecho de null, ancho de disco - 0. Fue comprado en 2018 por Mr. null A su cliente que regaló $ 2 millones por un automóvil claramente no le gustará que lo nombren " señor nulo”! Pero en serio, como resultado, apareció un objeto creado incorrectamente en nuestro programa: un automóvil con un ancho de disco de 0 (es decir, sin ningún disco), un maletero faltante, un interior hecho de un material desconocido e incluso perteneciente a alguien desconocido. ¡Uno solo puede imaginar cómo un error de este tipo puede "dispararse" cuando el programa se está ejecutando! Necesitamos evitar de alguna manera tales situaciones. Necesitamos tener una restricción en nuestro programa: al crear un nuevo objeto de automóvil para él siempre por ejemplo, se debe indicar el modelo y la velocidad máxima. De lo contrario, no permita la creación del objeto. Esta tarea es fácil de afrontar. funciones constructoras... Obtuvieron su nombre por una razón. El constructor crea una especie de "esqueleto" de la clase, al que debe corresponder cada nuevo objeto de la clase. Volvamos a una versión más simple de la clase Car con dos campos para mayor comodidad. Teniendo en cuenta nuestros requisitos, el constructor de la clase Car se verá así: public Car (String model, int maxSpeed) (this. Model = model; this. MaxSpeed ​​= maxSpeed;) Y la creación del objeto ahora se ve así: public static void main (String args) (Car bugatti = new Car ("Bugatti Veyron", 407);) Presta atención, cómo se crea el constructor... Parece un método normal, pero no tiene ningún tipo de retorno. En este caso, el nombre de la clase se indica en el constructor, también con mayúscula. En nuestro caso, es Car. Además, el constructor usa una nueva palabra clave para ti. esta... "esto" en inglés significa "esto, esto". Esta palabra se refiere a un tema específico. El código en el constructor: public Car (String model, int maxSpeed) (this. Model = model; this. MaxSpeed ​​= maxSpeed;) se puede traducir casi literalmente: "modelo para este automóvil (que estamos creando ahora) = el argumento del modelo, que se especifica en el constructor .maxSpeed ​​para esta máquina (que estamos creando) = el argumento maxSpeed ​​que se especifica en el constructor ". Y así sucedió: public class Car (String model; int maxSpeed; public Car (String model, int maxSpeed) (this. Model = model; this. MaxSpeed ​​= maxSpeed;) public static void main (String args) (Car bugatti = new Car ("Bugatti Veyron", 407); System.out.println (bugatti. Model); System.out.println (bugatti.maxSpeed);)) Salida de consola: Bugatti Veyron 407 El constructor ha asignado correctamente los valores requeridos. ¡Puede haber notado que un constructor es muy similar a un método regular! Así es: un constructor es un método, solo un poco específico :) Al igual que en un método, pasamos parámetros a nuestro constructor. Y al igual que llamar a un método, llamar a un constructor no funcionará si no los especifica: public class Car (String model; int maxSpeed; public Car (String model, int maxSpeed) (this. Model = model; this. MaxSpeed ​​= maxSpeed;) public static void main (String args) (Car bugatti = new Car (); // error!)) Verá, el constructor hizo lo que estábamos tratando de lograr. ¡Ahora no puedes crear un coche sin velocidad o sin modelo! Las similitudes entre constructores y métodos no terminan ahí. Al igual que los métodos, los constructores pueden sobrecarga... Imagina que tienes 2 gatos viviendo en tu casa. Te llevaste a uno de ellos cuando era un gatito, y al segundo lo trajiste a casa de la calle cuando era adulto y no sabes exactamente cuántos años tiene. Esto significa que nuestro programa debería poder crear gatos de dos tipos: con un nombre y una edad para el primer gato, y solo con un nombre para el segundo gato. Para hacer esto, sobrecargaremos el constructor: public class Cat (String name; int age; // para el primer gato // para el segundo gato public Cat (String name) (this. name = name;) public static void main (String args) (Cat barsik = new Cat ("Barsik", 5); Cat streetCatNamedBob = new Cat ("Bob");)) К al constructor original con los parámetros “nombre” y “edad”, agregamos uno más, solo con un nombre. Del mismo modo, hemos sobrecargado los métodos en los tutoriales anteriores. Ahora podemos crear con éxito ambas variantes de gatos :)

¿Recuerdas que al comienzo de la conferencia dijimos que ya habías usado constructores, solo que tú mismo no lo notaste? Esto es cierto. El punto es que cada clase en Java tiene un llamado Constructor predeterminado... No tiene argumentos, pero se activa cada vez que se crea cualquier objeto de cualquier clase. public class Cat (public static void main (String args) (Cat barsik = new Cat ();)) A primera vista, esto es invisible. Bueno, creamos un objeto y lo creamos, ¿dónde trabaja el constructor? Para ver esto, escribamos un constructor vacío para la clase Cat directamente con nuestras manos, y dentro de él enviamos una frase a la consola. Si se muestra, el constructor ha funcionado. public class Cat (public Cat () (System. out. println ("¡Creé un gato!");) public static void main (String args) (Cat barsik = new Cat (); // aquí es donde funcionó el constructor predeterminado } } Salida de consola: ¡Has creado un gato! ¡Aquí está la confirmación! El constructor predeterminado siempre está presente de manera invisible en sus clases. Pero necesitas conocer una característica más. El constructor predeterminado desaparece de la clase cuando crea algún constructor con argumentos. La prueba de esto, de hecho, ya la hemos visto más arriba. Aquí en este código: public class Cat (String name; int age; public Cat (String name, int age) (this. Name = name; this. Age = age;) public static void main (String args) (Cat barsik = new Cat (); // error!)) No pudimos crear un gato sin nombre y edad porque definimos un constructor para Cat: cadena + número... Constructor predeterminado justo después de esto desaparecido de la clase. Por lo tanto, asegúrese de recordar: si necesita varios constructores en su clase, incluso vacío, debe crearse por separado... Por ejemplo, estamos creando un programa para una clínica veterinaria. Nuestra clínica quiere hacer buenas obras y ayudar a los gatos sin hogar, de los que no sabemos ni nombre ni edad. Entonces nuestro código debería verse así: public class Cat (String name; int age; // para gatos domésticos public Cat (String name, int age) (this. name = name; this. age = age;) // para gatos callejeros public Cat () () public static void main (String args) (Cat barsik = new Cat ("Barsik", 5); Cat streetCat = new Cat ();)) Ahora que hemos escrito explícitamente el constructor predeterminado, podemos crear gatos de ambos tipos :) Para un constructor (como para cualquier método), el orden de los argumentos es muy importante. Intercambiemos los argumentos de nombre y edad en nuestro constructor. public class Cat (String name; int age; public Cat (int age, String name) (this. name = name; this. age = age;) public static void main (String args) (Cat barsik = new Cat ("Barsik ", 10); // ¡error!)) ¡Error! El constructor describe claramente: al crear un objeto Cat, debe pasarse número y cadena, en ese orden... Por tanto, nuestro código no funciona. Asegúrese de recordar esto y tenerlo en cuenta al crear sus propias clases: public Cat (String name, int age) (this. Name = name; this. Age = age;) public Cat (int age, String name) (this. Edad = edad; este .nombre = nombre;) ¡Estos son dos constructores completamente diferentes! Si expresa en una oración la respuesta a la pregunta "¿Por qué necesitas un constructor?", podemos decir: para garantizar que los objetos estén siempre en el estado correcto... Cuando use constructores, todas sus variables se inicializarán correctamente y no habrá máquinas con velocidad 0 y otros objetos "incorrectos" en el programa. Su uso es muy beneficioso, en primer lugar, para el propio programador. Si inicializa los campos usted mismo, existe un alto riesgo de perder algo y cometer errores. Y esto no sucederá con un constructor: si no le ha pasado todos los argumentos requeridos o no ha mezclado sus tipos, el compilador generará inmediatamente un error. Por separado, debe decirse que no deberías poner la lógica de tu programa dentro del constructor... Para esto tienes a tu disposición métodos, en el que puede describir toda la funcionalidad que necesita. Veamos por qué la lógica en el constructor es una mala idea: public class CarFactory (String name; int age; int carsCount; public CarFactory (String name, int age, int carsCount) (this. Name = name; this. Age = age ; this.carsCount = carsCount; System.out.println ( "Ella fue fundada" "Produce en promedio"+ (this. carsCount / this. age) + "autos por año"); ) public static void main (String args) (CarFactory ford = new CarFactory ("Ford", 115, 50000000);)) Tenemos una clase CarFactory describiendo una fábrica de automóviles. Dentro del constructor, inicializamos todos los campos y ponemos la lógica aquí: enviamos información sobre la fábrica a la consola. Parece que no hay nada de malo en eso, el programa funcionó perfectamente. Salida de consola: Nuestra fábrica de autos se llama Ford Fue fundada hace 115 años Durante este tiempo ha producido 50,000,000 de autos, en promedio produce 434,782 autos por año Pero de hecho, colocamos una bomba de tiempo. Y un código como este puede provocar errores con mucha facilidad. Imaginemos que ahora no estamos hablando de Ford, sino de la nueva fábrica "Amigo Motors", que existe desde hace menos de un año y produce 1000 autos: clase pública CarFactory (String name; int age; int carsCount; public CarFactory ( String name, int age, int carsCount) (this. Name = name; this. Age = age; this. CarsCount = carsCount; System. Out. Println ( "Nuestra fábrica de coches se llama"+ esto. nombre); Sistema. fuera. println "Ella fue fundada"+ esto. edad + "hace años"); Sistema. fuera. println "Durante este tiempo, se produjo"+ esto. carsCount + "coches"); Sistema. fuera. println "Produce en promedio"+ (this. carsCount / this. age) + "autos por año"); ) public static void main (String args) (CarFactory ford = new CarFactory ("Amigo Motors", 0, 1000);)) Salida de consola: Nuestra fábrica de automóviles se llama Amigo Motors Exception en el hilo "main" java.lang.ArithmeticException: / by zero. Fue fundada hace 0 años. Durante este tiempo, se han producido 1000 automóviles en CarFactory. (CarFactory.java:15) en CarFactory.main (CarFactory.java:23) El proceso finalizó con el código de salida 1¡Ha llegado! El programa terminó con una especie de error incomprensible. ¿Puedes adivinar cuál es la razón? La razón está en la lógica que ponemos en el constructor. En concreto, en esta línea: System. fuera. println "Produce en promedio"+ (this. carsCount / this. age) + "autos por año"); Aquí realizamos un cálculo y dividimos el número de máquinas producidas por la edad de la fábrica. Y como nuestra fábrica es nueva (es decir, tiene 0 años), el resultado es la división por 0, lo cual está prohibido en matemáticas. Como resultado, el programa termina con un error. ¿Qué deberíamos haber hecho? Mueva toda la lógica a un método separado y llámelo, por ejemplo, printFactoryInfo (). Se puede pasar un objeto CarFactory como parámetro. También puede poner toda la lógica allí y, al mismo tiempo, el procesamiento de posibles errores, como el nuestro con cero años. A cada uno lo suyo. Se necesitan constructores para establecer correctamente el estado de un objeto. Para la lógica empresarial, tenemos métodos. No mezcle uno con otro. Aquí hay algunos enlaces útiles donde puede leer más sobre constructores:

La función más importante de cualquier clase es el constructor. Te permite crear una instancia de un objeto. Si no tiene un constructor, se crea un constructor predeterminado:

Usuario de clase pública (
int age; // campo
String firstName; // campo
String lastName; // campo
User () (// así es como se ve el constructor predeterminado
// vacío
}
}

Como puede ver, el constructor tiene el mismo nombre que el nombre de la clase.
Los constructores, al igual que las funciones, pueden aceptar un conjunto de parámetros como entrada, que luego utilizan al crear un objeto.

Usuario de clase pública (
int age; // campo
String firstName; // campo
String lastName; // campo
Public User (int age, String firstName, String lastName) (// constructor con tres parámetros
this.age = edad;
this.firstName = firstName;
this.lastName = lastName;
}
}

Obviamente, los constructores se llaman cuando se crea el objeto:

Usuario usuario = nuevo usuario (18, "Bendjamin", "Botón");

Por lo tanto, hemos creado un objeto de la clase Usuario, cuyo campo Edad contiene los valores 18, el primer Nombre Bendjamin y el último Nombre Botón.
Usar este constructor es mucho más conveniente que si intentáramos hacerlo manualmente:

Usuario usuario = nuevo Usuario ();
usuario.edad = 18;
user.firstName = "Bendjamin";
user.lastName = "Botón";

Además, si utiliza algún constructor, no se crea el constructor predeterminado. Por lo tanto, si solo tenemos un constructor con tres parámetros, entonces no podemos crear un objeto de esta clase sin llamarlo:

User user = new User (); // error, no hay constructor predeterminado

Pasemos a algunas ventajas de la idea intellij. Presione alt + insertar:

Este es un menú para generar automáticamente algunas cosas útiles para la clase. Hoy estamos aquí interesados ​​en el artículo Constructor. Ahora, si tiene campos en la clase, puede elegir entre qué campos necesita crear un constructor y el entorno de programación escribirá su código por usted. Si necesita otro constructor, presione los botones apreciados nuevamente y agregue otro:

Usuario de clase pública (
int age; // campo
String firstName; // campo
String lastName; // campo
Usuario público (int edad, String firstName, String lastName) (
this.age = edad;
this.firstName = firstName;
this.lastName = lastName;
}

Usuario público (int edad) (
this.age = edad;
}
}

Ahora considere la extraña línea this.VariableName = VariableName. La palabra clave this indica que es necesario asignar el valor pasado al constructor a la instancia actual de la clase. Por lo tanto, si tuviéramos que escribir fuera de la clase, entonces user.age = age, donde age es una variable regular.
Se pueden llamar a otros constructores dentro de los constructores, por ejemplo:

Usuario de clase pública (
int age; // campo
String firstName; // campo
String lastName; // campo

Usuario público (int edad, String firstName, String lastName) (
this.age = edad;
this.firstName = firstName;
this.lastName = lastName;
}

Usuario público (int edad) (
this (edad, "desconocido", "desconocido"); // llamar al constructor desde tres parámetros
}
}

Además, si se usó herencia en su clase, entonces para llamar al constructor del padre, debe usar la palabra clave super
Los constructores son necesarios para la configuración inicial del objeto, si necesita realizar algunas acciones con los campos, por ejemplo, para inicializarlos.

Para lograr objetivos que van más allá de las necesidades de una inicialización simple, se proporcionan miembros especiales como parte de la clase: constructores(constructores). Un constructor es un bloque de expresiones que se utilizan para inicializar el objeto creado. La inicialización se realiza hasta que el nuevo operador devuelve una referencia de objeto al bloque de llamada. Los constructores tienen el mismo nombre que la clase en la que están declarados. Al igual que los métodos de clase ordinarios, los constructores pueden aceptar cualquier número de argumentos (incluido cero), pero a diferencia de los métodos, no pueden devolver valores de ningún tipo. Al crear un objeto de una clase que contiene un constructor que se declara con parámetros, el nuevo operador va acompañado del nombre de la clase y una lista de los argumentos correspondientes, entre paréntesis. Los constructores se llaman después asignar valores predeterminados a los campos del objeto recién creado y ejecutar instrucciones explícitas para inicializar los campos.

En la versión aumentada de la clase Body, cuyo texto se ve a continuación, el objeto se restaura a su estado original utilizando expresiones de inicialización y un constructor.

public long idNUm;

cadena pública nombre= "<Без имени>";

Órbitas del cuerpo público = nulo;

nextID largo estático privado = 0;

idNUm = nextID ++;

Una declaración de constructor consta de un nombre de clase seguido de una lista de parámetros (posiblemente vacíos), delimitados por paréntesis, y el cuerpo del constructor, un bloque de expresiones entre llaves. Los constructores, como los miembros de clase ordinarios, pueden recibir los mismos modificadores de acceso, pero los constructores, estrictamente hablando, son miembros de un tipo especial; sin embargo, tales diferencias semánticas sutiles, por regla general, excepto en situaciones en las que entra en juego la herencia.

El constructor de la clase Body se declara sin parámetros. Su propósito es bastante importante: garantiza la unicidad del valor del campo idNum del objeto de clase recién creado. En la versión original de la clase, un pequeño error del programador de usuario, por ejemplo, debido a una asignación inexacta de un valor al campo idNum o a la ausencia de instrucciones para incrementar el contenido del campo nextID, podría llevar al hecho de que varios objetos Body recibirían el mismo número de secuencia. Este resultado es claramente incorrecto, ya que viola la parte del contrato de clase que dice:

"Los valores idNum de diferentes objetos de la clase deben ser únicos".

Al transferir la responsabilidad de elegir los valores idNum correctos a la clase misma, nos desharemos de tales errores de una vez por todas. El constructor de la clase Body es ahora el único actor que modifica el contenido del campo nextID y necesita acceder a él. Por lo tanto, podemos y debemos designar la variable nextID con el modificador privado para evitar el acceso a ella fuera de la clase. Al hacer esto, eliminaremos una de las posibles fuentes de errores que amenazan a los futuros usuarios de nuestra clase.

Poseer un constructor, nosotros son libres de elegir los valores apropiados para la asignación a la variable idNUm. En futuras versiones de la clase, se puede proporcionar, digamos, la operación de navegar por una base de datos que contiene información sobre los cuerpos celestes conocidos por la ciencia, buscar el objeto astronómico correspondiente por nombre y calcular un nuevo número de serie del objeto solo si la búsqueda no fue exitoso. Tal cambio en el texto de la clase no tendrá ningún efecto en el código de la aplicación existente, ya que los detalles de implementación están ocultos en las profundidades de la propia clase.

Las expresiones de inicialización para el nombre de las variables y las órbitas en el cuerpo de una declaración de clase asignan algunos valores válidos y útiles a esta última. Ahora, cuando se crea, un objeto adquiere automáticamente el conjunto original de propiedades compatibles con el contrato que describen su estado. Además, somos libres de cambiar algunos de ellos a nuestra discreción:

Cuerpo sol = nuevo Cuerpo (); // idNUm = 0

sol. nombre = "Sol";

Cuerpo tierra = nuevo Cuerpo (); // idNum = 1

earth.name = "tierra";

tierra.orbitas = sol;

En el proceso de crear un objeto usando el operador new, el constructor de la clase Body llamado después asignación de las expresiones de inicialización proporcionadas por nosotros a los campos nombre y obbits.

El caso considerado anteriormente, cuando conocemos de antemano, en el momento de escribir el programa, el nombre de un objeto astronómico y sobre qué cuerpo celeste pasa la órbita de su movimiento, es relativamente raro. Desde este punto de vista, sería bastante razonable crear otro constructor que tome los valores del nombre del objeto y la referencia al objeto central como argumentos:

Cuerpo (String bodyName, Body orbitsAround) (

nombre = bodyName; orbits = orbitsAround;

Como puede ver fácilmente, un constructor de una clase se refiere a otro a través de la expresión this: la primera instrucción ejecutable en el cuerpo del constructor iniciador. Una propuesta similar se llama una llamada explícita al constructor. Si el constructor al que pretende hacer referencia implica explícitamente la especificación de argumentos, deben pasarse cuando se llame. Cuál de los constructores se llamará depende del número de argumentos y del conjunto de sus tipos. En este caso, la expresión this significa llamar a un constructor sin parámetros, lo que le permite establecer el valor idNum del objeto y aumentar el contenido actual del campo estático nextID en uno. Hacer referencia a esto hace posible evitar repetir el código de inicialización idNum y cambiar el nextID. Ahora el código para crear objetos se vuelve mucho más simple:

Cuerpo sol = nuevo Bоdу ("sol", nulo);

Cuerpo tierra = agua nueva ("tierra", sol);

La versión del constructor llamado durante la ejecución del nuevo operador está determinada por la estructura de la lista de argumentos pasada.

Si se usa una expresión de invocación de constructor explícita, debe ser la primera instrucción ejecutable en el cuerpo del constructor iniciador. Las expresiones utilizadas como argumentos de llamada no deben contener referencias a campos y métodos del objeto actual; en todos los casos, se supone que en esta etapa aún no se ha completado la construcción del objeto.

Por razones de completitud lógica, podríamos introducir otro constructor en la clase Body, proporcionando un único argumento y utilizado para crear objetos que representan cuerpos celestes que no son satélites de estrellas más grandes. Es conveniente referirse a este constructor cuando se sabe de antemano que el valor del segundo argumento es nulo:

Cuerpo (String bodyName) (

esto (bodyName, nulo);

Aquí nuevamente, se usa la técnica de llamar explícitamente a un constructor.

No es raro que un contrato de clase requiera que el código responsable de crear objetos de esta clase proporcione información adicional a los constructores de la clase. Por ejemplo, como autor de la clase Body, puede estipular la siguiente condición: "Todos los objetos de la clase Body deben tener un nombre". Para garantizar su ejecución, puede incluir un parámetro de nombre en la lista de parámetros de cada uno de los constructores de la clase; ahora no tiene que preocuparse por inicializar el campo de nombre.

Hay varias razones para usar constructores personalizados a continuación.

· Sin la ayuda de constructores con parámetros, algunas clases no pueden proporcionar a sus objetos valores iniciales aceptables.

· Cuando se utilizan constructores adicionales, la tarea de determinar las propiedades iniciales de los objetos se simplifica (un ejemplo ilustrativo es el constructor de la clase Body con dos parámetros).

· La creación de un objeto a menudo se asocia con altos costos debido a la elección incorrecta de inicializadores. Por ejemplo, si un objeto de una clase contiene una tabla y el costo computacional de construirla es alto, sería completamente irrazonable proporcionar un inicializador predeterminado, sabiendo que más adelante, de una forma u otra, tendrá que descartar el resultado de su trabajo y repetir la inicialización para darle a la tabla las propiedades necesarias en una situación particular. ... Es más conveniente aplicar inmediatamente un constructor adecuado que sea capaz de crear una tabla con las propiedades requeridas.

· Si el constructor no está marcado con la bandera de publicación, el rango de sujetos que pueden usarlo para crear instancias de clase es limitado. Tiene derecho, por ejemplo, a evitar que los programadores que utilizan un paquete creen objetos de clase proporcionando una marca de acceso a nivel de paquete para todos los constructores de clases.

Los constructores sin parámetros también se utilizan ampliamente. Si, al declarar una clase, no creó ningún constructor de ningún tipo, el compilador incluirá automáticamente un constructor vacío sin parámetros en la clase. Un constructor similar (llamado Constructor predeterminado) se crea solo si no existen otros constructores, ya que hay ejemplos de clases (como, por ejemplo, Attr, que se analiza en el próximo capítulo) en las que usar un constructor sin parámetros no es práctico o incluso imposible. Si se requieren tanto un constructor sin parámetros como uno o más constructores adicionales, el primero debe crearse explícitamente. El constructor predeterminado obtiene el mismo atributo de acceso que la clase para la que se creó, si la declaración de clase se proporciona con el modificador publiс, entonces el constructor

se marcará como publiс.

Hay otra forma especial del constructor: constructor de copias, que toma un objeto del tipo actual como argumento y crea una copia del mismo. Por lo general, dicho constructor almacena los valores del objeto original en los campos del nuevo objeto, pero a veces la semántica de la clase obliga al autor a proporcionar operaciones más sofisticadas en el cuerpo del constructor de copia. A continuación se muestra un constructor simple para una copia de objetos de tipo Body.

Cuerpo (Cuerpo otro) (

idNum = other.idNum;

nombre= otro.nombre;

órbitas = otras órbitas;

El enfoque para resolver el problema de copiar objetos usando constructores especiales no ha encontrado un uso generalizado en las clases de paquetes estándar de Java, ya que el uso del método Clone se considera más preferible para lograr este objetivo (ver sección 3.9 en la página 111). Sin embargo, se proporciona un constructor de copia simple, por ejemplo, como parte de la clase String y en las clases de colección (se tratan en el Capítulo 16)

Se admiten versiones genéricas de constructores de copia, que le permiten inicializar una colección con el contenido de otra colección (y no necesariamente del mismo tipo). De hecho, crear constructores de copias requiere el mismo esfuerzo que escribir un método de clonación correcto.

En el texto de los constructores, se permite mencionar excepciones declaradas.

Una cláusula throws se coloca después de la lista de parámetros, inmediatamente antes de la llave de apertura que marca el comienzo del cuerpo del constructor. Si una declaración de constructor contiene una cláusula throws, cualquier método que llame indirectamente al constructor cuando se ejecuta la nueva declaración debe asegurarse de que los tipos especificados se detectan utilizando las cláusulas catch adecuadas o enumerar estos tipos en la cláusula throws de su propia declaración.

Como sabe, un objeto es una instancia de una determinada clase. La nueva palabra clave se utiliza para crearlo, por ejemplo:
Persona estudiante = nueva persona ("Mike")
Este código crea un nuevo objeto Persona y se indica su nombre - Miguel... Línea " Miguel"Se pasa como argumento al constructor correspondiente Persona:

Persona (nombre de cadena) (this.name = nombre;)

Este constructor le permite especificar el nombre de una persona al crear un objeto.

Siempre se llama al constructor cuando se crea una nueva instancia de la clase. En otras palabras, los constructores se utilizan para inicializar el estado de un objeto cuando se crea el objeto. Los constructores parecen métodos regulares, pero están lejos de serlo:

  • Los constructores tienen el mismo nombre que el nombre de la clase.
  • Los constructores, como los métodos, tienen una lista de parámetros aceptados, pero no tienen un tipo de retorno (ni siquiera vacío).

A continuación se muestra un conjunto de 7 reglas básicas para trabajar con constructores , lo que le permite comprender completamente su trabajo.

  1. Los constructores pueden estar sobrecargados:

Esto significa que una clase puede tener muchos constructores diferentes si sus listas de parámetros son diferentes. Por ejemplo:

Clase Rectangle (int ancho; int alto; Rectangle () (ancho = 1; alto = 1;) Rectangle (int ancho) (this. Width = ancho; this. Height = ancho;) Rectangle (int ancho, int alto) ( este. ancho = ancho; este. alto = alto;))

Tener tres constructores diferentes Rectángulo puede crear un nuevo objeto de tres formas diferentes:

Rectángulo rect1 = nuevo Rectángulo (); Rectángulo rect2 = nuevo Rectángulo (10); Rectángulo rect3 = nuevo Rectángulo (10,20);

  1. Constructor predeterminado:

La declaración de constructores es opcional. Si ninguno de los constructores está definido, entonces el compilador Java genera automáticamente un constructor predeterminado que está vacío y no tiene parámetros.

Por ejemplo, si escribimos la clase Rectangle así:

Rectángulo de clase (ancho int, altura; área int () () int perímetro () ())

Luego, el compilador insertará automáticamente el constructor predeterminado: ectangle () ()

  1. El compilador no generará un constructor predeterminado si la clase ya tiene un constructor:

Considere el siguiente ejemplo:

Clase Rectángulo (int ancho; int alto; Rectángulo (int ancho) (este. Ancho = ancho; este. Alto = ancho;) Rectángulo (int ancho, int alto) (este. Ancho = ancho; este. Alto = alto;) )

Al intentar crear un nuevo objeto: Rectangle rect1 = new Rectangle (); El compilador arrojará un error porque no puede encontrar un constructor sin argumentos.

  1. Los constructores no se heredan:

A diferencia de los métodos, los constructores no se heredan. Ejemplo:

Class Rectangle (Rectangle (int ancho, int alto) ()) class Square extiende Rectangle ()

No puede hacer algo como esto: Cuadro cuadrado = nuevo Cuadrado (10, 10);

  1. ¡Los constructores pueden ser privados!

Puede hacer que el constructor sea privado para evitar que el código externo cree una nueva instancia de la clase. ¿Cuál podría ser la ventaja de un constructor privado?

En un patrón de diseño llamado único, se utiliza un constructor privado para garantizar que siempre exista una sola instancia de una clase. Clase único proporciona un método estático para obtener esta instancia única.

  1. El constructor predeterminado tiene el mismo modificador de acceso que la clase:

Al escribir la siguiente clase: public class Person ()

Al insertar el constructor predeterminado, el compilador también indicará el modificador de acceso requerido: public Preson ();

  1. La primera línea de cualquier constructor debe llamar al constructor sobrecargado de la misma clase o al constructor de su superclase:

Si este no es el caso, entonces el compilador agregará automáticamente una llamada al constructor de la superclase sin argumentos super (); Esto puede conducir a un error, ya que tal constructor puede no existir en la superclase. Ejemplo:

Clase Parent (Parent (int number) ()) class Child amplía Parent (Child () ())

Dará como resultado un error porque el compilador inserta la llamada super () en el constructor de la clase Niño:

Child () (super (); // agregó el compilador)

Sin embargo, el compilador no insertará el constructor predeterminado para la clase. Padre ya que ya hay otros constructores.