Bruce_Eckel_Piensa_en_Java 04 capítulo

Bruce Eckel Piensa_enJava 04 capítulo gy jossucI-Rodrigue7 ‘benpa,1R 16, 2016 57 pagcs 4: Inicialización Y limpieza A medida que progresa la revolución computacional, la programación «insegura» se ha convertido en uno de los mayores culpables del encarecmiento de la programación. Dos de estos aspectos de seguridad son la inicialización y la limpieza. Muchos de los fallos que se dan en C ocurren cuando el programador olvida inicializar una variable. Esto es especialmente ha- bitual con las bibliotecas, cuando los usuarios no saben cómo inicializar un componente de una biblioteca, o incluso cuándo eben hacerlo.

La lim ieza o eliminacion es un problema especial porque PACE 1 ors7 es fácil olvidarse deu e’ puesto que ya no tie imoo Por consiguiente, las ya no se utiliza, nto utilizaba quedan reservados y es fácil acabar quedándose sin recursos (y el más importante, la memoria). C++ introdujo el concepto de constructor, un método especial invocado automáticamente en la creación de un objeto. Java también adoptó el constructor, y además tiene un recolector de basura que libera automáticamente recursos de memoria cuando dejan de ser utilizados.

Este capítulo examina os aspectos de inicialización y eliminación, y su soporte en Java. Inicialización garantizada constructor Es posible imaginar la creación de un método denominado puede garantizar que se inicialice cada objeto proporcionando un método especial llamado constructor. Si una clase tiene un constructor, Java llama automáticamente al constructor cuando se crea un objeto, antes de que los usuarios puedan siquiera pensar en poner sus manos en él. por consiguiente, la inicialización queda garantizada. El siguiente reto es cómo llamar a este método. Hay dos aspectos.

El primero es que cualquier nombre que se use podría colisionar con un nombre que nos gustaría utilizar como miembro en una clase. El segundo es que dado que el compilador es el responsable de invocar al constructor, debe saber siempre qué método Invocar. La soluclón de C++ parece la mejor y más lógica, por lo que se utiliza también en Java: el nombre del constructor es el mismo que el nombre de la clase. Tiene sentido que un método así se invoque automaticamente en la inicialización. He aquí hay una clase con un constructor simple: / / : c04:ConstructorSimple. java / / Muestra de un constructor simple. 8 Piensa en Java class Roca { Roca() {l / Éste es el constructor System. out. println(«Creando Roca»); public class ConstructorSimple { public static void main (String[] args) foront i = O; i < lo; itt) new Roca ( ) ; 20F de todos los métodos sea minúscula no se aplica a los constructores, dado que el nombre del constructor debe coincidir exactamente con el nombre de la clase. Como cualquier método, el constructor puede tener parámetros para permitir especificar cómo se crea un objeto. El ejemplo de arriba puede cambiarse sencillamente de forma que el constructor reciba un argumento: / : c04:ConstructorSimple2. ava / / Los constructores pueden tener parámetros. class Roca2 { Roca2 (int i) ( System. out. println( "Creando la roca numero public class Coristr uctorSimple2 { public static void main(String[l for(inti= O; i < 10; i+t) new Roca2 (i): args) 4: Inicialización y limpieza 129 Los parámetros del constructor proporcionan un medio para pasar parámetros a la inicialización de un objeto. por ejemplo, si la clase Arbol tiene un constructor que toma un número entero que indica la altura del árbol, crearíamos un objeto Arbol como éste Arbol a e método porque no tiene valor de retorno.

Esto es muy diferente al valor de retorno void, en el que el método no devuelve nada pero se sigue teniendo la opción de hacer que devuelva algo más. Los constructores no devuelven nada y no es necesario tener ninguna opción. Si hubiera un valor de retorno, y si se pudiera seleccionar el propio, el compilador, de alguna manera, necesitaría saber qué hacer con ese valor de retorno. Sobrecarga métodos Uno de los aspectos más importantes de cualquier lenguaje de programación es el uso de los nombres. Al crear un objeto, se da n nombre a cierta región de almacenamiento.

Un método es un nombre que se asigna a una acción. Al utilizar nombres para describir el sistema, se crea un programa más fácil de entender y de modificar por la gente. Es como escribir en prosa -la meta es comunicarse con los lectores. Para hacer referencia a objetos y métodos se usan nombres. Los nombres bien elegidos hacen más sencillo que todos entiendan un código. Surge un problema cuando se trata de establecer una correspondencia entre el concepto de matiz del lenguaje humano y un lenguaje de programación. A menudo, la misma palabra expresa varios ignificados -se ha sobrecargado.

Esto es útil, especialmente cuando incluye diferencias triviales. Se dice «lava la camisa», «lava el coche» y «lava el perro». Sería estúpido tener que decir «lavacarmsas la camisa», «lavacoche el coche» y «lavaperro el perro» simplemente para que el que lo escuche no tenga necesidad de intentar distinguir entre las acciones que se llevan a cabo. La mayor ajes humanos son 40F redundantes, po distinguir entre las acciones que se llevan a cabo. La mayoría de los lenguajes humanos son redundantes, por lo que incluso aunque se te olviden unas pocas palabras, se gue pudiendo entender.

No son necesarios identificadores únicos -se puede deducir el significado del contexto. La mayoría de los lenguajes de programación (C en particular) exigen que se tenga un identificador único para cada función. Así, no se podría tener una función llamada print( ) para imprimir enteros si existe ya otra función llamada print( ) para imprimir decimales cada función requiere un nombre único. 130 En Java (‘y C++) otros factores fuerzan la sobrecarga de los nombres de método: el constructor. Dado que el nombre del constructor está predeterminado por el ombre de la clase, sólo puede haber un nombre de constructor.

Pero ¿qué ocurre si se desea crear un objeto de más de una manera? por ejemplo, suponga que se construye una clase que puede inicializarse a sí misma de manera estándar o leyendo información de un archivo. Se necesitan dos constructores, uno que no tome argumentos (el constructor por defecto, llamado también constructor sin parámetros), y otro que tome como parámetro un Stnng, que es el nombre del archivo con el cual inicializar el objeto. Ambos son constructores, por lo que deben tener el mismo nombre -el nombre de la clase. r consiguiente, la sobrecarga de métodos es esencial para permitir que se use el mismo nombre de métodos con distintos tipos de parámetros. Y aunque la sobrecarga de métodos es una necesidad para los constructores, es bastante y se s OF de métodos es una necesidad para los constructores, es bastante conveniente y se puede usar con cualquier método. He aquí un ejemplo que muestra métodos sobrecargados, tanto constructores como ordinarios: c04:Sobrecarga. java / / Muestra de sobrecarga de métodos / / tanto constructores como ordinarios. import java. util. ; class Arbol { nt altura; Arbol 0 visualizar (‘Plantando un retoño») ; altura = O; Arbol (int i) { visualizar(«Creando un nuevo arbol que tiene metros de alto»); altura – i; void info ( ) { arbol tiene + altura t » metros de alto»); void info(String S) { visualizar(s + » : El arbol tiene + altura t » metros de alto»); static void visualizar (String S) System. out. println ( S); 6 OF nada más que decir. Parecería extraho dar dos nombres separados a lo que es obviamente el mismo concepto. Afortunadamente, la sobrecarga de métodos permite usar el mismo nombre para ambos. Distinguir métodos sobrecargados

Si los métodos tienen el mismo nombre, ¿cómo puede saber Java qué método se debe usar en cada caso? Hay una regla simple: cada método sobrecargado debe tomar una única lista de tipos de parámetros. Si se piensa en esto por un segundo, tiene sentido: ¿de qué otra forma podría un programador distinguir entre dos métodos que tienen el mismo nombre si no fuera por los tipos de parámetros? Incluso las diferencias en el orden de los parámetros son suficientes para distinguir ambos métodos: (Aunque normalmente este enfoque no es necesario, pues produce un código dificil de mantener. / : c04:OrdenSobrecarga. java / / Sobrecarga basada en el / / orden de los parámetros. public class Ordensobrecarga ( static void print (String S, int i) «cadena: » t St entero: » t i); En algunos documentos sobre Java de Sun, por el contrario, se refieren a éstos con el poco elegante pero descriptivo nombre de «constructores sin paráme ino «constructor por defecto» se ha usado dura nos, por lo que será el 1 ///:Ambos métodos print( ) tienen los rmsmos argumentos, pero distinto orden, y eso es lo que los hace diferentes.

Sobrecarga con tipos primitivos Un tipo primitivo puede ser promocionado automáticamente de n tipo menor a otro mayor, y esto puede ser ligeramente confuso si se combina con la sobrecarga. El ejemplo siguiente demuestra lo que ocurre cuando se pasa un tipo primitivo a un método sobrecargado: / / : c04:SobrecargaPrimitivo. java / / Promoción de tipos primitivos y sobrecarga. public class SobrecargaPrimitivo { / / los booleanos no pueden convertirse automáticamente static void visualizar (String S) { System. out . rintln (S); void fl 80F («E(float)» ) ; f3 (double x) { visualizar («E(double)» ) fa (int x) { visualizar («f4(int)») ; } f4 (long x) { visualizar («f4(long)» ) ; } 4 (floatx) { visualizar («f4 (float) » ) ; } f4 (double x) { visualizar («f4(double)» ) ; void E5 (long x) { visualizar («f5(long)» ) ; } void f5 (float x) { visualizar («f5(float)» ) ; void f5 (double x) { visualizar («f5 (double)» ) void f6 (float x) void f6 (double x) visualizar («f7(double)» ) ; void f7 (double x) public static void main (String[l args) Sobrecargaprimitivo p = new SobrecargaPrimitivo(); Si se observa la salida de este programa, se veré que el valor constante 5 se trata como un int, de forma que si hay disponible un método sobrecargado que tome un int, será el utilizado. En todos los demás casos, si se tiene un tipo de datos menor al parámetro del método, ese tipo de dato será promocionado. Un dato de tipo char produce un efecto ligeramente diferente, pues si no encuentra una coincidencia exacta de char, se promociona a int. ¿Qué ocurre SI el parámetro es mayor que el que espera el método sobrecargado? La respuesta la proporciona una modificación del programa anterior: / / : c04:Degradacion. java / / Degradación de tipos primitivos y sobrecarga. public class Degradacion static void visualizar (String System. out. println (S); void fl (char x) void fl (byte x)