Documentos de Académico
Documentos de Profesional
Documentos de Cultura
H. Tejeda
Febrero 2016
Indice
1. Bloques y alcance 1
2. Sobrecarga de metodos 5
3. Ambiguedad 8
5. Referencia this 11
6. Campos static 15
8. Agrupamiento de clases 19
1. Bloques y alcance
Dentro de cualquier clase o metodo, el codigo entre un par de llaves es llamado un bloque. Para
el ejemplo del codigo 1, el metodo mostrado contiene dos bloques. El primer bloque contiene otro,
as que es un bloque externo, tambien conocido como bloque exterior. Este comienza inmedia-
tamente despues de la declaracion del metodo (lnea 1) y termina al final del metodo (lnea 13). El
segundo bloque es llamado el bloque interno o bloque interior. Este esta contenido dentro del
segundo conjunto de llaves (lneas 5 y 10) y contiene dos sentencias ejecutables: la declaracion de
otroNumero y una sentencia println(). El bloque interno esta anidado, o contenido enteramente
en el bloque exterior.
1
1 public s t a t i c void metodoConBloquesAnidados ( ) {
2 int unNumero = 5 1 2 ; // unNumero comienza a e x i s t i r
3 System . out . p r i n t l n
4 ( En b l o q u e e x t e r n o , unNumero e s + unNumero ) ;
5 { // i n i c i a e l b l o q u e i n t e r n o con l a l l a v e
6 int otroNumero = 1 0 2 4 ; // otroNumero comienza a e x i s t i r
7 System . out . p r i n t l n
8 ( En b l o q u e i n t e r n o , unNumero e s +
9 unNumero + y otroNumero e s + otroNumero ) ;
10 } // f i n d e l b l o q u e i n t e r n o y otroNumero c e s a de e x i s t i r
11 System . out . p r i n t l n
12 ( En b l o q u e e x t e r n o , unNumero e s + unNumero ) ;
13 } // f i n b l o q u e e x t e r n o y unNumero c e s a de e x i s t i r
Un bloque puede estar completamente dentro de otro bloque o fuera y separado, pero los bloques
nunca se pueden traslapar.
Cuando se declara una variable, no puede ser esta referida fuera de su bloque. Una variable comienza
a existir, o entra en alcance, cuando se declara. Una variable cesa de existir, o sale de alcance, al
final del bloque en el cual fue declarada. Se pueden crear tantas variables y bloques como se necesiten
dentro del cualquier programa, pero no es prudente hacerlo sin razon, ya que la probabilidad de un
uso impropio de las variables y alcance se incrementa.
No se pueden usar elementos de datos que no esten en el alcance. El codigo 2 tiene un metodo que
contiene dos bloques y las lneas 2, 5, 7, 12, 14 son sentencias no validas.
1 public s t a t i c void m e t o d o C o n S e n t e n c i a s I n v a l i d a s ( ) {
2 unNumero = 1 2 ;
3 int unNumero = 3 4 ;
4 unNumero = 5 ;
5 otroNumero = 6 7 8 ;
6 {
7 otroNumero = 9 0 1 ;
8 int otroNumero = 2 3 ;
9 otroNumero = 4 ;
10 }
11 unNumero = 5 6 ;
12 otroNumero = 7 8 ;
13 }
14 unNumero = 9 0 ;
2
todava. De igual forma sucede cuando se intenta hacer las asignaciones de las lnea 5 y 7, ya que
otroNumero no ha sido declarado todava. En la sentencia de la lnea 12 la variable otroNumero
esta fuera del bloque donde fue declarada y en la lnea 14 unNumero tambien lo esta.
Dentro de un metodo, se puede declarar una variable con el mismo nombre multiples veces siem-
pre y cuando cada declaracion este en su propio bloque sin solapamiento. El codigo 3 muestra
dos declaraciones de la variable llamada algunValor, las cuales son validas ya que cada variable
esta contenida dentro de su propio bloque. La primera instancia de algunValor se ha ido fuera de
alcance antes de que la segunda instancia entre en alcance.
1 public s t a t i c void d o s D e c l a r a c i o n e s ( ) {
2 {
3 int a l g u n V a l o r = 1 2 3 ;
4 System . out . p r i n t l n ( a l g u n V a l o r ) ;
5 }
6 { // no d e c l a r a r b l o q u e s s i n r a z on . Se i n i c i a para mostrar e l a l c a n c e
7 int a l g u n V a l o r = 4 5 6 ; // v a r i a b l e d i f e r e n t e a l a d e l b l o q u e p r e v i o
8 System . out . p r i n t l n ( a l g u n V a l o r ) ;
9 }
10 }
No se puede declarar el mismo nombre de variable mas de una vez dentro del bloque, aun si el
bloque contiene otros bloques. Cuando se intenta hacer esto, se esta intentando redeclarar la
variable, que es una accion ilegal. Esto se muestra en el codigo 4 donde la segunda declaracion de
unValor, lnea 3, causa un error al intentar declarar la misma variable dos veces dentro del bloque
externo. De la misma forma la tercera declaracion de un unValor, lnea 6, es invalida, aunque
apararezca dentro de un nuevo bloque. El bloque interno que contiene la tercera declaracion esta
completamente dentro del bloque externo, as que la primera declaracion de unValor no esta fuera
de alcance.
1 public s t a t i c void r e d e c l a r a c i o n I n v a l i d a ( ) {
2 int unValor = 1 2 ;
3 int unValor = 3 4 ; // r e d e c l a r a c i on i n v a l i d a por e s t a r en e l mismo b l o q u e
4 {
5 int o t r o V a l o r = 5 6 ;
6 int unValor = 5 6 ; // r e d e c l a r a c i on i n v a l i d a , unValor en a l c a n c e
7 }
8 }
Se puede declarar una variable dentro de un metodo de una clase y usar el mismo nombre de
variable dentro de otro metodo de la clase. La variable declarada dentro de cada metodo reside en
su propia localidad de memoria. Cuando se usa el nombre de la variable dentro del metodo en el
cual esta declarada, esta tiene precedencia sobre, o anula, cualquier otra variable con el mismo
nombre en otro metodos. Es decir, una variable declarada locamente siempre enmascara u oculta
otra variable con el mismo nombre en cualquier otra parte en la clase (incluyendo campos de datos).
3
con el mismo nombre pero con diferente direccion de memoria y un nuevo valor (20). La nueva
variable existe solo dentro de primerMetodo(), donde se muestra el valor que guarda. Cuando
se termina la ejecucion de primerMetodo() la logica regresa al metodo main() y se muestra la
original unNumero, guardando 10. Cuando unNumero es pasado al segundoMetodo(), se hace una
copia dentro del metodo. Esta copia tiene el mismo identificador como la original unNumero, pero
con una diferente direccion de memoria. As que cuando el valor es cambiado a 200 dentro de
segundoMetodo() y mostrado, no tiene ningun efecto en la variable original de main(). Cuando la
logica regresa a main() despues de segundoMetodo(), el valor original es mostrado otra vez.
1 public c l a s s ReemplazoVariable {
2 public s t a t i c void main ( S t r i n g [ ] a r g s ) {
3 int unNumero = 1 0 ; // unNumero d e c l a r a d o en main ( )
4 // Siempre que unNumero s e a usado , e s t e t e n d r a e l v a l o r de 10
5 System . out . p r i n t l n ( En main ( ) , unNumero e s + unNumero ) ;
6 primerMetodo ( ) ;
7 System . out . p r i n t l n ( De r e g r e s o en main ( ) , unNumero e s + unNumero ) ;
8 segundoMetodo ( unNumero ) ;
9 System . out . p r i n t l n ( De r e g r e s o en main ( ) o t r a vez , unNumero e s +
10 unNumero ) ;
11 }
12 public s t a t i c void primerMetodo ( ) {
13 // unNumero e s t a en una d i r e c c i on de memoria d i f e r e n t e a l que
14 // e s t a en main ( ) . Esta e s d e c l a r a d a l o c a l m e n t e en e s t e me t o d o .
15 int unNumero = 2 0 ;
16 System . out . p r i n t l n ( En primerMetodo ( ) , unNumero e s + unNumero ) ;
17 }
18 public s t a t i c void segundoMetodo ( int unNumero ) {
19 // El parametro unNumero r e s i d e en una d i r e c c i on de memoria d i f e r e n t e
20 // a l a que e s t a en main ( ) . Esta e s t a d e c l a r a d a l o c a l m e n t e en e s t e me t o d o .
21 System . out . p r i n t l n ( En segundoMetodo ( ) , a l i n i c i o unNumero e s +
22 unNumero ) ;
23 unNumero = 2 0 0 ;
24 System . out . p r i n t l n ( En segundoMetodo ( ) , despue s de una a s i g n a c i on +
25 unNumero e s + unNumero ) ;
26 }
27 }
Actividad 2. Compilar, ejecutar, y revisar la salida del codigo 5. La aplicacion se puede descargar
usando este enlace.
Si las variables dentro de metodos de una clase tienen el mismo nombre que los campos de la
clase entonces anulan u ocultan a estos. En Java a lo anterior se le conoce como sombreado.
En el codigo 6 se muestra la clase Empleado3 que tiene dos variables de instancia y tres metodos
void. El metodo setValores() pone valores a los dos campos de clase. Siempre que el metodo
metodoUsaAtributosInstancia() es usado con un objeto Empleado3, los valores de instancia para
numEmp y pagoEmp son usados. Sin embargo, cuando el otro metodo, metodoUsaVariablesLocales,
es usado con un objeto Empleado3, los valores de las variables locales dentro del metodo, 444 y
5555.55, ensombrecen las variables de instancia de la clase. El codigo 7 muestra una aplicacion
breve que declara un objeto Empleado3 y usa cada metodo de la clase.
4
1 public c l a s s Empleado3 {
2 private int numEmp ;
3 private double pagoEmpl ;
4 public void s e t V a l o r e s ( ) { // me t o d o que usa l o s campos de c l a s e .
5 numEmp = 2 2 2 ;
6 pagoEmpl = 3 3 3 3 . 3 3 ;
7 }
8 public void m e t o d o U s a A t r i b u t o s I n s t a n c i a ( ) { // o t r o me t o d o usando campos
9 System . out . p r i n t l n ( Numero de empleado e s + numEmp ) ;
10 System . out . p r i n t l n ( Pago d e l empleado e s + pagoEmpl ) ;
11 }
12 public void m e t o d o U s a V a r i a b l e s L o c a l e s ( ) {
13 int numEmp = 4 4 4 ; // v a r i a b l e s l o c a l e s que o c u l t a n l o s campos
14 double pagoEmpl = 5 5 5 5 . 5 5 ;
15 System . out . p r i n t l n ( Numero de empleado e s + numEmp ) ;
16 System . out . p r i n t l n ( Pago d e l empleado e s + pagoEmpl ) ;
17 }
18 } // f i n de l a c l a s e Empleado3
1 public c l a s s PruebaEmpleado3 {
2 public s t a t i c void main ( S t r i n g [ ] a r g s ) {
3 Empleado3 unTrabajador = new Empleado3 ( ) ;
4 unTrabajador . s e t V a l o r e s ( ) ;
5 unTrabajador . m e t o d o U s a A t r i b u t o s I n s t a n c i a ( ) ;
6 unTrabajador . m e t o d o U s a V a r i a b l e s L o c a l e s ( ) ;
7 }
8 } // f i n de l a c l a s e PruebaEmpleado3
Es importante entender que las variables y campos con el mismo nombre representan diferentes
localidades de memoria ya que son declaradas dentro de diferentes alcances.
2. Sobrecarga de metodos
En el lenguaje coloquial hay varias palabras sobrecargadas. Cuando se dice abrir la puerta, abrir
los ojos, y abrir un archivo de computadora, se habla de tres acciones muy diferentes usando
metodos diferentes y produciendo resultados muy diferentes. Quien tenga un conocimiento suficiente
del lenguaje no tiene problema para entender el significado porque el verbo abrir se entiende en el
contexto del objeto directo.
5
Cuando se sobrecarga un metodo, multiples metodos comparten un nombre, y el compilador en-
tiende cual debe usar basandose en los argumentos en la llamada al metodo. Por ejemplo, suponer
que se a creado un metodo de clase para aplicar una tasa de interes simple a un saldo bancario. El
metodo es llamado calculaInteres(); este recibe dos parametros doubleel saldo y la tasa de
interes y muestra el resultado multiplicado. El codigo 8 muestra el metodo.
Cuando una aplicacion llama al metodo calculaInteres() y pasa dos argumentos double, como
en calculaInteres(1000.0, 0.04), el interes es calculado correctamente como 4 % de $1000.00.
Suponer que usuarios diferentes quieren calcular el interes usando tipos diferentes de argumentos.
Algunos usuarios quieren indicar una tasa de interes de 4 % usando 0.04; otros podran usar 4 y
suponer que significa 4 %. Si el metodo es llamado usando 1000.00 y 4, el metodo trabaja porque el
argumento entero es promovido a un double, pero el interes es calculado incorrecto como 4000.00,
en vez de 40.00.
Una solucion a lo anterior es sobrecargar el metodo calculaInteres(). Por ejemplo, ademas del
metodo mostrado en el codigo 8, se podra agregar el metodo mostrado en el codigo 9.
Si una aplicacion llama al metodo calculaInteres() usando dos argumentos double, por ejem-
plo, calculaInteres(1000.00 0.04)la primera version del metodo, el mostrado en el codigo
8, se ejecuta. Sin embargo, si un entero es usado como el segundo argumento en una llamada a
calculaInteres()como en calculaInteres(1000.00, 4)la segunda version del metodo, la
mostrada en el codigo 9, se ejecuta. En el segundo ejemplo, la tasa es dividida por 100.0 antes de
ser usada para determinar el interes ganado.
Por supuesto, se podra usar metodos con diferentes nombres para resolver el dilema de calcular
correctamente el interes. Sin embargo, es mas facil y mas conveniente para los programadores que
usan los metodos, recordar solo el nombre de un metodo que pueden usar en la forma que es
mas apropiada para sus programas. Es mas conveniente permitir usar un nombre razonable para
las tareas que son funcionalmente identicas excepto para los tipos de argumentos que pueden ser
pasados a estos.
6
Actividad 4. Escribir una aplicacion que contenga los metodos de los codigos 8 y 9, as como
llamadas a estos metodos como se indica previamente, para comprobar que el calculo se hace
correctamente.
Java convierte las variables para unificar el tipo cuando se realizan operaciones aritmeticas con
tipos diferentes. En forma similar Java tambien promueve un tipo de datos a otro cuando se pasa a
un metodo. Por ejemplo, si un metodo tiene un parametro double y se le pasa un entero, el entero
es promovido a un double. El orden de promocion es double, float, long, e int. Cualquier tipo
en la lista puede ser promovido a cualquier tipo que le precede.
Si una aplicacion tiene solo una version de un metodo, se puede llamar al metodo usando parametro
del tipo de dato correcto o uno que pueda ser promovido al tipo de dato correcto. Considerar el
metodo simple mostrado, codigo 10, de la aplicacion donde se declara valorDouble como una
variable double y un valorInt como una variable int, luego se hace llamada a metodoSimple()
con estos argumentos, y el resultado es Metodo recibe parametro doble en ambos casos. Cuando
se llama al metodo con un argumento entero, el entero es moldeado como (o promovido a) un
double.
1 public c l a s s LlamadaSimple {
2 public s t a t i c void main ( S t r i n g [ ] a r g s ) {
3 double v a l o r D o u b l e = 1 2 . 3 4 5 ;
4 int v a l o r I n t = 6 7 8 ;
5 metodoSimple ( v a l o r D o u b l e ) ;
6 metodoSimple ( v a l o r I n t ) ;
7 }
8 public s t a t i c void metodoSimple ( double d ) {
9 System . out . p r i n t l n ( Metodo r e c i b e parametro d o b l e ) ;
10 }
11 }
Actividad 5. Ejecutar la aplicacion LlamadaSimple, codigo 10, para comprobar lo que se indica
previamente.
Nota. Si no existiera el metodo con la declaracion void metodoSimple( double d ), pero existiera
la declaracion void metodoSimple( int i ), entonces la llamada al metodo metodoSimple(
valorDouble ); fallara. Un int puede ser promovido a un double, pero un double no puede
convertirse a un int.
7
1 public c l a s s DosMetodosSimples {
2 public s t a t i c void main ( S t r i n g [ ] a r g s ) {
3 double v a l o r D o u b l e = 1 2 . 3 4 5 ;
4 int v a l o r I n t = 6 7 8 ;
5 metodoSimple ( v a l o r D o u b l e ) ;
6 metodoSimple ( v a l o r I n t ) ;
7 }
8 public s t a t i c void metodoSimple ( double d ) {
9 System . out . p r i n t l n ( Metodo r e c i b e parametro d o b l e ) ;
10 }
11 public s t a t i c void metodoSimple ( int d ) {
12 System . out . p r i n t l n ( Metodo r e c i b e parametro i n t ) ;
13 }
14 }
Actividad 7. Escribir una aplicacion que sobrecargue un metodo que muestre fechas. El metodo
debe ser capaz de mostrar las fechas cuando se pasa solo el mes, con el da y el mes, y con el da, mes
y ano. Los argumentos pasados al metodo son de tipo entero. Para las llamadas al metodo cuando
la fecha no este completa, considerar 2016 como el ano por defecto, y a falta de da considerar el
primer da del mes.
3. Ambiguedad
Cuando se sobrecargan metodos, se corre el riesgo de crear una situacion ambiguauna en la cual
el compilador no puede determinar que situacion usar.
Estos metodos tienen diferentes tipos en sus listas de parametros. Una llamada a calculaInteres()
con un argumento int y un double (en ese orden) ejecutan la primera version del metodo, y
una llamada con un double y un int ejecuta la segunda version del metodo. En ambos casos el
8
compilador puede encontrar un apareamiento exacto para los argumentos mandados. Si se llama
usando dos argumentos enteros, surge una situacion ambigua porque no hay apareamiento exacto
para el metodo que se llama. Los enteros en la llamada al metodo pueden promoverse a un int y a
un double para aparear la primera version, o a un double y un int para aparear la segunda version,
por lo cual el compilador no sabe cual version del metodo calculaInteres usar, y programa no
compila.
Las dos versiones de calculaInteres() podran coexistir si nunca se hicieran llamadas ambiguas.
Un metodo sobrecargado no es ambiguo por s mismose hace ambiguo si se crea una situacion
ambigua.
Metodos con nombres identicos que tienen listas de parametros identicas pero con diferente tipo
devuelto no estan sobrecargadosson ilegales. Los siguientes dos metodos son ilegales en la misma
clase.
int unMetodo(int x)
void unMetodo(int x)
Nota. El compilador determinar cual version de un metodo llamara mediante la firma del metodo.
La firma del metodo es la combinacion del nombre del metodo y la cantidad, tipos y orden de los
parametros.
Java da automaticamente un constructor cuando se crea una clase que no tiene su propio cons-
tructor. Se escribe un constructor cuando se quiere asegurar que los campos esten inicializados con
algun valor por defecto apropiado. El constructor dado automaticamente es un constructor por
defecto, no requiere argumentos, pero se puede escribir un constructor por defecto configurado.
Cuando se escriben constructores propios se pueden escribir versiones para recibir parametros, que
frecuentemente son empleados para inicializar campos de datos.
Considerar la clase Empleado con solo un campo de datos, codigo 12. Su constructor asigna 999 a
numEmp a cada objeto Empleado instanciado. Cada vez que un objeto Empleado es creado usando una
sentencia como Empleado trabajadorHoras = new Empleado();, si no se usa algun metodo de
asignacion, se asegura que trabajadorHoras, al igual que todos los objetos Empleado, se inicializa
numEmp a 999.
1 public c l a s s Empleado {
2 private int numEmp ;
3 Empleado ( ) {
4 numEmp = 9 9 9 ;
5 }
6 }
Codigo 12: La clase Empleado con un constructor por defecto que inicializa el campo numEmp.
Alternativamente, se podra escoger crear objetos Empleado con valores iniciales para numEmp que
sean diferentes para cada objeto. Para realizar esto se puede pasar al constructor el numero deseado
9
para el empleado. El codigo 13 muestra la clase Empleado que contiene un constructor que recibe un
parametro. Con este constructor, un argumento es pasado usando una sentencia como la siguiente:
1 public c l a s s Empleado {
2 private int numEmp ;
3 Empleado ( int num) {
4 numEmp = num ;
5 }
6 }
Cuando se crea una clase Empleado con un constructor como el del codigo 13, para poder crear
un objeto de esta clase el uso del constructor debera tener un argumento entero. Por lo tanto, la
siguiente sentencia no funciona:
Sobrecarga constructor
Al igual que cualquier metodo, se puede sobrecargar el constructor. Con la sobrecarga se permiten
formas para crear objetos con diferentes argumentos de inicializacion, o ninguno, segun se requiera.
El codigo 14 muestra la clase Empleado que contiene dos constructores. Cuando se usa esta clase para
crear un objeto Empleado se tiene la opcion de crearlo recibiendo un valor inicial con el constructor
por defecto, Empleado otroTrabajador = new Empleado();, o bien con un numero particular
usando el constructor con un argumento, Empleado otroTrabajador = new Empleado(4567);.
1 public c l a s s Empleado {
2 private int numEmp ;
3 Empleado ( ) {
4 numEmp = 9 9 9 ;
5 }
6 Empleado ( int num) {
7 numEmp = num ;
8 }
9 }
Se ha mostrado como emplear los constructores para inicilizar valores de campos, pero pueden
tambien usarse argumentos para cualquier otro proposito.
Actividad 8. Disenar la clase PolizaAseguramientoAuto la cual tendra tres campos para el nume-
10
ro de la poliza, la cantidad de pagos que hara el cliente en el ano, y la ciudad de residencia del cliente.
Sobrecargar el constructor para que pueda aceptar tres argumentos (numero de poliza, pagos, ciu-
dad), dos argumentos (numero de poliza, pagos), y un argumento (numero de poliza). Incluir en
esta clase un metodo que muestre en la salida estandar la informacion de los valores de los campos.
Tambien escribir una aplicacion que muestre la creacion de tres objetos PolizaAseguramientoAuto
usando cada uno de los constructores, ademas mostrar cada uno de los objetos.
5. Referencia this
Cuando se instancia un objeto de una clase, memoria es reservada para cada campo de instancia de
la clase. Cada instanciacion de una clase tiene sus propios campos de datos. Cuando se quiere que
cada objeto comparta un valor, se define el campo como static; un campo no es static cuando
el valor en cada campo debe ser unico. Cuando se crea un metodo para una clase, cualquier objeto
puede usar el mismo metodo. Si el metodo hace un calculo, pone un valor al campo, o construye
un objeto, las instrucciones son las mismas para cada objeto instanciado.
Cuando se usa un metodo no estatico, se usa el nombre del objeto, un punto, y el nombre del
metodo, por ejemplo, unTrabajador.getNumEmp(); o otroTrabajador.getNumEmp();. Cuando
se ejecuta el metodo getNumEmp(), se ejecuta la unica copia del metodo. Sin embargo, dentro del
metodo getNumEmp(), cuando se accesa el campo numEmp, se accesa un campo diferente dependiendo
del objeto. El compilador debera determinar cual copia del valor numEmp debera ser regresado por
el metodo.
El compilador accesa el campo del objeto corrrecto porque cada vez que se llama al metodo no
estatico, implcitamente se pasa una referencia al objeto nombrado puesto con la llamada del
metodo. Una referencia es una direccion de memoria del objeto. La referencia esta implcita
porque se entiende automaticamente sin estar actualmente escrita. La referencia a un objeto que
es pasado a cualquier metodo no estatico de un objeto es llamada la referencia this; this es una
palabra reservada en Java. Solo metodos de instancia tienen una referencia this. Los dos metodos
getNumEmp() para la clase Empleado, codigo 15, trabajan igual. El primer metodo usar la referencia
this sin estar consciente de ello; el segundo metodo usa la referencia this explcitamente. Ambos
metodos regresan el numEmp del objeto usado para llamar al metodo.
Codigo 15: Dos versiones identicas del metodo getNumEmp, con y sin una referencia explcita this.
En algunas ocasiones se debera usar la referencia this para que la clase pueda trabajar correcta-
mente. En la clase Estudiante, codigo 16, el constructor tiene nombres de parametros identicos
a los nombres de los campos de clase. Dentro del constructor, numEst y promedio son nombres
11
declarados localmente, no los nombres de los campos de clase. La sentencia numeEst = numEst; no
realiza nadaasigna el valor de la variable local a s misma. La aplicacion cliente UsaEstudiante,
codigo 17, intenta crear un objeto Estudiante con el numero 1234 y un promedio de 9.5.
1 public c l a s s E s t u d i a n t e {
2 private int numEst ;
3 private double promedio ;
4 E s t u d i a n t e ( int numEst , double promedio ) {
5 numEst = numEst ;
6 promedio = promedio ;
7 }
8 public void m o s t r a r E s t u d i a n t e ( ) {
9 System . out . p r i n t l n ( E s t u d i a n t e # + numEst +
10 con promedio + promedio ) ;
11 }
12 }
1 public c l a s s U s a E s t u d i a n t e {
2 public s t a t i c void main ( S t r i n g [ ] a r g s ) {
3 E s t u d i a n t e unFisMat = new E s t u d i a n t e ( 1 2 3 4 , 9 . 5 ) ;
4 unFisMat . m o s t r a r E s t u d i a n t e ( ) ;
5 }
6 }
Una forma de resolver el problema con la clase Estudiante es usando identificadores diferentes
para los campos de la clase y los parametros del constructor. Pero en ocasiones los identificadores
que se han escogido son los mejores y mas simples para un valor. Si se escoge usar los mismos
identificadores, se puede usar la referencia this explcitamente para identificar los campos. La
clase Estudiante2, codigo 18, muestra la forma de usar la referencia this con el nombre del
campo en el constructor, para que la referencia se haga al campo de la clase en vez de la variable
local declarada en el metodo.
12
1 public c l a s s E s t u d i a n t e 2 {
2 private int numEst ;
3 private double promedio ;
4 E s t u d i a n t e 2 ( int numEst , double promedio ) {
5 t h i s . numEst = numEst ;
6 t h i s . promedio = promedio ;
7 }
8 public void m o s t r a r E s t u d i a n t e ( ) {
9 System . out . p r i n t l n ( E s t u d i a n t e # + numEst +
10 con promedio + promedio ) ;
11 }
12 }
Codigo 18: La clase Estudiante2 usando la referencia explcita this dentro del constructor.
Actividad 10. Escribir una aplicacion que cree un objeto del tipo Estudiante2 mediante el cons-
tructor de dos parametros y muestre el objeto creado
En la clase Estudiante3, codigo 19, tiene campos de datos para el numero de estudiante y el
promedio. Se han escrito cuatro constructores sobrecargados con el siguiente funcionamiento res-
pectivamente:
Constructor que acepta un double para asignarlo al promedio, pero inicializa cada numero
de estudiante a 999.
Constructor que acepta un int y lo asigna al numero de estudiante, pero inicializa el promedio
de cada estudiante a 0.0.
Constructor por defecto que asigna 999 a cada numero de estudiante y 0.0 a cada promedio.
La clase Estudiante3 funciona y permite instanciar en cuatro diferentes formas, pero hay varias
repeticiones en los constructores.
13
1 public c l a s s E s t u d i a n t e 3 {
2 private int numEst ;
3 private double promedio ;
4 E s t u d i a n t e 3 ( int num , double prom ) {
5 numEst = num ;
6 promedio = prom ;
7 }
8 E s t u d i a n t e 3 ( double prom ) {
9 numEst = 9 9 9 ;
10 promedio = prom ;
11 }
12 E s t u d i a n t e 3 ( int num ) {
13 numEst = num ;
14 promedio = 0 . 0 ;
15 }
16 Estudiante3 ( ) {
17 numEst = 9 9 9 ;
18 promedio = 0 . 0 ;
19 }
20 }
Se puede reducir la cantidad de codigo repetido de la clase Estudiante3 para hacer el codigo menos
propenso a errores llamando a una version del constructor (el mas general) desde los otros (los mas
particulares). Para hacerlo se tiene que usar la referencia this en los constructores mas particulares
para llamar al constructor mas general. La clase Estudiante4, codigo 20, muestra como otra version
de la clase Estudiante3 se puede reescribir.
1 public c l a s s E s t u d i a n t e 4 {
2 private int numEst ;
3 private double promedio ;
4 E s t u d i a n t e 4 ( int num , double prom ) {
5 numEst = num ;
6 promedio = prom ;
7 }
8 E s t u d i a n t e 4 ( double prom ) {
9 t h i s ( 9 9 9 , prom ) ;
10 }
11 E s t u d i a n t e 4 ( int num ) {
12 t h i s (num , 0 . 0 ) ;
13 }
14 Estudiante4 ( ) {
15 this (999 , 0 . 0 ) ;
16 }
17 }
Codigo 20: La clase Estudiante4 usando this en tres de sus cuatro constructores.
Se puede usar la referencia this con nombres de campos en cualquier metodo dentro de una clase,
sin embargo no se se puede llamar this() desde otros metodos en una clase; solo se puede llamar
desde constructores y debe ser la primera sentencia en el constructor.
14
Actividad 11. Crear una aplicacion que muestre el uso de cada uno de los constructores de la
clase Estudiante3, ademas agregar un metodo que muestre la informacion de los campos de la
clase. Repetir la actividad pero creando objetos de la clase Estudiante4 .
6. Campos static
Los metodos que se crean para ser usados sin objetos son static. La mayora de los metodos
creados dentro de una clase de la cual objetos seran instanciados son no estaticos. Los metodos
static no tienen una referencia this porque no hay objeto asociado con ellos; por lo que son
llamados metodos de clase.
Se pueden crear variables de clase, que son variables que son compartidas por cada instan-
ciacion de una clase. Las variables de instancia en una clase existen separadamente para cada
objeto creado, mientras que solo hay una copia de cada variable de clase static por clase. La clase
JugadorBeisbol, codigo 21, contiene un campo static llamado contador, y dos campos no estati-
cos llamados numero y promedioBateo. El constructor JugadorBeisbol pone valores a numero y
promedioBateo e incrementa contador en uno, es decir, cada vez que un objeto JugadorBeisbol es
construido, este contiene valores individuales para numero y promedioBateo, y el campo contador
tiene la cantidad de objetos existentes y es compartido por todos los objetos JugadorBeisbol.
1 public c l a s s J u g a d o r B e i s b o l {
2 private s t a t i c int c o n t a d o r = 0 ;
3 private int numero ;
4 private double promedioBateo ;
5 J u g a d o r B e i s b o l ( int id , double prom ) {
6 numero = i d ;
7 promedioBateo = prom ;
8 contador = contador + 1 ;
9 }
10 public void mostrarJugador ( ) {
11 System . out . p r i n t l n ( Jugador # + numero +
12 promedio de b a t e o e s + promedioBateo +
13 Hay + c o n t a d o r + j u g a d o r e s ) ;
14 }
15 }
La clase UsaJugador, codigo 22, es una aplicacion que declara dos objetos JugadorBeisbol, los
muestra, y luego crea un tercer objeto JugadorBeisbol y lo muestra, y finalmente muestra nueva-
mente el primer objeto creado.
15
1 public c l a s s UsaJugador {
2 public s t a t i c void main ( S t r i n g [ ] a r g s ) {
3 J u g a d o r B e i s b o l unCatcher = new J u g a d o r B e i s b o l ( 1 2 , 0 . 2 1 8 ) ;
4 J u g a d o r B e i s b o l u n S h o r t s t o p = new J u g a d o r B e i s b o l ( 3 1 , 0 . 3 8 5 ) ;
5 unCatcher . mostrarJugador ( ) ;
6 u n S h o r t s t o p . mostrarJugador ( ) ;
7 J u g a d o r B e i s b o l u n O u t f i e l d e r = new J u g a d o r B e i s b o l ( 4 4 , 0 . 5 0 5 ) ;
8 u n O u t f i e l d e r . mostrarJugador ( ) ;
9 unCatcher . mostrarJugador ( ) ;
10 }
11 }
Campos constantes
Para crear constantes con nombre se usa la palabra reservada final. En algunos casos un campo de
datos en una clase debera ser constante. Por ejemplo, se quedra guardar un valor identificador de
escuela que es el mismo para cada objeto Estudiante5 que sea creado, as que debera ser declarado
static. Ademas, si se quiere que el valor para el identificador ID sea fijo o inmutable para que
todos los objetos Estudiante5 usen el mismo valor de identificador, al igual que con las variables,
se usa la palabra reservada final. La clase Estudiante5, codigo 23, contiene la constante simbolica
ID ESCUELA.
1 public c l a s s E s t u d i a n t e 5 {
2 private s t a t i c f i n a l int ID ESCUELA = 1 2 3 4 5 ;
3 private int numEst ;
4 private double promedio ;
5 E s t u d i a n t e 5 ( int numEst , double promedio ) {
6 t h i s . numEst = numEst ;
7 t h i s . promedio = promedio ;
8 }
9 public void m o s t r a r E s t u d i a n t e 5 ( ) {
10 System . out . p r i n t l n ( E s t u d i a n t e # + numEst +
11 con promedio + promedio ) ;
12 }
13 }
Un valor de un campo final no estatico puede ser puesto en el constructor de la clase. Un valor de
un campo final static debera ser puesto en la declaracion, como en la clase Estudiante5. Tiene
sentido porque solo hay un campo static guardado para todos los objetos instanciados.
Nota. Se puede usar la palabra reservada final con metodos o clases al igual que con campos.
Cuando se usa de esta forma, final indica limitaciones puestas a la herencia.
16
Los campos declarados como static no son siempre final. A la inversa, campos final no son
siempre static, En resumen:
Si se quiere crear un campo para que todas las instanciaciones de la clase lo puedan acceder
y modificar, entonces sera static pero no final.
Si se quiere que cada objeto creado de una clase contenga su propio valor final, se podra
declarar el campo para ser final pero no static.
Si se quiere que todos los objetos compartan un solo valor inmutable, entonces el campo es
static y final.
Actividad 13. Crear una clase para el registro de un evento anual de triatlon para perros. La clase
contiene un campo final que guarda la cantidad de eventos en el que cada perro ha participado.
La clase tambien contiene otro campo static que guarda el puntaje acumulado para todos los
perros participantes. Considerar seis campos mas para el nombre del perro, el puntaje para tres
calificaciones (agilidad, obediencia y porte), el puntaje total y el promedio. El constructor de la
clase requiere cinco parametrosnombre del perro, numero de eventos en los cuales ha participado
el perro, los puntajes de las tres calificaciones. Despues de las asignaciones de los parametros a
los campos correspondientes, el constructor calcula el puntaje total y el promedio de cada perro.
Tambien se debe agregar el puntaje total al puntaje acumulado de todos los perros. Incluir un
metodo que muestre los cados de cada participante en triatlon. Escribir una aplicacion que muestre
el uso de la clase descrita previamente, para al menos 3 perros.
Los creadores de Java han hecho cientos de clases que se pueden usar en los programas. Esta es
una ventaja que tiene Java porque para muchas tareas ya existe una clase con ese proposito.
Cada clase esta guardada en un paquete, o una biblioteca de clases, el cual es una carpeta que
da un agrupamiento conveniente para las clases. Muchos paquetes Java estan disponibles solo si
explcitamente se nombran dentro del programa; por ejemplo, para usar JOptionPane, primero se
debe importar el paquete javax.swing en el programa. El paquete java.lang es implcitamente
importado en cada programa Java. Las clases que contiene el paquete son las clases fundamenta-
les, o clases basicas, contrarias a las clases opcionales que deben ser nombradas explcitamente.
La clase java.lang.Math contiene constantes y metodos que se puedan usar para realizar funciones
matematicas comunes. Todas las constantes y los metodos en la clase Math son staticson varia-
bles de clase y metodos de clase. Por ejemplo la constante que es usada en geometra esta incluida
como una aproximacion del radio de la circunferencia del crculo a su diametro. La declaracion para
PI en la clase Math es la siguiente:
17
public, as cualquier programa puede accederla directamente
final, as no puede ser cambiada
static, as solo una copia existe y se puede acceder esta sin declarar un objeto Math
double, as puede guardar un valor de punto flotante de doble precision
Se puede usar el valor de PI dentro de cualquier programa escribiendo el camino completo del
paquete donde PI esta definido; por ejemplo, para calcular el area de un crculo usando la siguiente
sentencia:
Como el paquete java.lang es importado automaticamente en los programas, basta con una re-
ferencia simple Math.PI, ya que Java la completa con el paquete importado automaticamente.
Entonces, la sentencia preferida y mas simple es:
Ademas de constantes, muchos metodos utiles estan disponibles en la clase Math. El cuadro 1
muestra algunos metodos comunes de la clase Math.
Como todas las constantes y metodos en la clase Math son de clase (static), no se requiere crear
una instancia de la clase Math. No se pueden instanciar objetos de tipo Math porque el constructor
de la clase Math es private.
18
Importar clases explcitamente
Para usar otras clases que no estan en el paquete java.lang, se debe hacer de alguna de las
siguientes formas:
En algunos ejemplos previos que se han revisado se han usado las clases JOptionPane y Scanner
que fueron importadas para usar sus metodos.
De acuerdo a lo mencionado previamente, se puede instanciar un objeto del tipo Scanner usando
la ruta completa de la clase, como sigue:
Tambien se puede instanciar el objeto de tipo Scanner, como se ha visto en los ejemplos previos,
incluyendo
import java.util.Scanner;
como la primera lnea en el programa, para entonces al usar la clase Scanner se abrevie as:
La ultima forma para importar la clase es importar el paquete entero de clases. Se usa el asterisco
() como smbolo comodn, para indicar que este reemplaza cualquier conjunto de caracteres. La
sentencia con import se escribe entonces como:
import java.util.*;
8. Agrupamiento de clases
Hay dos formas para agrupar clases, usando composicion y anidando clases. En esta seccion se da
una breve descripcion de ambos conceptos.
19
Composicion
Los campos en una clase pueden ser datos simples como int o double, pero tambien pueden ser
tipos de clase. La composicion describe la relacion entre clases cuando un objeto de una clase es
un campo de datos dentro de otra clase, como cuando se usan campos de objeto String.
Cuando se usa un objeto como un miembro de datos de otro objeto, se deberan proporcionar valores
para el objeto contenido si no tiene constructor por defecto. La clase NombreDireccion, codigo 24,
guarda informacion el nombre y la direccion. Esta clase puede ser usada para otras clases como
empleados, clientes, estudiantes y cualquiera que requiera esta informacion. La clase contiene tres
campos, todos ellos son puestos por el constructor.
1 public c l a s s NombreDireccion {
2 private S t r i n g nombre ;
3 private S t r i n g d i r e c c i o n ;
4 private int c o d i g o P o s t a l ;
5 NombreDireccion ( S t r i n g nom , S t r i n g d i r , int cp ) {
6 nombre = nom ;
7 direccion = dir ;
8 c o d i g o P o s t a l = cp ;
9 }
10 public void m o s t r a r ( ) {
11 System . out . p r i n t l n ( nombre ) ;
12 System . out . p r i n t l n ( d i r e c c i o n ) ;
13 System . out . p r i n t l n ( c o d i g o P o s t a l ) ;
14 }
15 }
Para el diseno de la clase Escuela, codigo 25, se quiere guardar informacion de esta. En vez de
declarar campos para el nombre y la direccion, se usa la clase NombreDireccion. La relacion creada
es llamada tiene-una relacion porque una clase tiene una instancia de otra.
1 public c l a s s E s c u e l a {
2 private NombreDireccion nomDir ;
3 private int i n s c r i p c i o n ;
4 public E s c u e l a ( S t r i n g nom , S t r i n g d i r , int cp , int i n s c r ) {
5 nomDir = new NombreDireccion (nom , d i r , cp ) ;
6 inscripcion = inscr ;
7 }
8 public void m o s t r a r ( ) {
9 System . out . p r i n t l n ( I n f o r m a c i on de l a e s c u e l a : ) ;
10 nomDir . m o s t r a r ( ) ;
11 System . out . p r i n t l n ( I n s c r i p c i on e s + i n s c r i p c i o n ) ;
12 }
13 }
Como se muestra en el codigo 25, el constructor Escuela requiere cuatro parametros. Dentro del
constructor, tres de los parametrosel nombre, la direccion, y el codigo postalson pasados al
20
constructor NombreDireccion para dar valores a los campos apropiados. El cuarto parametro del
constructor es asignado al campo inscripcion de la clase Escuela.
1 public c l a s s UsaEscuela {
2 public s t a t i c void main ( S t r i n g [ ] a r g s ) {
3 E s c u e l a mi Escuel a = new E s c u e l a
4 ( P a t i t o Cuac Cuac , Fantasa 1234 , 5 8 0 0 0 , 2 3 5 ) ;
5 miEs cuela . m o s t r a r ( ) ;
6 }
7 }
Clases anidadas
En Java se puede crear una clase dentro de otra clase y guardarlas juntas; tales clases son las clases
anidadas. La clase contenedora es la clase nivel superior. Hay cuatro tipos de clases anidadas:
Clases miembro static. Esta clase tiene acceso a todos los metodos estaticos de la clase
nivel superior.
Clases miembro no estaticas, tambien conocidas como clases internas. Este tipo de
clases requiere una instancia y tiene acceso a todos los datos y metodos de la clase nivel
superior.
La razon mas comun para anidar una clase dentro de otra es porque la clase interna es usada
solamente por la clase nivel superior, es decir, es una clase auxiliar a la clase nivel superior.
La clase ListaInmueble describe casas que estan disponibles a la venta. La clase podra contener
campos separados para el numero, el precio, la direccion y la superficie. Como una alternativa, se
podra decidir que el numero y el precio vayan con el inmueble, y que la direccion y la superficie
vayan con la casa, as que se podra crear una clase interna como la que se muestra en el codigo
27.
21
1 public c l a s s L i s t a I n m u e b l e {
2 private int numeroLista ;
3 private double p r e c i o ;
4 private DatosCasa datosCasa ;
5 public L i s t a I n m u e b l e ( int num , int p r e c i o , S t r i n g d i r e c c i o n , int s u p e r f i c i e ) {
6 numeroLista = num ;
7 this . p r e ci o = p r e c i o ;
8 datosCasa = new DatosCasa ( d i r e c c i o n , mCuad ) ;
9 }
10 public void m o s t r a r ( ) {
11 System . out . p r i n t l n ( L i s t a n d o # + numeroLista +
12 p r e c i o de venta $ + p r e c i o ) ;
13 System . out . p r i n t l n ( D i r e c c i on : + datosCasa . d i r e c c i o n ) ;
14 System . out . p r i n t l n ( datosCasa . s u p e r f i c i e + m2 ) ;
15 }
16 private c l a s s DatosCasa {
17 private S t r i n g d i r e c c i o n ;
18 private int s u p e r f i c i e ;
19 public DatosCasa ( S t r i n g d i r e c c i o n , int s u p e r f i c i e ) {
20 this . d i r e c c i o n = d i r e c c i o n ;
21 this . s u p e r f i c i e = s u p e r f i c i e ;
22 }
23 }
24 }
22