Está en la página 1de 528

UNIVERSIDAD AUTONOMA DE SINALOA

FACULTAD DE INFORMÁTICA DE MAZATLAN

PROGRAMACIÓN I
(Lenguaje JAVA)
TITULAR DE LA MATERIA:
DR. JOSÉ NICOLÁS ZARAGOZA GONZÁLEZ
INTRODUCCION AL LENGUAJE JAVA.
Conceptos Básicos.
El lenguaje Java nace en 1991 en Sun Microsystems Inc.
Es un lenguaje derivado de C y C++.
Fue creado por James Gosling, Patrick Naughton, Chris Warth, Ed Frank y
Mike Sheridan.
Originalmente se llamó “Oak”, en 1995 cambió su nombre a Java.
La intención era crear un lenguaje de programación para desarrollar
software para diversos dispositivos electrónicos como hornos de
microondas y controles remotos, se buscaba un lenguaje de programación
que fuera independiente de la plataforma y que se pudiese ejecutar en
distintos tipos de CPUs bajo diferentes entornos.
Actualmente, una de las principales aplicaciones de Java es en Internet, ya
que un programa en java puede “correrse”, independientemente del sistema
operativo o del navegador.
La primera versión comercial de Java se lanzó en 1997 y se denominó JDK
1.1. En diciembre de 1998 Sun lanzó la plataforma Java 2, la cual se
conoció originalmente como JDK 1.2.
La principal característica de Java es el byte-code (o código de bytes), esto
significa que el código fuente Java se "compila" a un código de bytes de alto
nivel independiente de la máquina. Este código, llamado bytecode, está
diseñado para ser interpretado y ejecutarse en una máquina hipotética,
llamada Máquina Virtual de Java o JVM (Java Virtual Machine).
Para desarrollar programas en Java, es necesario contar con un entorno de
desarrollo, el más común es el Java Development Kit (JDK).

Programa en Java

Máquina Virtual Java

Sistema Operativo

Computadora
Las características principales que nos ofrece Java con respecto a
cualquier otro lenguaje de programación, son:
a) Sencillo.
b) Orientado a objetos.
c) Distribuido.
d) Robusto.
e) Arquitectura neutra.
f) Seguro.
g) Portable.
h) Multihilo.
i) Interpretado.
j) Dinamico
El entorno de desarrollo JAVA.

El entorno habitual para desarrollar programas en Java consiste en un


navegador que pueda ejecutar applets, un compilador que convierta el
código fuente Java a bytecode y el intérprete Java para ejecutar los
programas.
También se necesita un editor para escribir el código fuente, y aunque no
son estrictamente necesarias otras herramientas como el debugger, un
entorno visual, la documentación o un visualizador de jerarquía de clases,
es conveniente contar con todas o algunas de ellas cuando se trata de
desarrollar proyectos de aplicaciones.
Actualmente hay entornos completos de desarrollo integrados para Java
diferentes del JDK, que hasta el momento es el entorno básico de Java que
proporciona Sun.
Está formado por herramientas en modo texto, que son:
java, intérprete que ejecuta programas en bytecode.
javac, compilador de Java que convierte el código fuente en bytecode.
javah, crea archivos de cabecera para implementar métodos para cualquier
clase.
javap, es un descompilador de bytecode a código fuente Java.
javadoc, es un generador automático de documentos HTML a partir del
código fuente Java.
Para más información, o descargar una versión actualizada de Java, puede
hacerlo en la siguiente dirección:

http://www.oracle.com/technetwork/java/javase/downloads/
index.html
jGRASP

Debido al nivel básico de programación que trabajaremos (aplicaciones),


nosotros utilizaremos el el jGRASP, entorno de programación Java
desarrollado por la Universidad de Auburn, de licencia libre y que permite el
desarrollo de aplicaciones (programas) y applets. Permite el desarrollo de
aplicaciones en C, C++, Java y ADA, pero cuenta con más opciones. En la
parte inferior tiene una ventana que muestra durante el proceso de
compilación, los errores encontrados durante la misma (ceja: Compile
Messages), si es que los hay. Al momento de “correr” el programa, la misma
ventana permite mostrar la ejecución de programa y en la cual se capturan
los datos y se muestran los resultados, ceja: (Run I/O).
En la parte superior cuenta con un menú de opciones que nos permite abrir,
cerrar, imprimir y guardar archivos; editar, copiar y pegar texto; compilar y
correr aplicaciones o applets, etcétera. Del lado izquierdo, tiene una
ventana que muestra el directorio de trabajo y cuenta con opciones para
depurar el programa. Esta versión puede obtenerse en la siguiente
dirección:
http://www.jgrasp.org/
Aplicaciones y applets.

Los programas en Java se dividen en dos tipos o categorías: aplicaciones y


applets.
Las aplicaciones son programas hechos en lenguajes de alto nivel y que
funcionan en una computadora bajo un sistema operativo. Un programa en
Java requiere de la Máquina Virtual de Java para ser ejecutado. Las
aplicaciones se usan para resolver diversos problemas y pueden agruparse
para formar sistemas, así, existen sistemas para inventarios, nómina,
control escolar, etcétera.
Un applet, es un programa diseñado para ser transmitido por Internet y
ejecutado en un navegador Web compatible con Java. Los applets tienen
algunas limitaciones ya que necesitan de ciertas condiciones de seguridad
para evitar daños en el sistema en el que está funcionando el navegador.
Creación de programas en Java.

Java es un lenguaje de alto nivel que permite realizar programas


transportables o portátiles.
La transportabilidad o portabilidad significa que es posible adaptar el
software escrito para un tipo de computadora en otra, por ejemplo, si un
programa escrito para una Apple Macintosh se puede llevar sin cambio a
una IBM PC, entonces el programa es transportable.
Como todos los programas, los programas en Java casi siempre pasan a
través de las siguientes fases para su ejecución:
a) Editar.
b) Compilar.
c) Enlazar.
d) Cargar.
e) Ejecutar.
Un programa compilado con éxito, puede ejecutarse por un intérprete tantas
veces como se desee sin necesidad de compilarse de nuevo. Un ejemplo
típico de un programa en Java es el siguiente:

/* Hola.java */

class Hola
{

public static void main (String args[ ])


{
System.out.println ("Hola!... Este es mi primer programa en Java");
}
}

Para entender la estructura del programa, primero debemos conocer lo


conceptos de la programación orientada a objetos (POO), lo cual veremos a
continuación.
PROGRAMACIÓN ORIENTADA A OBJETOS.

Conceptos Básicos.

La programación orientada a objetos (POO) es un estilo de


programación.
El elemento principal es el objeto.

Objeto.

Es un conjunto complejo de datos y programas que


poseen estructura y forman parte de una organización.
También podemos definirlo como una encapsulación de un
conjunto de datos y los métodos para manipularlos.
Los mecanismos básicos de la programación orientada a
objetos son:
a) Los objetos.

Un objeto es una encapsulación genérica de datos y de los procedimientos


para manipularlos. En tanto que los programas tradicionales
(estructurados y modulares) se componen de procedimientos y de datos.
Los programas orientados a objetos se componen exclusivamente de
objetos. Un objeto contiene operaciones (métodos) que definen su
comportamiento y variables (datos), manipuladas por esas operaciones,
las cuales definen el estado del objeto.

b) Los mensajes.

Los objetos reciben, interpretan y responden a mensajes de otros objetos.


El paso de mensajes entre objetos sustituye al flujo de control tradicional,
ya que los mensajes originan cambios en el estado del objeto. Cuando un
objeto recibe un mensaje, debe conocer perfectamente lo que tiene que
hacer, y cuando un objeto envía un mensaje, no necesita conocer cómo se
desarrolla, sino simplemente que se está desarrollando.
c) Los métodos.

Un método es un conjunto de instrucciones y equivalen a las funciones o


procedimientos de la programación estructurada y modular. Los métodos se
implementan dentro de una clase y determinan cómo debe actuar el objeto
cuando recibe un mensaje. Dentro de los métodos se pueden declarar y
usar variables que se conocen como variables asociadas o atributos, las
cuales permiten almacenar información para dicho objeto. Un método
también puede enviar mensajes a otros objetos solicitando una acción o
información.
La estructura más interna de un objeto está oculta para otros usuarios (esto
se conoce como encapsulamiento) y la única conexión que tiene con el
exterior son los mensajes. Los atributos (datos) que oculta un objeto,
solamente pueden ser manipulados por los métodos asociados al propio
objeto.
d) Las clases.

Una clase puede ser considerada como un formato o plantilla para crear
objetos, los cuales serán de esa clase o tipo.
Una clase describe los métodos y atributos que definen las características
comunes a todos los objetos de esa clase. De esta manera, la clave de la
programación orientada a objetos, consiste en abstraer (o visualizar de
forma muy general) los métodos y atributos comunes a un conjunto de
objetos y encapsularlos en una clase.

e) Las subclases.

Las subclases, son clases derivadas de una clase en particular.


objeto

atributos
mensajes
métodos
CARACTERÍSTICAS DE LA PROGRAMACIÓN
ORIENTADA A OBJETOS.

Las características fundamentales de la programación orientada a objetos


(POO) son:

1) Abstracción.
Abstraer significa: “separar mentalmente”. En programación, la abstracción
consiste en la generalización conceptual de los atributos y propiedades de
un determinado conjunto de objetos. De esta manera, la clave de la
programación orientada a objetos está en abstraer los métodos y los datos
comunes a un conjunto de objetos y almacenarlos en una clase.
2) Encapsulamiento.
Se refiere a la práctica de incluir dentro de un objeto todo lo que necesita,
de forma que ningún otro objeto pueda conocer nunca su estructura
interna.

3) Herencia.
La herencia es el mecanismo mediante el cual se comparten y derivan,
métodos y atributos entre clases y subclases.

Clase: Mobiliario Objeto: silla

Costo Costo
Dimensiones Dimensiones
Peso Peso
Localización Localización
Color Color
Objeto: sillón
Alta Alta
Baja Costo Baja
Consulta Dimensiones Consulta
Peso
Modificación Localización
Modificación
Color

Alta Los objetos heredan


Baja
Consulta
todos los atributos y
Modificación operaciones de la clase.
4) Polimorfismo.
Polimorfismo significa: “muchas formas”. En la programación orientada a
objetos, esta característica permite implementar múltiples formas de un
mismo método, dependiendo cada una de ellas, de la clase sobre la que
se realice la implementación. De esta manera se puede acceder a una
variedad de métodos distintos (todos con el mismo nombre) utilizando
exactamente el mismo medio de acceso.

objeto

atributos
métodos

mensajes

objeto mensajes objeto

atributos atributos
mensajes
métodos métodos
Estructura de un programa en Java.
<sentencia(s) import> Declaración para importar clases de paquetes.

[protección] class NombreClase


{

<Variables miembro de la clase (atributos)>

< [modificador] tipo_devuelto método1 ( Lista de parámetros )


{
Declaración de variables locales
Sentencias ejecutables
}

• • • Definición de métodos (operaciones) dentro de la clase.

[modificador] tipo_devuelto métodoN ( Lista de parámetros )


{
Declaración de variables locales
Sentencias ejecutables
} >

< public static void main ( String args [ ] ) Método principal.


{
Declaración de variables locales
Sentencias ejecutables
} >
}
1. Sentencias import.

Las clases en Java se agrupan en paquetes. Los paquetes se encuentran


en directorios de disco que tienen el mismo nombre que el paquete. Para
importar una clase de un paquete desde un programa se utiliza la sentencia
import. En un programa en Java, pueden aparecer cualquier número de
sentencias import, las cuales deben escribirse antes de cualquier definición
de clase.
La sintaxis general de la sentencia import es la siguiente:
import nombrePaquete.nombreClase;

Ejemplo:

import java.lang.System; Importa la clase System del paquete java.lang.

import java.io.*; Importa las clases que puedan ocuparse para


operaciones de entrada/salida del paquete
java.io.
2. Declaración de clases y nombre del programa.

Todo programa en Java está conformado por clases. Un programa debe


contener al menos una clase, la cual puede ser considerada como la clase
principal, puede contener el método main() e incluso otros métodos y
variables. Una clase es un tipo definido por el usuario que describe los
atributos y los métodos de los objetos que se crearán a partir de la misma.
La declaración de una clase puede empezar con una palabra clave que es
un modificador de protección que generalmente indica el acceso y es
opcional; a continuación sigue el indicador de clase, la palabra reservada
class; después sigue el nombre de la clase y los miembros de la clase:
variables y métodos; el convenio general entre los programadores para dar
nombre a las clases, es comenzar el nombre de la clase con una letra
mayúscula. El archivo en el cual se guarda el código debe tener
exactamente el mismo nombre de la clase, respetando mayúsculas y
minúsculas. Cada definición de una clase Java deberá estar en un archivo.
Protección de una clase.
La protección de una clase determina la relación que tiene con otras clases
de otros paquetes. Existen dos niveles de protección: de paquete y público.
Una clase con nivel de protección de paquete sólo puede ser utilizada por
las clases de su paquete. Esto se logra definiendo el tipo de acceso que
puede ser privado (private) o protegido (protected).
Un miembro declarado private es accesible solamente por los métodos de
su propia clase. Esto significa que no puede ser accedido por los métodos
de cualquier clase, incluidas las subclases. Un miembro declarado
protected se comporta exactamente igual que uno privado para los
métodos de cualquier otra clase, excepto para los métodos de las clases del
mismo paquete o de sus subclases, independientemente del paquete al que
pertenezcan, para las que se comporta como un miembro público.
Por otra parte, una clase pública puede ser utilizada por cualquier otra clase
de otro paquete. Así, un miembro declarado public está accesible para
cualquier otra clase o subclase que necesite utilizarlo.
Por omisión, una clase tiene el nivel de protección de paquete, cuando se
desee que una clase tenga protección pública, hay que calificarla como tal
utilizando la palabra reservada public. Así mismo, los atributos static de la
clase generalmente son declarados públicos.
3. Variables miembro de la clase (atributos).

Los miembros dato de una clase se definen como variables de instancia.


Estas variables pueden ser de cualquier tipo primitivo (int, char, byte, float,
double, etc.), arreglos, cadenas, etcétera. Toda variable debe ser definida
antes de ser utilizada. La definición de una variable, declara la variable y
además le asigna memoria. La sintaxis es la siguiente:
acceso nombreTipo nombreVariableInstancia;

acceso Puede ser public, protected, private; o bien, el acceso por


defecto o por omisión.
public Se puede acceder a la variable desde cualquier método.
protected Los métodos de la clase, los métodos de las clases del mismo
paquete pueden acceder a la variable y también los métodos
de las clases derivadas.
private Sólo los métodos de la clase pueden acceder a la variable.
por omisión Los métodos de la clase y los de las clases del mismo
paquete pueden acceder a la variable.
4. Definición de métodos (operaciones).
[ método1, método2, ..., métodoN ]

Un método es un conjunto de sentencias que ejecutan una tarea específica.


En Java, un método siempre pertenece a una clase y su definición nunca
puede contener la definición de otro método, esto significa que no se
pueden tener métodos anidados. Todos los métodos tienen nombre y una
lista de datos o valores que reciben, llamados parámetros o argumentos. La
definición de un método consta de dos partes: la cabecera y cuerpo del
método. La sintaxis para definir un método es la siguiente:

[modificador] tipo_devuelto método ( Lista de parámetros )


{
Declaración de variables locales
Sentencias ejecutables
return expresión; // No se escribe si el método es de tipo void.
}
modificador Es una palabra clave que especifica desde donde puede ser
llamado el método. Existen cuatro niveles de acceso: public,
protected, private o por omisión, que son los mismos
definidos en la declaración de variables.
tipo_devuelto Especifica el tipo de dato devuelto por el método. Éste puede
ser cualquier tipo primitivo o referenciado. Para indicar que
un método no devuelve nada se utiliza la palabra reservada
void, en este caso se omite la sentencia return o se escribe
sola, sin ninguna expresión.
método El nombre de un método puede ser cualquier identificador
válido, pero no puede ser una palabra reservada Java. Entre
los programadores se tiene el convenio de que la primera
letra del nombre del método se escribe con minúsculas. Un
método puede tener palabras reservadas asociadas como:
static, abstract y final.
Lista de parámetros La lista de parámetros de un método son las variables que
reciben los valores de los argumentos especificados cuando
se llama o invoca. Estos pueden ser: cero, uno o más
identificadores con sus tipos, separados por comas. Aunque
los identificadores sean del mismo tipo, cada uno debe ser
antecedido por su tipo.
5. Método main( ).

Todos los programas de aplicación de Java inician su ejecución llamando al


método main(). Esto significa que main() es el punto de entrada a la
aplicación, y también su punto de salida. Cada programa de aplicación en
Java tiene un método main() y solo uno, si tiene más de un main() se
produce un error, aunque estén en diferentes clases. Las clases de Java no
necesariamente deben tener un método main(), a menos que esa clase sea
el punto de comienzo del programa. El método main() se define de la
siguiente manera:

public static void main ( String args [ ] )


{
Declaración de variables locales
Sentencias ejecutables
}
Identificadores.
Un identificador es una secuencia de caracteres, letras, dígitos, el guión
bajo o subrayado y el símbolo $. El primer carácter debe ser una letra, un
símbolo de subrayado o el símbolo $. Los caracteres siguientes pueden ser
letras, números o símbolos de subrayado y no deben contener espacios en
blanco o caracteres especiales.
En un identificador, las letras minúsculas y las mayúsculas son
consideradas como diferentes, El nombre de un identificador no debe ser
igual que una palabra reservada.
Como recomendación para escribir identificadores tenemos:
1. Escribir identificadores de variables en letras minúsculas.
2. Nombres de constantes en mayúsculas.
3. Los nombres de métodos con tipo de letra mixto: mayúscula/minúscula.
4. Los identificadores de clases con el primer carácter en mayúsculas.
Palabras reservadas.
Una palabra reservada no puede ser usada como nombre de identificador,
clase, objeto o método. Todas las palabras reservadas están en minúsculas
y deben escribirse tal como se indican. A continuación se presenta la lista
de palabras reservadas:
abstract extends long switch
boolean false native synchronized
break final new this
byte finally null throw
byvalue float operator throws
case for outer transient
cast future package true
catch generic private try
char goto protected var
class if public void
const implements return volatile
continue import rest while
default inner short widefp
do instanceof static
double int strictfp
else interface super
Líneas de programa.

En Java se utiliza el carácter de punto y coma (;) para indicar el fin de una
sentencia. Se pueden colocar varias sentencias en una línea siempre y
cuando se separen con puntos y comas. Así mismo, un bloque es un
conjunto de sentencias con un punto y coma después de cada una de ellas
y van encerradas entre llaves { }.

Comentarios.

Un comentario es un texto que explica una instrucción o una función, se


sitúa en cualquier parte del programa y es ignorado por el compilador. Estos
comentarios pueden ser tan largos como se desee y son una parte
importante de la documentación de un programa, ya que ayudan al
programador y a otras personas a la comprensión del mismo.
Formato:
Comentario tradicional, para más de una línea /* comentario */
Comentario de una sola línea // comentario
TIPOS DE DATOS.

Todos los datos tienen un tipo asociado con ellos. El tipo de un dato
determina el conjunto de valores que puede tomar una variable tomando
en cuenta la representación interna de los números o el espacio de
memoria ocupado por una variable de un tipo dado. La unidad de medida
de la capacidad de memoria es el byte (octeto); un byte se compone de
ocho dígitos binarios (bits) que pueden tomar cada uno el valor 0 ó 1.

Clasificación de los tipos de datos:

En Java, los tipos de datos básicos o primitivos son:

A) Enteros.
B) Reales.
C) Caracteres.
D) Lógicos o Booleanos.
A) Tipos Enteros.
Los tipos enteros de datos son:

a) byte. (octeto - 1 byte).

El tipo byte es utilizado para almacenar valores enteros en el rango de -128


a +127.
Ejemplos:
byte a, i, j;

b) short. (entero formato corto - 2 bytes).

El tipo short, se define como un dato de 16 bits de longitud,


independientemente de la plataforma en la que resida el bytecode de java.
Proporciona números enteros en el rango de valores:
short -32,768 .. +32,767
Ejemplos:
short i, j;
short a = -500;
c) int. (entero - 4 bytes).

Un valor int se define como un dato de 32 bits de longitud,


independientemente de la plataforma en la que resida el bytecode de java.
El rango de valores es de:
int -2,147’483,648 .. +2,147’483,647
Ejemplos:
int n, x;
int a = 2000;

d) long. (entero formato largo - 8 bytes).

Son números sin punto decimal en formato largo. Un valor long se define
como un dato de 64 bits de longitud, independientemente de la plataforma
en la que resida el bytecode de java. Están comprendidos en el rango de:
long -9’223,372’036,854’775,808 .. +9’223,372’036,854’775,807
Ejemplos:
long n, m;
long a = 2500000;
B) Tipos Reales.
Los tipos de datos reales son aquellos que representan al conjunto de los
números reales. Los números reales se pueden representar en dos formas:
1. Notación científica o de punto (coma) flotante.
El área ocupada por un número real se divide en dos zonas: mantisa y
exponente.
mantisa: número fraccionario (negativos o positivos)
exponente: Potencia de 10
número real = mantisa x 10 exponente
Esta notación se utiliza para representar números muy grandes o muy
pequeños. En notación decimal los números se escriben en notación
exponencial e (e de exponente y significa elevar 10 a la potencia que le
sigue).
n e ± dd
n número decimal (con o sin signo + o -)
dd exponente entero (positivo, negativo o cero)
Ejemplo: 2.83 x 105 (2.83e+5)
2. Notación en punto fijo.
Expresa el número real con un punto decimal.
Ejemplo: 3.1416
a) float. (reales en simple precisión - 4 bytes).

Estos números son los más comúnmente usados en un lenguaje de


programación. Un real en simple precisión es un número que puede
tener un punto decimal y que puede estar comprendido en el rango de:

-3.402823E+38 .. -3.402823E-38 para números negativos


3.402823E-38 .. 3.402823E+38 para números positivos

El tipo float se utiliza para declarar un dato real de 32 bits en el formato


IEEE 754 (1 bit para el signo, 8 bits para el exponente y 23 para la
mantisa). Un número real en simple precisión tiene 7 dígitos significativos.
Ejemplos:
float x;
float a = 3.14159F;
float b = 2.2e-5F;
b) double. (reales en doble precisión - 8 bytes).

Un número real en doble precisión es un número que puede tener un


punto decimal y que puede estar comprendido en el rango de:

-1.79769E+308 .. -1.79769E-308 para números negativos


1.79769E-308 .. 1.79769E+308 para números positivos

El tipo double se utiliza para declarar un dato real de 64 bits en el formato


IEEE 754 (1 bit para el signo, 11 bits para el exponente y 52 para la
mantisa). Un número real en doble precisión tiene hasta 16 dígitos
significativos, lo cual permite cálculos más precisos que con los reales de
simple precisión.
Ejemplos:
double x;
double a = 3.1415926;
double b = 2.2e-18;
C) Tipos Carácter. (caracteres o enteros – 2 bytes).

El tipo carácter o char se utiliza para declarar datos enteros en el rango de


\u0000 a \uFFFF en Unicode (0 a 65535). Los valores de 0 a 127 (\u0000 a
\u00FF) corresponden con los caracteres del código ASCII, los cuales
conforman una parte muy pequeña del juego de caracteres Unicode.
También acepta los caracteres del código ASCII ampliado (127 a 255).
Debido a que Java fue diseñado con el objeto de poder ser utilizado en
cualquier país, independientemente del tipo de alfabeto, para representar
los caracteres en Java se utilizó el estándar Unicode, que maneja más de
30,000 caracteres distintos de la mayoría de los idiomas escritos conocidos
en todo el mundo. El código Unicode, es un código de 16 bits (esto significa
que cada carácter ocupa 2 bytes) creado con el único fin de
internacionalizar el lenguaje.
Internamente, los caracteres se almacenan como números. La letra ‘A’, se
almacena como el número 65 y la ‘a’ como el 97. Por este motivo, se
pueden realizar operaciones aritméticas con datos de tipo char.
Ejemplos:
char c;
char car = ‘a’;
char car = 97;
D) Tipos Lógicos o Booleanos.

El tipo boolean se utiliza para indicar si el resultado de la evaluación de una


expresión booleana es verdadero o falso. Los dos posibles valores de una
expresión booleana son true y false, verdadero y falso, respectivamente.
Las palabras true y false son palabras reservadas en Java. A una variable
boolean se le puede asignar el resultado de una expresión condicional, las
cuales dan como resultado verdadero o falso. El valor de una variable
booleana no se puede convertir a otros tipos, pero si se puede convertir a
una cadena de caracteres y si es necesario, se puede visualizar.
Ejemplos:
boolean bandera;
boolean encontrado = true;
boolean intercambio = false;
CONSTANTES.
Una constante es un valor que no puede cambiar durante la ejecución
del programa. Las constantes pueden ser un número (entero o real), un
carácter o una cadena de caracteres. En Java existen dos tipos de
constantes:
A. Constantes literales.
B. Constantes declaradas.

A. Constantes literales.
Las constantes literales o constantes son las más utilizadas, se llaman
así porque toman un valor directo o literal y así se escriben directamente
en el programa; se clasifican en cuatro grupos:
a) Constantes enteras.
b) Constantes reales.
c) Constantes carácter.
d) Constantes de cadena.
a) Constantes enteras.
El lenguaje Java permite especificar un entero en base: 10 (decimal), 8
(octal) y 16 (hexadecimal). Si la constante es positiva, el signo más (+) es
opcional. Si es negativa, lleva el signo menos (-). El tipo de una constante
está determinado por su valor. También se puede añadir un sufijo (en
mayúsculas o minúsculas). Si el sufijo es L, su tipo es long.
Ejemplo: 1000L constante entera de tipo long

Una constante decimal puede tener uno o más dígitos, con valores de 0
a 9, de los cuales el primero de ellos es distinto de cero. No se deben
utilizar nunca comas ni otros signos de puntuación en números enteros.
Ejemplo: 4326

Una constante octal puede tener uno o más dígitos, con valores de 0 a 7,
precedidos por 0 (cero).
Ejemplo: 0400

Una constante hexadecimal puede tener uno o más caracteres, con


valores de 0 a 9 y de A a F (mayúsculas o minúsculas), precedidos por 0x
o 0X (cero más x).
Ejemplo: 0x100
b) Constantes reales.
Una constante real está formada por una parte entera, seguida por un
punto decimal y una parte fraccionaria. También se permite la notación
científica, en cuyo caso se añade al valor una e o E, seguida por un
exponente positivo o negativo.
ParteEntera.ParteFraccionaria[{e/E}{[+]/-}dígitos]

Donde dígitos representa cero o más dígitos del 0 al 9 y E o e es el


símbolo de exponente de la base 10 que puede ser positivo o negativo
(2E-5 = 2x10-5). Si la constante real es positiva no se necesita especificar
el signo, pero si es negativa debe llevar el signo menos.
Ejemplo:
-17.24
17.244283
.008e3
27E-3

Existen dos tipos de constantes reales:


float 4 bytes
double 8 bytes
Una constante real tiene siempre por defecto el tipo double, a no ser que
se añada a la misma el sufijo f o F, en cuyo caso será de tipo float.
Ejemplo: 17.24F constante real de tipo float

En Java existen dos expresiones definidas como constantes las cuales se


utilizan cuando se presentan errores con valores numéricos, estas
expresiones son: Infinity (infinito) y NaN (Not a Number). Infinity (positivo
o negativo), es una constate real que se muestra como resultado de
ciertas funciones matemáticas, por ejemplo el logaritmo de cero, cuyo
valor es ∞ (infinito).
Ejemplo:
System.out.println("Log(0) = " + Math.log(0.0));
Muestra: Log(0) = -Infinity

Cuando una función o una operación matemática no esta definida para


ciertos valores, se dice que esta expresión no es numérica o no es un
número (Not a Number o NaN).
Ejemplo:
System.out.println("Log(-1) = " + Math.log(-1));
Muestra: Log(-1) = NaN
c) Constantes carácter.
Este tipo de constantes está formado por un único carácter encerrado
entre comillas simples (apóstrofes). Estos caracteres forman parte del
conjunto universal de caracteres denominado Unicode. Además de los
caracteres ASCII, las constantes carácter manejan las secuencias de
escape, llamados también caracteres de barra invertida.
Ejemplos:
'' espacio en blanco
'x' letra minúscula x
'\n' nueva línea (salto de línea)
‘\r’ retorno de carro
'\x001B' carácter ASCII Esc
d) Constantes de cadena.
Una constante de cadena de caracteres o simplemente de cadena, es un
conjunto de caracteres encerrados entre comillas dobles. En Java las
cadenas son objetos sin nombre.
Ejemplos:
"Esto es una constante de caracteres"
"3.1415926"
"Facultad de Informática de Mazatlán"

En el siguiente ejemplo, el carácter \n fuerza a que la cadena: "O pulsar


Enter" se escriba en una nueva línea.
"Escribir un número entre 1 y 5 \nO pulsar Enter"

Cuando una cadena de caracteres es demasiado larga puede utilizarse el


carácter "+" como carácter de continuación o de concatenación.
"Esta cadena de ”+”caracteres esta “+”concatenada."
Esta cadena de caracteres esta concatenada.
B. Constantes declaradas.

Al igual que otros lenguajes de programación, Java permite la declaración


de constantes simbólicas, las constantes se declaran anteponiendo el
calificador final. A un objeto declarado como constante no se le puede
modificar el valor durante la ejecución del programa, por lo que al
declararse debe ser inicializado. El formato general para crear una
constante puede ser cualquiera de los dos siguientes:
final tipo NombreConstante = ValorConstante;
final static tipo NombreConstante = ValorConstante;

Cuando una constante se califica con final y static, sólo existirá una copia
de la constante para todos los objetos que se declaren de esa clase. Si no
se califica con static, cada objeto incluirá su propia copia de la constante.
En los métodos, las constantes locales no pueden ser declaradas static. La
forma más común de declarar una constante es utilizando únicamente el
calificador final, los nombres de constantes declaradas se acostumbra
escribirlos con mayúsculas.
Ejemplo:
final int MAX = 100;
final double PI = 3.141592;
VARIABLES.
Las variables son posiciones de memoria con nombre cuyo valor puede
cambiar durante la ejecución del programa, el cambio se produce
mediante sentencias ejecutables. El nombre de la posición es un
identificador válido y se llama nombre de la variable y el valor
almacenado en la posición se llama valor de la variable. Todas las
variables de un programa en Java deben ser declaradas antes de ser
utilizadas. La declaración consiste en enunciar el nombre de la variable y
asociarle un tipo. El tipo determina los valores que puede tomar la
variable así como las operaciones que con ella pueden realizarse. La
declaración de una variable en Java puede situarse en cualquier parte del
programa:
a) En una clase, como miembro de la clase.
b) Al principio de un método o bloque de código.
c) En el lugar en que será utilizada.
La sintaxis correspondiente a la declaración de una variable es la siguiente:
Formato:
tipo Nombre [, Nombre2, Nombre3...];
tipo Determina el tipo de la variable (char, int, float, double, ...).
Nombre Indica el nombre de la variable (o variables separadas por comas
si son más de una).

Ejemplo:
int cont, i, posición;
char c;
float x, y;

Las variables miembro de una clase siempre son inicializadas por defecto
por el compilador Java para cada objeto que se declare de la misma: las
variables numéricas a 0, los caracteres a ‘\0’, las lógicas a false y las
referencias a cadenas de caracteres y otros objetos a null. Sin embargo,
una variable puede ser inicializada cuando se declara.
Ejemplo:
char car = '\0'; /* car es igual al carácter nulo */
int i = 1; /* inicializa i a 1 */
float a = 0.0F; /* inicializa a a 0 */
a) Declaración de una variable en una clase, como miembro de la clase.
La variable se declara como un miembro de la clase, al mismo nivel que los
métodos de la clase. Estas variables están disponibles para todos los
métodos de la clase y para todas las clases declaradas en el mismo
programa, por lo que puede decirse que una variable de clase es global
para esa clase, sus subclases y los programas que definen y utilizan
objetos de esa clase. A estas variables se les asigna memoria cuando se
crea un objeto de la clase y permanece, hasta que el objeto es liberado
automáticamente o termina la ejecución del programa. Se les llama también
variables de instancia.
Formato:
Modificador tipo Nombre;
Ejemplo:
private int cont, i, posición; Declarada privada.
protected char c; Declarada protected.
float x, y; Declarada por omisión (sin modificador).
public Se puede acceder a la variable desde cualquier método.
protected Los métodos de la clase, los métodos de las clases del mismo paquete pueden acceder a la
variable y también los métodos de las clases derivadas.
private Sólo los métodos de la clase pueden acceder a la variable.
por omisión Los métodos de la clase y los de las clases del mismo paquete pueden acceder a la variable.
(sin modificador)
b) Declaración de una variable al principio de un método o bloque de
código.
Las variables también se pueden declarar en un método o en un bloque
dentro de un método, por ejemplo un ciclo. Las variables que se declaran al
interior de un método se consideran variables locales. Las variables locales
son aquellas definidas en el interior de un método y son visibles sólo en ese
método en particular. No pueden ser modificadas por ninguna sentencia
externa al método. Dos o más métodos pueden definir variables con el
mismo nombre (por ejemplo: contadores y acumuladores). Las variables
locales de los métodos no existen en memoria hasta que se ejecuta el
método; por esta razón, a estas variables locales se les denomina también
automáticas o auto, ya que se crean automáticamente en la entrada al
método y se liberan automáticamente cuando se termina la ejecución del
método.
Ejemplo:
long factorial (int n)
{
int i = 1;
long a = 1;
•••
}
c) Declaración de una variable en el lugar en que será utilizada.
El lenguaje Java tiene una gran flexibilidad ya que permite declarar una
variable en el punto donde se vaya a utilizar. Esta propiedad se utiliza
principalmente en diseño de ciclos, ya que es posible declarar la variable
en el momento de su utilización.
Ejemplo:
for ( int i = 0; i < 10; i++) {
•••
}
CONVERSIÓN ENTRE TIPOS DE DATOS.

Cuando Java tiene que evaluar una expresión en la que intervienen


operandos de diferentes tipos, primero convierte, sólo para realizar las
operaciones solicitadas, los valores de los operandos al tipo del operando
cuya precisión sea más alta. Cuando se trata de una asignación, convierte
el valor de la derecha al tipo de la variable de la izquierda siempre que no
haya pérdida de información. En caso contrario, Java exige que la
conversión se realice explícitamente, en tal caso marca un error indicando
posible pérdida de precisión.
Las conversiones se dan de la siguiente manera: byte, short y char se
convierten a int. Si entonces un operando es long, toda la expresión se
convierte a long. Si un operando es de tipo float, la expresión entera se
convierte a float. Y finalmente si cualquier operando es double, el
resultado es double.

byte short
int long float double
char
Moldes.

Las conversiones de tipo solo se aplican a los valores que sean operados
cuando la expresión es evaluada, fuera de la expresión, la variable es del
tipo que fue definida. Sin embargo, Java permite una conversión explícita
(conversión forzada) del tipo de una expresión mediante una construcción
denominada cast (molde) y tiene la siguiente forma:
(tipo) expresión

Cualquier valor de un tipo entero o real puede ser convertido a o desde


cualquier tipo numérico. No se pueden realizar conversiones entre los tipos
enteros o reales y el tipo boolean.
Ejemplo:
int a = 5, b = 2, c;
double d;
c = a / b; // El resultado es: 2
d = (double) a / b; // El resultado es: 2.5
EXPRESIONES Y OPERACIONES ARITMETICAS.
Los programas Java constan de datos, sentencias de programa y
expresiones. Una expresión es una combinación de operadores y
operandos (que pueden ser constantes, variables o una combinación de
ambas), y a veces pueden contener métodos. Las expresiones de Java
siguen las reglas del álgebra.
Operadores.
Los operadores son símbolos que indican como son manipulados los
datos. El lenguaje Java define muchos más operadores que la mayoría de
los otros lenguajes de programación:
a) Operadores Aritméticos.
b) Operadores de Relación.
c) Operadores Lógicos.
d) Operadores Unitarios.
e) Operadores de Asignación.
f) Operadores Lógicos para el Manejo de Bits.
g) Otros Operadores.
a) Operadores Aritméticos.
Las operaciones aritméticas básicas en Java son: suma, resta,
multiplicación, división y módulo. Los símbolos usados para indicar
operaciones aritméticas son:

Operación Símbolo Usado Símbolo Usado


en Java. en Matemáticas.
Suma + +

Resta - -

Multiplicación * x •

División / / ÷

Módulo (residuo de la división % \


entera)
1. Los operadores aritméticos ( +, -, * ) pueden ser utilizados con tipos
enteros o reales.
2. El operador (/) puede ser utilizado con tipos enteros o reales. Si ambos
operandos son enteros el resultado es entero (int). En el resto de los casos
el resultado es real (double).
3. El operador % se utiliza con números enteros y reales. El operador %
calcula el resto de la división de dos números enteros (int) o reales
(double).
Formato:
operando1 % operando2
operando1 y operando2 Operadores enteros o reales.

Ejemplos:
int a = 10, b = 3, c;
float x = 2.0F, y;

1. y = x + a; /* el resultado es 12.0 de tipo float */


2. c = a / b; /* el resultado es 3 de tipo int */
3. c = a % b; /* el resultado es 1 de tipo int */
4. y = a / b; /* el resultado es 3 de tipo int. Se convierte a float
para asignarlo a y */
Orden de importancia de las operaciones aritméticas básicas
(jerarquía).

Una expresión aritmética es: una constante, una variable o una


combinación de constantes y/o variables unidas por operadores
aritméticos. Cuando una operación aritmética se evalúa, el resultado
siempre es un número. Cuando en una expresión aparecen dos o más
operadores, las operaciones siguen un orden de ejecución de acuerdo a
las siguientes reglas de prioridad o jerarquía (las operaciones de igual
prioridad, se leen y se ejecutan de izquierda a derecha):

Símbolo Expresión Prioridad (Precedencia)


( ) Agrupamiento 1
* Multiplicación 2
/ División 2
% Módulo 2
+ Suma 3
- Resta 3
Escritura de fórmulas matemáticas en Java.

En Java, las fórmulas matemáticas se deben escribir en forma lineal. Por


este motivo, en ocasiones es necesario usar paréntesis que indiquen el
orden correcto de evaluación de los operadores. Las siguientes
expresiones representan fórmulas matemáticas convertidas a lenguaje
Java.
Fórmulas matemáticas. Expresión Java.
a = bc a = b * c;

x = b2 - 4ac x = b * b - 4 * a * c;

y2 - y1
m =  m = ( y2 - y1 ) / ( x2 - x1 );
x2 - x1

x+y 5
a =  +  a = ( x + y ) / ( z + w ) + 5 / ( 1 + x * x );
z+w 1 + x2
b) Operadores de Relación.
Los operadores de relación (también llamados de comparación) se
utilizan para relacionar o comparar dos expresiones u operandos, los
operadores de relación son:

Significado Símbolo Usado Símbolo Usado


en Java. en Matemáticas.
Mayor que > >
Mayor o igual que >= ≥
Igual a (igualdad) == =
Diferente de o Distinto a != ≠
Menor o igual que <= ≤
Menor que < <

Decimos que la condición es verdadera (true), cuando la expresión que


evaluamos se cumple. La condición es falsa (false), cuando la
expresión evaluada no se cumple.
c) Operadores Lógicos.
Los operadores lógicos se usan junto con los operadores de relación para
evaluar expresiones, la expresión evaluada puede proporcionarnos un
resultado verdadero (true) o falso (false).
Los operadores lógicos son: && (y), || (o), ! (no) y ^ (o excluyente) (en
inglés and, or, not y xor).
La notación utilizada es la siguiente:
[ operando 1 ] operador_lógico operando 2

Los operandos 1 y 2 son las expresiones que se van a evaluar y se


recomienda encerrarlas entre paréntesis para evitar errores.
En algunas expresiones, dependiendo del operador lógico que se utilice,
el operando 1 no existe.
La forma de evaluar estos operadores se muestra a continuación
utilizando las tablas de verdad:
a) Operador && (y). <&>
Solo cuando ambas condiciones son true (se cumplen), el resultado es
true. Esto es, AND da como resultado el valor lógico true si ambos
operandos son true. Si uno de ellos es false, el resultado es el valor lógico
false. Si el primer operando es false, el segundo operando no es evaluado.

operando 1 operando 2 operando 1 && operando 2


true true true
true false false
false true false
false false false
b) Operador || (o). <|>
Cuando alguna de las condiciones es true (se cumple), el resultado es
true. Con el operador OR (símbolo ASCII 124), el resultado es false si
ambos operandos son false. Si uno de los operandos tiene un valor
distinto de false, el resultado es true. Si el primer operando es true, el
segundo operando no es evaluado.

operando 1 operando 2 operando 1 || operando 2


true true true
true false true
false true true
false false false
c) Operador ! (no).
El operador NOT, devuelve un resultado de false si el operando tiene un
valor true, y devuelve true en caso contrario.

operando ! operando
true false
false true

d) Operador ^ (xor).
Cuando alguna de las condiciones es true (se cumple) y la otra false, el
resultado es true. En caso contrario, si ambas son true o false, la
expresión es false.

operando 1 operando 2 operando 1 ^ operando 2


true true false
true false true
false true true
false false false
El orden de evaluación de los operadores lógicos es el siguiente:

Operador Prioridad Símbolo Usado en Símbolo Usado en


Java. Matemáticas.
No 1 ! ∼ (negación)

XOR 2 ^ (o excluyente)
Y 3 && ∧ (conjunción)

O 4 || ∨ (disyunción)

El resultado es de tipo boolean. Los operandos pueden ser enteros o


reales.
d) Operadores Unitarios (unarios o monarios).

Operador Operación

- Cambia el signo al operando (complemento a dos). El


operando puede ser entero o real.
~ Complemento a 1. El operando tiene que ser entero
(carácter ASCII 126).
++ Incremento.
-- Decremento.
! Negación.
e) Operadores de Asignación.

Operador Operación
++ Incremento.
-- Decremento.
= Asignación simple.
*= Multiplicación más asignación.
/= División más asignación.
%= Módulo más asignación.
+= Suma más asignación.
-= Resta más asignación.
<<= Desplazamiento a la izquierda mas asignación.
>>= Desplazamiento a la derecha más asignación con extensión de signo.
>>>= Desplazamiento a la derecha más asignación rellenando con ceros.
&= Operación AND sobre bits más asignación.
|= Operación OR sobre bits más asignación.
^= Operación XOR sobre bits más asignación.
f) Operadores Lógicos para el Manejo de Bits.

Operador Operación
& Operación AND a nivel de bits.
| Operación OR a nivel de bits (ASCII 124).
^ Operación XOR a nivel de bits.
<< Desplazamiento a la izquierda.
>> Desplazamiento a la derecha con extensión de signo.
>>> Desplazamiento a la derecha rellenando con ceros.
Los operadores Y, O y XOR producen un resultado basado en la comparación de los
bits correspondientes de cada operando. El operador Y activa un bit si los dos bits
que se comparan son 1. El operador O activa un bit si uno de los bits que se
comparan es 1. El operador XOR (O excluyente) activa un bit si uno de los dos bits
comparados es 1, pero no si los dos son 1 o 0.
El operador complemento a uno (~) es un operador unario que invierte el estado de
cada bit de un entero o carácter. De forma que los 1 se ponen a 0 y los 0 a 1.
Los operadores de desplazamiento >>, >>> y <<, mueven todos los bits de una
variable a la derecha o a la izquierda, según se especifique. A medida que se
desplazan los bits hacia un extremo se va rellenando con ceros (>>) o por el valor
del bit más significativo (>>>) por el extremo opuesto. Los bits que salen se pierden.
Un desplazamiento a la derecha de un número negativo introduce unos.

La forma general de desplazamiento a la derecha es:


variable >> número de posiciones de bits
variable >>> número de posiciones de bits

La forma general de desplazamiento a la izquierda es:


variable << número de posiciones de bits

Un desplazamiento a la izquierda equivale a una multiplicación por 2 y un


desplazamiento a la derecha a una división entre 2.
g) Otros Operadores.

a) Operador condicional.
Java tiene un operador condicional, llamado también operador ternario
( ? : ), que se utiliza en expresiones condicionales y tienen la forma:
operando1 ? operando2 : operando3 ;

La expresión operando1 debe ser una expresión booleana. La


evaluación se realiza de la siguiente manera:

* Si el resultado de la evaluación de operando1 es true, el resultado de


la expresión condicional es operando2.
* Si el resultado de la evaluación de operando1 es false, el resultado de
la expresión condicional es operando3.
Ejemplo:
mayor = ( a > b ) ? a : b; /* el mayor de a y b */

El ejemplo dice que si a > b entonces mayor = a,


de lo contrario, mayor = b.
b) Operador coma ( , ).
El operador coma permite combinar dos o más expresiones separadas por
comas en una sola línea. Se evalúa primero la expresión de la izquierda
antes de evaluar la expresión de la derecha, a continuación el valor de la
expresión de la izquierda es descartado, se continúa evaluando las
expresiones de izquierda a derecha. El tipo y el valor del resultado son el
tipo y el valor del operando de la derecha. El operador coma tiene la
menos prioridad de todos los operadores Java y se asocia de izquierda a
derecha.
Expresión1, expresión2, expresión3, …, expresiónN

c) Molde o Cast. ( tipo )


Java permite una conversión explícita (conversión forzada) del tipo de una
expresión mediante una construcción denominada cast (molde) y tiene la
siguiente forma:
(tipo) expresión

Cualquier valor de un tipo entero o real puede ser convertido a o desde


cualquier tipo numérico. No se pueden realizar conversiones entre los tipos
enteros o reales y el tipo boolean.
d) Operador instanceof.
Java trabaja con objetos que son instancias de clases. El operador
instanceof es un operador relación cuya evaluación da como resultado un
valor de tipo boolean y utiliza dos operandos, el primero debe ser un objeto
y el segundo un tipo de datos, una clase. Evalúa la expresión a verdadero
si el primer operando es una instancia del segundo.
Operando1 instanceof Operando2

e) Operador new.
El operador new es un operador que reserva memoria dinámicamente para
un objeto, esto es, se usa para crear un objeto. Su forma general es:
variable = new nombre_de_clase();

variable Es una variable del mismo tipo de la clase creada.


nombre_de_clase Es el nombre de la clase que está siendo
instanciada.
Orden de prioridad de los operadores y orden de evaluación (jerarquía).
Jerarquía Operadores Asociatividad Tipo
1 () [] . izquierda a derecha Paréntesis, punto
2 - ! ~ ++ -- derecha a izquierda Unarios
3 new (tipo) expresión derecha a izquierda Crear Obj., molde
4 * / % izquierda a derecha Multip., división
5 + - izquierda a derecha Aditivo
6 << >> >>> izquierda a derecha Desplazamiento
7 < <= > >= instanceof izquierda a derecha Relacional
8 == != izquierda a derecha Igualdad
9 & izquierda a derecha AND (niv. bits)
10 ^ izquierda a derecha XOR (niv. bits)
11 | izquierda a derecha OR (niv. bits)
12 && izquierda a derecha AND lógico
13 || izquierda a derecha OR lógico
14 ?: derecha a izquierda Condicional
15 = += -= *= /= %= <<= >>= >>>= &= derecha a izquierda Asignación
|= ^=
UNIVERSIDAD AUTONOMA DE SINALOA
FACULTAD DE INFORMÁTICA DE MAZATLAN

PROGRAMACIÓN I
Instrucciones Fundamentales
TITULAR DE LA MATERIA:
DR. JOSÉ NICOLÁS ZARAGOZA GONZÁLEZ
INSTRUCCIONES FUNDAMENTALES.

Un programa de aplicación escrito en Java está compuesto


de objetos, y un objeto es la concreción o instancia de una
clase, a su vez, la clase es la generalización de un tipo de
objetos. La estructura básica general de un programa en
Java es la siguiente:
<sentencia(s) import> Declaración para importar clases de paquetes.
[protección] class NombreClase
{
<Variables miembro de la clase (atributos)>
< [modificador] tipo_devuelto método1 ( Lista de parámetros )
{
Declaración de variables locales
Sentencias ejecutables
}
[modificador] tipo_devuelto método2 ( Lista de parámetros )
{
Declaración de variables locales
Sentencias ejecutables
}
• • • Definición de métodos (operaciones) dentro de la clase.
[modificador] tipo_devuelto métodoN ( Lista de parámetros )
{
Declaración de variables locales
Sentencias ejecutables
} >
< public static void main ( String args [ ] ) Método principal.
{
Declaración de variables locales
Sentencias ejecutables
} >
}
También puede crearse una clase y grabarse en un archivo
que debe tener exactamente el mismo nombre que la clase y
la extensión .java. Por su parte, el programa principal puede
almacenarse en un archivo independiente, el cual llamará a
la clase o clases definidas en otros archivos al momento de
definir sus objetos o instancias de clase.
<Archivo 1> Debe llamarse igual que la clase.

<sentencia(s) import> Declaración para importar clases de paquetes.

[protección] class NombreClase


{
<Variables miembro de la clase (atributos)>
[modificador] tipo_devuelto método1 ( Lista de parámetros )
{
Declaración de variables locales
Sentencias ejecutables
}
[modificador] tipo_devuelto método2 ( Lista de parámetros )
{
Declaración de variables locales
Sentencias ejecutables
}
• • • Definición de métodos (operaciones) dentro de la clase.
[modificador] tipo_devuelto métodoN ( Lista de parámetros )
{
Declaración de variables locales
Sentencias ejecutables
}
}
<Archivo 2> Debe llamarse igual que la clase.

<sentencia(s) import> Declaración para importar clases de paquetes.

[protección] class NombreClase


{
public static void main ( String args [ ] ) Método principal.
{
Declaración de variables locales
Creación de objetos o instancias de clase
Sentencias ejecutables
}
}
1. Sentencias import.
Un paquete es un conjunto de clases relacionadas entre sí. Los paquetes
se encuentran en directorios de disco que tienen el mismo nombre que el
paquete. Para importar una clase de un paquete desde un programa se
utiliza la sentencia import. Pueden aparecer cualquier número de
sentencias import, las cuales deben escribirse antes de cualquier
definición de clase. La sintaxis general de la sentencia import es la
siguiente:
import Paquete1.[Paquete2.]nombreClase;
Ejemplo:
import java.lang.System; Importa la clase System del paquete java.lang.
import java.io.*; Importa las clases que puedan ocuparse para
operaciones de entrada/salida del paquete java.io.

Así mismo, un programador puede definir sus propios paquetes para


agrupar clases; los paquetes se deben ubicar en subdirectorios con el
mismo nombre que el paquete. Para incorporar las clases contenidas en
ese paquete, se utilizan las declaraciones import de la misma manera que
con los paquetes predefinidos. Los principales paquetes de Java son:
Paquete Explicación
java.applet Este paquete contiene la clase Applet, la cual proporciona todo lo necesario
para programar applets.
java.awt En este paquete se encuentran todas las herramientas gráficas AWT (Abstract
Window Toolkit) que proporcionan el soporte gráfico para los applets. Esto es,
los métodos y clases que permiten crear y manejar ventanas, gráficos y texto.
java.beans Java Beans es un componente de software que se ha diseñado para ser
utilizado en entornos diferentes y desarrollar complejos sistemas de software
reutilizables.
java.io El paquete java.io contiene el sistema básico de Entrada/Salida de Java,
incluyendo la E/S con archivos.
java.lang Las clases, interfaces y métodos básicos, necesarios para desarrollar un
programa en Java se encuentran en este paquete. Las clases de este
paquete son importadas de forma automática por lo que no es necesaria una
sentencia import que importe este paquete.
java.math Este paquete contiene clases para realizar operaciones con números enteros
de diferente precisión y aritmética de punto flotante.
java.net El paquete java.net proporciona el soporte para el trabajo en red y las
conexiones del protocolo TCP/IP.
java.rmi Contiene las clases e interfaces que permiten invocar a un método remoto
(RMI, Remote Method Invocation). Esto es, un objeto Java que se ejecuta en
una máquina, invoca a otro objeto Java que se ejecuta en otra máquina.
Paquete Explicación

java.security Este paquete contiene clases e interfaces que implementan sistemas de


autentificación y control de acceso. Soporta el envío y recepción de mensajes
encriptados y firmas digitales.
java.sql Contiene las clases e interfaces que permiten desarrollar programas que
ejecuten instrucciones en lenguaje estándar de acceso a Bases de Datos
SQL (Structured Query Language o Lenguaje Estructurado de Consultas) a
través de JDBC (Java DataBase Connectivity).
java.text El paquete java.text da soporte al manejo de textos en aplicaciones Java,
proporcionando clases e interfaces que trabajan con cadenas de texto, dan
formato, realizan búsquedas y buscan texto.
java.util Este es uno de los paquetes más usados. Contiene un conjunto de clases e
interfaces de utilerías para diversas aplicaciones como son: la generación de
números pseudoaleatorios, manejo de fecha y hora, observación de eventos,
manipulación de conjuntos de bits y operaciones con cadenas.
javax.net Este paquete define clases e interfaces para dar soporte a sockets cliente –
servidor que sean de tipo diferente a los que se establecen por defecto.
javax.swing Swing es un conjunto de clases que proporcionan componentes más
potentes y flexibles que los que ofrece AWT. Contiene métodos y clases que
permiten crear y manejar ventanas, gráficos y texto.
javax.xml Este paquete proporciona una API (interfaz de programación de aplicaciones)
para el análisis y transformación de documentos XML.
2. Declaración de clases y nombre del programa.
Una clase es un tipo definido por el usuario que define las variables y los
métodos comunes a todos los objetos que se crearán a partir de la misma.
La declaración de una clase puede empezar con una palabra clave que es
un modificador de protección que generalmente indica el acceso y es
opcional; a continuación sigue el indicador de clase, la palabra reservada
class; después sigue el nombre de la clase y los miembros de la clase:
variables y métodos.
El convenio general entre los programadores para dar nombre a una clase,
es comenzar el nombre de la clase con una letra mayúscula.
Otra observación importante es que el archivo en el cual se guarda el
código, debe tener exactamente el mismo nombre de la clase
(NombreClase = NombreClase.java), respetando mayúsculas y
minúsculas.
En el caso de los programas, deberá ser el nombre de la clase principal,
que es la clase que contiene el método main(). En ambos casos, la
extensión del archivo será .java.
Por ejemplo: NombreClase.java.
Cada definición de una clase Java deberá estar en un archivo.
La forma general de una clase es la siguiente:
<sentencia(s) import> Declaración para importar clases de paquetes.

[protección] class NombreClase


{
tipo Variable_miembro_de_la_clase_1
tipo Variable_miembro_de_la_clase_2
• • •
tipo Variable_miembro_de_la_clase_N

[modificador] tipo_devuelto método1 ( Lista de parámetros )


{
Declaración de variables locales
Sentencias ejecutables
}

• • • Definición de métodos (operaciones) dentro de la clase.

[modificador] tipo_devuelto métodoN ( Lista de parámetros )


{
Declaración de variables locales
Sentencias ejecutables
}
}
Una clase puede contener diferentes miembros. Los más importantes son:
* Constructores. Crean un objeto de una clase determinada y se utilizan
para inicializar el estado del objeto.
* Variables de instancia. Almacenan información acerca del estado del
objeto.
* Métodos. Realizan alguna operación sobre un objeto.
* Variables estáticas. Almacenan información que se relaciona con la clase
completa en lugar de con un objeto específico.
* Métodos estáticos. Realizan alguna operación que se relaciona con la
clase completa en lugar de con un objeto específico.

Una clase Java se debe compilar antes de que cualquier programa la


mande llamar. El código compilado de la clase (denominado bytecode), se
almacena en un archivo con el mismo nombre pero con la extensión .class
en vez de .java. Así, si se compila el archivo Clase.java, se creará un
archivo Clase.class, posteriormente se puede combinar esta clase con un
método main() que utilice esa clase.
Creación y utilización de un objeto.
Normalmente, un programa crea muchos objetos a partir de una variedad
de clases. Un objeto es una instancia de una clase y se pueden crear
muchas instancias de una clase. Estos objetos interactúan con otros
objetos enviándose mensajes entre sí. Mediante estas interacciones entre
objetos, un programa Java puede implementar una Interfaz Gráfica de
Usuario (GIU), mover una animación o enviar y recibir información en una
red. Una vez que un objeto ha completado el trabajo para el que fue
creado, el espacio de memoria ocupado se libera, lo cual se conoce como
recolección de basura, y sus recursos (de memoria) se reciclan para ser
usados por otros objetos. El ciclo de vida de un objeto consta de tres
etapas:
1. Creación.
2. Uso.
3. Destrucción.
1. Creación de un objeto.
Para declarar un objeto se debe utilizar una variable para representar ese
objeto (esto es similar a la declaración de una variable de un tipo de dato
primitivo). La sintaxis para declarar una variable objeto es:
NombreClase nombreObjeto;

La creación de un objeto de una clase se denomina crear una instancia de


clase. Un objeto es similar a una variable pero definida de tipo clase, la
declaración de un objeto simplemente asocia a la variable con la clase. Sin
embargo, la declaración no crea el objeto, sino que crea la variable que
posteriormente va a referenciar a un objeto de esa clase. Para crear
realmente un objeto y poder acceder a él con una variable, se necesita
utilizar el operador new, con el fin de asignar espacio de memoria para el
mismo y asociarlo a la variable. La sintaxis es:
nombreObjeto = new NombreClase();
Normalmente se combinan la declaración e instanciación juntas en una
sola sentencia utilizando la siguiente sintaxis:
NombreClase nombreObjeto = new NombreClase();

Las variables de objetos que permiten acceder a los objetos creados


(instanciados) se denominan referencias al objeto.
Siempre debe utilizarse el operador new para crear un objeto antes del
manejo de ese objeto. El manejo o manipulación de un objeto que no ha
sido creado producirá un error en tiempo de ejecución.
2. Uso de un objeto.
Una vez que se ha creado un objeto se debe utilizar para llevar a cabo
algún proceso o acción. Se puede necesitar información del objeto, cambiar
su estado o realizar alguna otra acción. Para hacer esto, existen dos
formas:

a) Manejando sus variables.


Para referirse a las variables de un objeto, se añade el nombre de la
variable a una referencia de un objeto utilizando el operador punto (.).
referenciaObjeto.variable

b) Llamar o invocar a sus métodos.


La llamada a los métodos de un objeto también utiliza el operador punto.
Existen dos formas de invocar al método: utilizando argumentos o con
paréntesis vacíos, cuando no se tiene ningún argumento.
referenciaObjeto.nombreMétodo(lista de argumentos)
referenciaObjeto.nombreMétodo( )
3. Destrucción de un objeto.
Java gestiona automáticamente la liberación de la memoria lo cual se
conoce como recolección de basura y consiste en lo siguiente: cuando no
existen referencias a un objeto, se supone que no se va a necesitar ya, y
la memoria ocupada por dicho objeto puede ser recuperada. La
recolección de basura sólo se produce esporádicamente, si es necesario,
durante la ejecución del programa. Los diferentes intérpretes de Java
siguen distintos procedimientos de recolección de basura, eso es algo que
maneja internamente Java y no hay necesidad de preocuparse por ello al
hacer un programa.
3. Variables miembro de la clase (atributos).
Los miembros dato de una clase se definen como variables de instancia.
Estas variables pueden ser de cualquier tipo primitivo (int, char, byte, float,
double, etc.), arreglos, cadenas, etcétera. Toda variable debe ser definida
antes de ser utilizada. La definición de una variable, declara la variable y
además le asigna memoria. La sintaxis es la siguiente:
acceso tipo nombreVariableInstancia;

La accesibilidad (acceso) de las variables de una clase puede ser:


1. private, sólo es accesible dentro de la clase.
2. default (sin modificador), accesible por cualquier clase del paquete.
3. protected, accesible en todo el paquete y en clases derivadas de otros
paquetes.
4. public, accesible desde cualquier clase.

Violar estas normas de acceso da un error al compilar el programa.


Además, una variable puede ser inicializada en la propia definición.
Ejemplos:
int lado = 5;
float area = 2.5F;
4. Definición de métodos (operaciones).
[ método1, método2, ..., métodoN ]
Un método es un conjunto de sentencias que ejecutan una tarea específica.
En Java, un método siempre pertenece a una clase y su definición nunca
puede contener la definición de otro método, esto significa que no se
pueden tener métodos anidados. Todos los métodos tienen nombre y una
lista de datos o valores que reciben, llamados parámetros o argumentos. La
definición de un método consta de dos partes: la cabecera y cuerpo del
método. La sintaxis para definir un método es la siguiente:

[modificador] tipo_devuelto método ( Lista de parámetros )


{
Declaración de variables locales
Sentencias ejecutables
return expresión; // No se escribe si el método es de tipo void.
}
Constructores.
Los constructores son métodos no estáticos que tienen el mismo nombre de
la clase, no devuelven ningún valor y se llaman automáticamente cuando se
crea una clase. La función del constructor es inicializar un nuevo objeto (los
datos del objeto). Para una clase, se pueden especificar tantos
constructores como sea necesario, diferenciándose uno de otro por el
número o tipo de parámetros. Los valores que inicializan a las variables de
instancia se pasan a través de la lista de argumentos de los constructores.
Si la clase no tiene ningún constructor, se utiliza un constructor por defecto
que no inicializará los datos de sus objetos. Si no se utilizan constructores,
todos sus objetos serán inicialmente iguales.

class Cubo
{
double lado;
// Constructor para el objeto Cubo.
Cubo (double l) {
lado = l;
}
••• // Definición de métodos.
}
5. Método main( ).
Todos los programas de aplicación de Java inician su ejecución llamando al
método main(). Esto significa que main() es el programa principal o punto
de inicio de la aplicación, y también su punto de salida. Cada programa de
aplicación en Java tiene un método main() y solo uno, si tiene más de un
main() se produce un error, aunque estén en diferentes clases. Las clases
de Java no necesariamente deben tener un método main(), a menos que
esa clase tenga el programa principal El método main() se define de
cualquiera de la siguientes maneras:

public static void main ( String args[ ] )


{
Declaración de variables locales
Sentencias ejecutables
}

public static void main ( String[ ] args )


{
Declaración de variables locales
Sentencias ejecutables
}
ASIGNACION.
La Sentencia de Asignación.
La sentencia de asignación se utiliza para guardar o almacenar valores o
variables. La asignación es una operación que coloca o sitúa un valor
determinado en una posición de memoria. En Java la sentencia de
asignación simple utiliza el signo igual '=' y debe terminar con punto y coma
(;). La sentencia de asignación es asimétrica, esto quiere decir que la
expresión de la derecha es evaluada y el resultado es asignado a la
variable indicada a la izquierda. En una operación de asignación, el valor de
la derecha es convertido al tipo del valor de la izquierda.
Formato:
Variable operador expresión ;
Variable = expresión; /* ejemplo de sentencia de asignación simple */

Variable Identificador válido declarado en la sección de


declaraciones.
Operador Operador de asignación.
expresión Variable, constante, expresión aritmética o fórmula.
Operadores de Asignación.
Operador Operación
(expr) ++ Incremento (prefijo).
(expr) -- Decremento (prefijo).
++ (expr) Incremento (postfijo).
-- (expr) Decremento (postfijo).
= Asignación simple.
*= Multiplicación más asignación.
/= División más asignación.
%= Módulo más asignación.
+= Suma más asignación.
-= Resta más asignación.
<<= Desplazamiento a la izquierda mas asignación.
>>= Desplazamiento a la derecha más asignación con extensión de signo.
>>>= Desplazamiento a la derecha más asignación rellenando con ceros.
&= Operación AND sobre bits más asignación.
|= Operación OR sobre bits más asignación.
^= Operación XOR sobre bits más asignación.
OPERACIONES DE ENTRADA/SALIDA:

Los datos se pueden almacenar en memoria de tres formas diferentes:


asociados con constantes, asignados a una variable con una sentencia
de asignación o con una sentencia de lectura. La sentencia de lectura es
el método más adecuado si se desea manipular diferentes datos cada
vez que se ejecuta el programa. Además la lectura de datos permite
asignar valores en memoria desde dispositivos o archivos externos (Por
ejemplo: un teclado o una unidad de disco). A esta operación se le
denomina: operación de entrada o lectura.
Conforme se realizan cálculos en un programa, se necesitan visualizar
los resultados. Esta operación se conoce como operación de salida o de
escritura.
En los algoritmos y en pseudocódigo, las instrucciones de entrada/salida
son:
leer (listas de variables entrada) leer x, y, z o leer ( x, y, z )
escribir (listas de variables salida) escribir x, y, z o escribir ( x, y, z )
En Java, la entrada y salida se lee y se escribe a través de flujos (streams).
Java 2 define dos tipos de flujos: de bytes y de caracteres. Un flujo es un
objeto que hace de intermediario entre el programa y el origen o destino de
la información. Esto significa que el programa leerá o escribirá en el flujo
sin importarle desde dónde viene la información o adonde va, ni el tipo de
datos que se leen o escriben. Básicamente, la fuente de entrada de datos
es el teclado y la fuente de salida de resultados es la pantalla.
Debido a que todas las clases relacionadas con flujos pertenecen al
paquete java.io de la biblioteca estándar de Java, un programa que utilice
flujos de Entrada/Salida (E/S), tendrá que importar este paquete:
import java.io.*;

Las clases del paquete java.io están divididas en dos grupos distintos. Uno
ha sido diseñado para trabajar con datos de tipo byte y el otro con datos de
tipo char.
Así mismo, la biblioteca de Java proporciona tres flujos estándar manejados
por la clase System del paquete java.lang. Estos flujos predefinidos son
automáticamente abiertos cuando se inicia un programa, y cerrados cuando
finaliza:
System.in. Referencia a la entrada estándar del sistema, que normalmente
es el teclado. Se utiliza para leer datos introducidos por el usuario.
System.out. Referencia a la salida estándar del sistema, que normalmente
es la pantalla. Se utiliza para mostrar los datos al usuario.
System.err. Referencia a la salida estándar de error del sistema, que
normalmente es el monitor. Se utiliza para mostrar mensajes de error al
usuario.
La clase System define dos referencias a objetos static para la entrada por
teclado y salida por monitor:
System.in para entrada por teclado.
System.out para salida por pantalla.

El primero es una referencia a un objeto de la clase BufferedInputStream en


la cual hay diversos métodos para poder leer los caracteres tecleados. El
segundo es una referencia a un objeto de la clase PrintStream con métodos
como print() o println(), para salida por pantalla. A continuación veremos
como utilizar estas clases y métodos.
1. SALIDA (ESCRITURA DE RESULTADOS).

Un programa debe proporcionar información de salida (resultados). La


salida toma información de la memoria y la presenta en pantalla, o bien, la
puede guardar en un dispositivo de almacenamiento (disco duro o flexible) o
en un puerto de Entrada/Salida.

Flujos de salida.

OutputStream.
La clase OutputStream es una clase abstracta que es una superclase de
todas las clases que representan un flujo en el que un origen escribe bytes
en un destino. El método más importante de esta clase es write. Este
método se presenta de tres formas:
public void write ( int b) throws IOException
public void write ( byte[ ] b) throws IOException
public void write ( byte[ ] b, int off, int len) throws IOException
La primera versión de write simplemente escribe el byte especificado en un
flujo de salida. Puesto que el parámetro es de tipo int, lo que se escribe es
el valor correspondiente a los 8 bits menos significativos, el resto son
ignorados.
La segunda versión del método write escribe los bytes almacenados en el
arreglo b en un flujo de salida.
La tercera versión del método write escribe un máximo de len bytes de un
arreglo b a partir de su posición off, en un flujo de salida.
Cada uno de estos métodos ha sido escrito para que bloquee la ejecución
del programa que los manda llamar hasta que toda la salida solicitada haya
sido escrita.
Por su parte, la clase Writer es una clase abstracta que es superclase de
todas las clases que representan un flujo para escribir caracteres a un
destino. Sus métodos son similares a los de la clase OutputStream, con la
diferencia de que utilizan parámetros de tipo char en lugar de tipo byte.
System.out
El objeto out definido en la clase System está asociado con el flujo de
salida que dirige los datos y permite visualizarlos en el monitor. Con estos
métodos se puede imprimir cualquier cadena (String) o tipo de dato
primitivo o referenciado: Object, char[ ], int, short, long, double y bolean.
El método se encarga de convertir a cadena esos tipos básicos y
mostrarlos en pantalla. Así mismo, se pueden concatenar cadenas con
caracteres, enteros, etcétera, para lo cual se utiliza el operador +, que
internamente realiza la conversión. También existe una versión de println
que no tiene argumentos y lo que hace es avanzar a la línea siguiente.
System.out es una referencia a un objeto de la clase PrintStream, el cual
es un flujo de salida derivado de OutputStream, y tiene métodos que
permiten fácilmente la salida por pantalla. Estos métodos son:

print ( ) Escribe una cadena de caracteres en el buffer de la pantalla.


println ( ) Escribe una cadena de caracteres en el buffer de la pantalla y
añade el carácter de salto de línea al final de su salida.
flush ( ) Limpia el buffer con las cadenas almacenadas enviándolas a la
pantalla.
Java también hace uso de las secuencias de escape o constantes
especiales de carácter con barra invertida. La lista y significado de estas
constantes se muestran en la siguiente tabla.

Código Significado
‘\b’ Retroceso (backspace).
‘\n’ Salto de línea (line feed).
‘\r’ Retorno de carro (return).
‘\t’ Tabulación horizontal.
‘\f’ Salto de página (form feed).
‘\"’ Imprime comillas dobles.
‘\'’ Imprime una comilla simple.
‘\0’ Carácter nulo.
‘\\’ Imprime una barra invertida.
‘\000’ Número octal.
‘\uhhhh’ Número hexadecimal.
PrintWriter.
En la mayor parte de las aplicaciones reales de Java, no se utilizan programas cuya
salida basada en texto, sea a través del monitor, sino que serán aplicaciones
gráficas que basen su interacción con el usuario en un conjunto de herramientas
gráficas denominado AWT (Abstract Window Toolkit). Sin embargo, se recomienda el
uso de la clase PrintWriter en programas reales y aplicaciones de software con
salidas basadas en texto. PrintWriter es una clase que se basa en caracteres y, por
esta razón, resulta más fácil para la utilización internacional de un programa.
PrintWriter define varios constructores, el más recomendado es el siguiente:
PrintWriter (OutputStream flujosalida, bolean flushOnNuevalínea)
Donde flujosalida es un objeto del tipo OutputStream, y flushOnNuevalínea, una
variable booleana que controla si Java limpia el flujo de salida cada vez que se llama
al método println(). Si la variable flushOnNuevalínea es true, el flujo de salida se
limpia automáticamente. En caso de que sea false, esta limpieza no es automática.
La clase PrintWriter soporta los métodos print() y println() para todos los tipos,
incluyendo Object. Por lo tanto se pueden utilizar estos métodos de la misma
manera que se utilizan con System.out. Si un argumento no es de un tipo sencillo,
los métodos de PrintWriter llaman al método toString() del objeto, y entonces se
imprime el resultado.
Para escribir en la pantalla utilizando la clase PrintWriter, hay que especificar el
System.out para el flujo de salida y limpiar el flujo después de cada nueva línea. El
siguiente ejemplo crea un objeto PrintWriter que está conectado a la salida por el
monitor:
PrintWriter pw = new PrintWriter (System.out, true);
Visualizar datos con formato.
Los resultados producidos por las aplicaciones pueden tener algún tipo de
formato, ya que es posible que en alguna ocasión necesitemos expresar
una cantidad:
• Incluyendo el punto de los decimales y la coma de los miles.
• Con un determinado número de dígitos enteros, completando con ceros
por la izquierda si fuera necesario.
• Con un número determinado de decimales y ajustada a la derecha.
• O con una serie de cantidades decimales, una debajo de otra, ajustadas
por el punto decimal.
Si en lugar de cantidades hablamos de fechas, también podemos requerir
de diferentes modos de presentación.
Para controlar los distintos formatos, Java proporciona un conjunto de
clases en el paquete java.text. La clase Format es una clase abstracta
para dar formato a números, fechas/hora y mensajes. De esta clase se
derivan tres subclases especializadas en cada una de las tareas
mencionadas: NumberFormat, DateFormat y MessageFormat.
La clase NumberFormat es la clase base abstracta para todos los formatos
numéricos. La clase DateFormat es también una clase abstracta para los
formatos de fechas y horas. Pero las clases que son particularmente útiles y
que nos interesa conocer son: DecimalFormat, SimpleDateFormat y
MessageFormat.
a) Dar formato a números.
Para dar formato a un número, primero hay que crear un objeto formateador
basado en un formato específico, y luego utilizar su método format para
convertir el número en una cadena construida a partir del formato elegido.
Los símbolos que se pueden utilizar para especificar un determinado
formato son:
Símbolo Significado
0 Representa un dígito cualquiera, incluyendo los ceros no significativos.
# Representa un dígito cualquiera, excepto los ceros no significativos.
. Representa el separador decimal.
, Representa el separador de los miles.
E Formato de notación científica. E, separa la mantisa y el exponente.
; Actúa como separador cuando se especifican varios formatos.
- Signo negativo de forma predeterminada.
% Multiplicar por 100 y mostrar el símbolo %.
$ Representa el símbolo monetario.
carácter Cualquier carácter puede ser utilizado como prefijo o como sufijo. Por
ejemplo: $ o ‘\u0024’.
El siguiente ejemplo crea un objeto llamado formato que permitirá obtener
números formateados con dos decimales, si los hay, con la coma de los
miles.
DecimalFormat formato = new DecimalFormat(“###,###.##”);
String salida = formato.format(dato);

Si el número de dígitos correspondiente a la parte entera excede el número


de posiciones especificado para la misma, el formato se extiende en lo
necesario. Si el número de dígitos decimales excede el número de
posiciones especificado para los mismos, la parte decimal se trunca
redondeando el resultado.
Se puede utilizar también un objeto formateador basado en la localidad
actual. Por ejemplo, las siguientes líneas de código darán lugar a números
formateados así: $123,456.00.
NumberFormat formato = NumberFormat.getCurrencyInstance();
String salida = formato.format(dato);
El método getCurrencyInstance devuelve el formato monetario de la localidad
actual cuando no se especifica una, o el de la especificada. Por ejemplo:
Locale es_MX = new Locale("es","MX");
NumberFormat formato = NumberFormat.getCurrencyInstance(es_MX);
String salida = formato.format(dato);

Donde (“es”, “MX”) significa español de México. Otros ejemplos de localidades son:
(“en”, “US”), significa inglés de Estados Unidos, (“en”, “GB”), significa inglés de Gran
Bretaña; (“es”, “ES”), significa español de España, (“fr”, “FR”), significa francés de
Francia; (“de”, “DE”), significa alemán de Alemania; etc. Sin embargo, una localidad
no es un idioma, ya que un mismo idioma se puede hablar en varios países. Cuando
se escriba un programa internacional se tendrá que definir la localidad actual y el
conjunto de localidades que soportará el programa. Las localidades son definidas en
Java por la clase Locale incluida en el paquete java.util. Un objeto de la clase
Locale es simplemente un identificador para una localidad específica. Por ejemplo,
el siguiente código crea dos objetos: país[0] y país[1], uno para el español de
México y otro para el inglés de Estados Unidos.
Locale[ ] país = {
new Locale(“es”, “MX”);
new Locale(“en”, “US”);
};
Aplicando todos los métodos, se puede obtener el formato predeterminado para
cualquiera de éstos dos países. Por ejemplo:
DecimalFormat df = (DecimalFormat) DecimalFormat.getNumberInstance(país[i]);

Cuando escribimos valores numéricos con o sin formato, quedan alineados


automáticamente a la izquierda. Para alinear a la derecha una serie de valores
numéricos formateados, además del objeto formateador, hay que crear un objeto de la
clase FieldPosition basado en la posición utilizada para realizar la alineación. Ésta
puede ser:
INTEGER_FIELD Alineación por el último dígito entero (por el punto decimal).
FRACTION_FIELD Alineación por el último dígito decimal.

INTEGER_FIELD y FRACTION_FIELD son dos constantes pertenecientes a la clase


Numberformat. Para utilizar el objeto FieldPosition definido, el método format
invocado a través del objeto formateador debe tener tres parámetros: el valor
numérico a formatear, un objeto StringBuffer donde se almacenará el número
formateado y el objeto FieldPosition. Para realizar la alineación se deberán añadir al
principio del objeto StringBuffer un número de espacios en blanco igual al espacio de
impresión deseado menos el total de dígitos a imprimir.
String patrón = new String(“###,###,##0.00”);
DecimalFormat formato = new DecimalFormat(patrón);
FieldPosition fp = new FieldPosition(NumberFormat.FRACTION_FIELD);
b) Dar formato a fechas/horas.
Para dar formato a una fecha/hora dada, primero hay que crear un objeto
formateador de la clase SimpleDateFormat basado en un formato
específico, y luego utilizar su método format para convertir la fecha/hora en
una cadena construida a partir del formato elegido. Los símbolos que se
pueden utilizar para especificar un determinado formato son:
Símbolo Significado Presentación Ejemplo
y año numérica 2006
M mes del año numérica y alfabética 01 y enero
d día del mes numérica 15
h hora (1 a 12) numérica 10
H hora (0 a 23) numérica 13
m minutos numérica 30
s segundos numérica 55
S milisegundos numérica 678
E día de la semana alfabética viernes
D día del año numérica 230
F día de la semana del mes numérica 3 (3º X de enero)
w semana del año numérica 25
W semana del mes numérica 2
a marca am/pm alfabética PM
Z zona horaria alfabética GMT+07:00
En las presentaciones alfabéticas, 4 o más símbolos dan lugar a la forma
completa (por ejemplo: MMMM da lugar al nombre del mes completo:
enero); y menos de 4 da lugar a la forma abreviada o a la numérica (por
ejemplo: MMM da lugar a una abreviatura, ene; MM a un número de dos
dígitos, 01, y M a un número de un dígito, 1).
En las presentaciones numéricas un símbolo da lugar al mínimo número de
dígitos. Por ejemplo si yyyy da lugar a 2006, y, yy o yyy dan lugar a 06.
Cualquier otro carácter fuera de los rangos [‘A’..’Z’] y [‘a’..’z’] será tratado
como un separador.
El siguiente ejemplo almacena en salida la fecha y la hora actuales según el
formato especificado por patrón.
Date hoy = new Date();
String patron = “EEEE dd-MMM-yyyy, HH:mm:ss”;
SimpleDateFormat formato = new SimpleDateFormat(patron);
String salida = formato.format(hoy);
Un objeto Date, construido sin argumentos, encapsula el tiempo en milisegundos
transcurridos desde el 1 de enero de 1970.
Se puede utilizar también un objeto formateador basado en la localidad actual. En
este caso dicho objeto será creado y devuelto por alguno de los métodos de la clase
DateFormat. Por ejemplo, las siguientes líneas de código almacenarán en sFecha y
sHora la fecha y la hora según el formato local predeterminado.
Date hoy = new Date();
String sFecha, sHora;
DateFormat formato;
formato = DateFormat.getDateInstance();
sFecha = formato.format(hoy);
formato = DateFormat.getTimeInstance();
sHora = formato.format(hoy);

El método getDateInstance sin argumentos devuelve el formato utilizado para


mostrar la fecha en la localidad actual, y el método getTimeInstance sin
argumentos devuelve el formato utilizado en la localidad actual para mostrar la hora.
Ambos métodos pueden ser invocados con un argumento que especifique el estilo
con el que está formateada la fecha o la hora; o bien con el estilo y la localidad,
donde país es un objeto Locale.
DateFormat.getDateInstance(DateFormat.MEDIUM);
DateFormat.getDateInstance(DateFormat.DEFAULT, pais);
c) Dar formato a mensajes.
Para dar formato a un mensaje que se desea construir durante la
ejecución, hay que crear un objeto formateador de la clase
MessageFormat. Esta clase proporciona un medio para construir
mensajes con partes variables que serán reemplazadas durante la
ejecución. Por ejemplo:
Object[ ] argumentos = {new Double(.20), new Double(9000)};
MessageFormat mensaje = new MessageFormat("En la compra
realizada se descontó un {0} ahorrando {1}");
System.out.println(mensaje.format(argumentos));
2. ENTRADA (LECTURA DE DATOS).

El término lectura se aplica a la entrada de valores provenientes de


dispositivos periféricos y dirigidos hacia zonas de memoria. El periférico
puede ser el teclado, una unidad de disco o algún otro dispositivo. En esta
sección nos referimos al teclado.
La operación de lectura permite proporcionar datos durante la ejecución de
un programa. Los datos que se pueden leer son: enteros, reales, caracteres
o cadenas.

Flujos de entrada.

InputStream.
La clase InputStream es una clase abstracta que es una superclase de
todas las clases que representan un flujo en el que un destino lee bytes de
un origen. El método más importante de esta clase es read. Este método se
presenta de tres formas:
public int read ( ) throws IOException
public int read ( byte[ ] b) throws IOException
public int read ( byte[ ] b, int off, int len) throws IOException
La primera versión de read simplemente lee bytes individuales de un flujo
de entrada; concretamente lee el siguiente byte de datos disponible.
Devuelve un entero (int) correspondiente al valor ASCII del carácter leído al
número de bytes leídos si se lee un arreglo o bien -1 cuando en un intento
de leer datos se alcanza el final del flujo (si no hay más datos).
La segunda versión del método read lee un número de bytes de un flujo de
entrada y los almacena en un arreglo b. Devuelve un entero
correspondiente al número de bytes leídos, o bien -1 si no hay bytes
disponibles para leer porque se ha alcanzado el final del flujo.
La tercera versión del método read lee un máximo de len bytes a partir de
su posición off de un flujo de entrada y los almacena en un arreglo b.
Cada uno de estos métodos ha sido escrito para que bloquee la ejecución
del programa que los manda llamar hasta que toda la entrada solicitada
esté disponible.
Por su parte, la clase Reader es una clase abstracta que es superclase de
todas las clases que representan un flujo para leer caracteres desde un
origen. Sus métodos son similares a los de la clase InputStream, con la
diferencia de que utilizan parámetros de tipo char en lugar de tipo byte.
System.in.
La clase System.in define un objeto de la clase BufferedInputStream, cuya
referencia viene dada por in. El objeto está asociado a un flujo estándar de
entrada que por defecto es el teclado. Los elementos básicos de este flujo
son caracteres individuales, no cadenas como ocurre con el objeto out.
Entre los métodos de la clase se encuentra read(), que devuelve el carácter
actual en el buffer de entrada o un entero correspondiente al valor ASCII del
carácter leído. Debido a que Sysyem.in es un flujo con buffer, no se pasa
ninguna entrada al programa hasta que no se oprime la tecla <ENTER>.
Ejemplo:
char c;
int b;
c = (char) System.in.read( ); // Si capturamos: A
System.out.println(c); // Imprime: A
b = (byte) System.in.read( ); // Si capturamos: A
System.out.println(b); // Imprime: 65
Como no resulta práctico capturar la entrada, carácter por carácter, se hace
línea por línea. Para esto se utiliza primero la clase ImputStreamReader, de
la que se crea un objeto inicializado con System.in:
InputStreamReader endat = new InputStreamReader (System.in);

Este objeto que se crea, se utilize a su vez como argumento para inicializar
otro objeto de la clase BufferedReader, el cual permite capturar las líneas
de caracteres del teclado con el método readLine():
BufferedReader entrada = new BufferedReader ( endat );

El método readLine() crea y devuelve un objeto tipo cadena (String) con la


línea leída; la referencia a este objeto se asigna a una variable de tipo
String. El objeto de la clase BufferedReader se puede crear todo de una
sola vez en una sola sentencia, lo cual es la forma común de hacerlo en
todos los programas:
BufferedReader entrada = new BufferedReader (
new InputStreamReader ( System.in ) );
Scanner.
La clase Scanner, implementada a partir de la versión 1.5 de Java en el
paquete java.util, permite leer tipos primitivos de datos y secuencias de
cadenas utilizando métodos simples para leer texto. Scanner puede
separar las entradas en símbolos o subcadenas (tokens), usando un
patrón delimitador de separación de los espacios en blanco. Los
símbolos resultantes o subcadenas, se pueden convertir entonces en
valores de diversos tipos de datos usando algunos de los siguientes
métodos.

Con la clase Scanner, podemos leer símbolos o subcadenas utilizando


espacios en blanco como delimitadores, así mismo, podemos entrar
datos en un archivo. A continuación, se presenta un ejemplo que lee un
número entero a través del flujo System.in:

int i;
Scanner leeDato = new Scanner(System.in);
i = leeDato.nextInt();
Método Descripción
nextByte() Lee y devuelve la subcadena leída como un valor byte.
nextShort() Lee y devuelve la subcadena leída como un valor short.
nextInt() Lee y devuelve la subcadena leída como un valor int.
nextLong() Lee y devuelve la subcadena leída como un valor long.
nextFloat() Lee y devuelve la subcadena leída como un valor float.
nextDouble() Lee y devuelve la subcadena leída como un valor double.
nextBoolean() Lee y devuelve la subcadena leída como un valor bolean.
nextBigDecimal() Lee y devuelve la subcadena leída como un valor BigDecimal.
nextBigInteger() Lee y devuelve la subcadena leída como un valor BigInteger.
next() Lee y devuelve el símbolo o la subcadena leída.
Clases que encapsulan los tipos primitivos.
Java incorpora los tipos básicos como int, long, char, etc. Pero además
proporciona la declaración de una clase para cada uno de los tipos básicos,
denominadas clases envoltorio. El paquete java.lang proporciona las clases
Byte, Character, Short, Integer, Long, Float, Double y Boolean, que
encapsulan cada uno de los tipos primitivos y proporcionan los métodos
parseByte(), parseShort(), parseInt() y parseLong() respectivamente.
Estos métodos devuelven el equivalente byte, short, int, y long de la
cadena numérica que los llama. Existen métodos similares para las clases
Float y Double.
De acuerdo con esto, para obtener un número a partir de una cadena de
caracteres proporcionada por readLine habrá que ejecutar los siguientes
pasos:
1. Definir un flujo de entrada de la clase BufferedReader.
2. Leer la cadena de caracteres.
3. Convertir el objeto String en un número del tipo deseado.
A su vez, para convertir un número entero en una cadena decimal, han de
usarse las versiones de toString() definidas en las clases Byte, Short,
Integer, o Long. Las Integer y Long también proporcionan los métodos
toBinaryString(), toHexString() y toOctalString(), que convierten un valor
en una cadena binaria, hexadecimal u octal, respectivamente.
a) Clase Byte.
Esta clase se corresponde con el tipo byte, cada objeto de esta clase
contiene un entero de tipo byte. Las variables del tipo clase Byte son
referenciadas a objetos que se crean con el operador new. El constructor
que se aplica al crear un objeto de esta clase tiene como argumento un
número entero de tipo byte.
Formato para crear un objeto Byte:
byte variable;
Byte variable = new Byte (valor);

Además del constructor, la clase tiene diversos métodos, entre otros


parseByte(). Que es un método static que tiene como argumento una
cadena y devuelve el valor byte correspondiente a la conversión de los
números de la cadena. Al ser un método static, se llama desde la clase y
no desde un objeto de la clase. Si la conversión no es posible, genera una
excepción en tiempo de ejecución. A continuación se presentan algunos de
los métodos de esta clase.
Atributo Descripción
MIN_VALUE Valor más pequeño de tipo byte.
MAX_VALUE Valor más grande de tipo byte.

Método Descripción
doubleValue() Devuelve el objeto Byte como un valor double.
floatValue() Devuelve el objeto Byte como un valor float.
byteValue() Devuelve el objeto Byte como un valor byte.
shortValue() Devuelve el objeto Byte como un valor short.
intValue() Devuelve el objeto Byte como un valor int.
longValue() Devuelve el objeto Byte como un valor long.
parseByte(String) Convierte una cadena a un valor byte.
toString(int) Convierte un valor byte en una cadena (objeto
String).
valueOf(String) Crea un objeto Byte a partir de una cadena.
b) Clase Short.
Esta clase se corresponde con el tipo short, cada objeto de esta clase
contiene un entero de tipo short. Las variables del tipo clase Short son
referenciadas a objetos que se crean con el operador new. El constructor
que se aplica al crear un objeto de esta clase tiene como argumento un
número entero de tipo Short.
Formato para crear un objeto Short:
short variable;
Short variable = new Short (valor);

Además del constructor, la clase tiene diversos métodos, entre otros


parseShort(). Que es un método static que tiene como argumento una
cadena y devuelve el valor short correspondiente a la conversión de los
números de la cadena. Al ser un método static, se llama desde la clase y
no desde un objeto de la clase. Si la conversión no es posible, genera una
excepción en tiempo de ejecución. A continuación se presentan algunos de
los métodos de esta clase.
Atributo Descripción
MIN_VALUE Valor más pequeño de tipo short.
MAX_VALUE Valor más grande de tipo short.

Método Descripción
doubleValue() Devuelve el objeto Short como un valor double.
floatValue() Devuelve el objeto Short como un valor float.
byteValue() Devuelve el objeto Short como un valor byte.
shortValue() Devuelve el objeto Short como un valor short.
intValue() Devuelve el objeto Short como un valor int.
longValue() Devuelve el objeto Short como un valor long.
parseShort(String) Convierte una cadena a un valor short.
toString(int) Convierte un valor short en una cadena (objeto
String).
valueOf(String) Crea un objeto Short a partir de una cadena.
c) Clase Integer.
Esta clase se corresponde con el tipo int, cada objeto de esta clase
contiene un entero de tipo int. Las variables del tipo clase Integer son
referenciadas a objetos que se crean con el operador new. El constructor
que se aplica al crear un objeto de esta clase tiene como argumento un
número entero de tipo Integer.
Formato para crear un objeto Integer:
int variable;
Integer variable = new Integer (valor);

Además del constructor, la clase tiene diversos métodos, entre otros


parseInt(). Que es un método static que tiene como argumento una cadena
y devuelve el valor int correspondiente a la conversión de los números de la
cadena. Al ser un método static, se llama desde la clase y no desde un
objeto de la clase. Si la conversión no es posible, genera una excepción en
tiempo de ejecución. A continuación se presentan algunos de los métodos
de esta clase.
Atributo Descripción
MIN_VALUE Valor más pequeño de tipo int.
MAX_VALUE Valor más grande de tipo int.

Método Descripción
doubleValue() Devuelve el objeto Integer como un valor double.
floatValue() Devuelve el objeto Integer como un valor float.
byteValue() Devuelve el objeto Integer como un valor byte.
shortValue() Devuelve el objeto Integer como un valor short.
intValue() Devuelve el objeto Integer como un valor int.
longValue() Devuelve el objeto Integer como un valor long.
parseInt(String) Convierte una cadena a un valor int.
toString(int) Convierte un valor int en una cadena (objeto String).
valueOf(String) Crea un objeto Integer a partir de una cadena.
d) Clase Long.
Esta clase se corresponde con el tipo long, cada objeto de esta clase
contiene un entero de tipo long. Las variables del tipo clase Long son
referenciadas a objetos que se crean con el operador new. El constructor
que se aplica al crear un objeto de esta clase tiene como argumento un
número entero de tipo Long.
Formato para crear un objeto Long:
long variable;
Long variable = new Long (valor);

Además del constructor, la clase tiene diversos métodos, entre otros


parseLong(). Que es un método static que tiene como argumento una
cadena y devuelve el valor long correspondiente a la conversión de los
números de la cadena. Al ser un método static, se llama desde la clase y
no desde un objeto de la clase. Si la conversión no es posible, genera una
excepción en tiempo de ejecución. A continuación se presentan algunos de
los métodos de esta clase.
Atributo Descripción
MIN_VALUE Valor más pequeño de tipo long.
MAX_VALUE Valor más grande de tipo long.

Método Descripción
doubleValue() Devuelve el objeto Long como un valor double.
floatValue() Devuelve el objeto Long como un valor float.
byteValue() Devuelve el objeto Long como un valor byte.
shortValue() Devuelve el objeto Long como un valor short.
intValue() Devuelve el objeto Long como un valor int.
longValue() Devuelve el objeto Long como un valor long.
parseLong(String) Convierte una cadena a un valor long.
toString(int) Convierte un valor long en una cadena (objeto
String).
valueOf(String) Crea un objeto Long a partir de una cadena.
e) Clase Double.
Esta clase funciona de forma parecida a las clases enteras, sin embarga, a
partir de la versión 1.3 de JDK se incorporó el método parseDouble(), que
es un método static que tiene como argumento una cadena y devuelve el
valor double correspondiente a la conversión de los números de la cadena.
Al ser un método static, se llama desde la clase y no desde un objeto de la
clase. Si la conversión no es posible, genera una excepción en tiempo de
ejecución. A continuación se presentan algunos de los métodos de esta
clase.
Atributo Descripción
MIN_VALUE Valor más pequeño de tipo double.
MAX_VALUE Valor más grande de tipo double.
NaN No es un número.
POSITIVE_INFINITY Más infinito.
NEGATIVE_INFINITY Menos infinito.

Método Descripción
doubleValue() Devuelve el objeto Double como un valor double.
floatValue() Devuelve el objeto Double como un valor float.
byteValue() Devuelve el objeto Double como un valor byte.
shortValue() Devuelve el objeto Double como un valor short.
intValue() Devuelve el objeto Double como un valor int.
longValue() Devuelve el objeto Double como un valor long.
parseDouble(String) Convierte una cadena a un valor double. (Java 2)
toString(int) Convierte un valor double en una cadena (objeto String).
valueOf(String) Crea un objeto Double a partir de una cadena.
f) Clase Float.
Esta clase funciona de forma parecida a las clases enteras, sin embarga, a
partir de la versión 1.3 de JDK se incorporó el método parseFloat(), que
es un método static que tiene como argumento una cadena y devuelve el
valor float correspondiente a la conversión de los números de la cadena.
Al ser un método static, se llama desde la clase y no desde un objeto de
la clase. Si la conversión no es posible, genera una excepción en tiempo
de ejecución. A continuación se presentan algunos de los métodos de esta
clase.
Atributo Descripción
MIN_VALUE Valor más pequeño de tipo float.
MAX_VALUE Valor más grande de tipo float.
NaN No es un número.
POSITIVE_INFINITY Más infinito.
NEGATIVE_INFINITY Menos infinito.

Método Descripción
doubleValue() Devuelve el objeto Float como un valor double.
floatValue() Devuelve el objeto Float como un valor float.
byteValue() Devuelve el objeto Float como un valor byte.
shortValue() Devuelve el objeto Float como un valor short.
intValue() Devuelve el objeto Float como un valor int.
longValue() Devuelve el objeto Float como un valor long.
parseFloat(String) Convierte una cadena a un valor float. (Java 2)
toString(int) Convierte un valor float en una cadena (objeto String).
valueOf(String) Crea un objeto Float a partir de una cadena.
Excepciones.
Una excepción indica una condición anormal que no se debe encontrar durante la
ejecución normal de un programa. Así, una excepción es un error del programa que
sucede durante su ejecución. Por ejemplo, una entrada incorrecta de datos o una
división entre cero, Java lanza una excepción, que cuando no se captura envía un
mensaje sobre lo ocurrido y detiene su ejecución (las excepciones se lanzan
<throw>, no ocurren). Por lo que, si deseamos que la ejecución del programa no se
detenga, debemos capturarla <catch> y manejarla de manera adecuada para
reanudar la ejecución del programa.
Las excepciones en Java son objetos de subclases de Throwable. Por ejemplo, el
paquete java.io define una clase de excepción general denominada IOException
para excepciones de Entrada/Salida.
Una vez que se lanza una excepción, ésta no desaparece aunque el programador la
ignore (una excepción no se puede ignorar ni suprimir). Una condición de excepción
se debe reconocer y manejar. Una excepción no manejada se propagará
dinámicamente hasta alcanzar el nivel más alto de la función (main en Java). Así,
cuando ocurre una excepción y no existe un manejador para la excepción, la
excepción se propaga al método que hizo la llamada; si en este caso tampoco se
captura la excepción, se propaga al método que a su vez lo invocó; si llega al
método por el que empieza la ejecución, main(), y tampoco es capturada, la
ejecución (del programa) termina.
En general, el mecanismo de excepciones en Java permite, principalmente,
la detección de errores y su posible recuperación, permitiendo separar
explícitamente el código que maneja los errores, del código básico de una
aplicación, haciéndolo más legible. La forma general del mecanismo de
excepciones es:
try {
••• // Código de la aplicación.
}
catch ( clase_de_excepción e ) {
••• // Código de tratamiento de la excepción.
}
catch ( clase_de_excepción_2 e ) {
••• // Código de tratamiento para otra excepción.
}

El modelo de un mecanismo de excepciones consta básicamente de cinco


palabras reservadas: try, throw, throws, catch y finally.
* try. Bloque para detectar excepciones.
* catch. Manejador para capturar excepciones de los bloques try.
* throw. Expresión para lanzar excepciones.
* throws. Indica las excepciones que puede lanzar un método.
* finally. Bloque opcional, situado después de un catch de un try.
En general, podemos decir que los pasos del modelo para capturar
excepciones son:
1. Primero, el programador ‘intenta’ (try) una operación para anticipar
errores.
2. Cuando una rutina encuentra un error, se ‘lanza’ (throw) una excepción.
3. Por último, se anticipa la condición de error y se ‘captura’ (catch) la
excepción que se ha lanzado para su limpieza y/o recuperación.
El mecanismo de excepciones se completa con:
* Un bloque (finally) que, si se especifica, siempre se ejecuta al final de un
bloque try.
* Especificaciones de excepciones que dictaminan cuales excepciones, si
existen, puede lanzar un método.
Así, para capturar una excepción hay que hacer dos cosas: una, poner a
prueba el código que puede lanzar excepciones dentro de un bloque try; y
dos, manejar la excepción cuando se lance, en un bloque catch.
import java.io.*;
public class LeerDato
{
public static String dato()
{
BufferedReader leerCad = new BufferedReader (new InputStreamReader (System.in));
String num = ""; // Se inicializa num a cadena vacía.
try {
num = leerCad.readLine();
}
catch(IOException e){
System.err.println("Error: " + e.getMessage());
}
return num;
}
/* Método para convertir la cadena leída en entero (int) */
public static int numInt()
{
try {
return Integer.parseInt(dato());
}
catch(NumberFormatException e){
return 0;
}
}
} /* Fin de la clase * /
Ejemplo del uso de un bloque try-catch para lectura de datos aplicando la clase Scanner.

/* Método para leer un numero de tipo int, usando la clase Scanner */


public static int tipoInt()
{
Scanner lee = new Scanner(System.in);
try {
return lee.nextInt();
}
catch(InputMismatchException e){
return 0;
}
}

/* Método para leer un numero de tipo double, usando la clase Scanner */


public static double tipoDouble()
{
Scanner lee = new Scanner(System.in);
try {
return lee.nextDouble();
}
catch(InputMismatchException e){
return 0;
}
}
EL ESTILO DE PROGRAMACIÓN.

Cada persona tiene una manera diferente de ver las cosas, lo cual se ve
reflejado en la forma en que visualiza un problema y el enfoque con el cual
le da solución. Asimismo, los analistas de sistemas y los programadores,
desarrollan sus programas de manera diferente según su punto vista. Por
lo cual, si se pide a diversas personas crear un programa para resolver un
mismo problema, cada una de ellas creará un programa diferente y aún
cuando las diferencias no sean muy grandes, no existirán dos programas
exactamente iguales, debido a que cada uno aplicó su estilo de programar.
El buen estilo de programación, es una de las características más
importantes que debe tener un programador. Un programa con buen estilo
es más fácil de leer, de corregir y de mantener. Aunque la experiencia
proporciona el estilo, existen una serie de reglas que se recomiendan
seguir desde el principio del aprendizaje de la programación.
a) Sangrías.
Los programas escritos en Java no exigen reglas muy estrictas en su
escritura, salvo el no usar las palabras clave como nombres de
identificadores y el respeto a las mayúsculas y minúsculas en los nombres
de las constantes declaradas, clases, objetos, métodos y paquetes. Sin
embargo, una práctica habitual y recomendable es el uso de sangrías en los
bloques, métodos y clases.

b) Comentarios.
Un comentario es un texto que explica una instrucción o procedimiento, se
sitúa en cualquier parte del programa y es ignorado por el compilador. Estos
comentarios pueden ser tan largos como se desee y son una parte
importante de la documentación de un programa, ya que ayudan al
programador y a otras personas a la comprensión del programa.
Formato:
1. /* Comentario de una o más líneas */
2. // Comentario de una sola línea
Se recomienda colocar comentarios en la cabecera del programa que
indiquen por lo menos lo siguiente:
- Nombre del programador.
- La fecha de la versión actual.
- Una breve descripción de lo que hace el programa.

c) Líneas en blanco.
Una forma de hacer un programa más legible es dejar líneas en blanco
entre partes importantes o que estén lógicamente separadas. Por ejemplo:
Entre la cabecera y la sección de declaraciones, entre métodos, antes de
main, etc.
d) Otros consejos prácticos.
•Elegir nombres de identificadores significativos.
•Evitar puntos y comas innecesarios.
•Tratar de que las líneas de programa no sean mayores de 80 caracteres.
•Alinear operaciones o separadores en líneas consecutivas, definiendo claramente
los métodos, estructuras y las operaciones anidadas dentro de ellas.
•Blancos no significativos, esto es, incluir un espacio a cada lado de un operador y
después de las comas, puntos y comas y dos puntos.
•Poner cada sentencia en una línea distinta.
•Si una sentencia continúa en otra línea, se debe(n) sangrar la(s) línea(s)
siguiente(s).
•Insertar líneas en blanco antes del programa principal, así como en cualquier
segmento o bloques de sentencias significativas.
•Utilizar espacios entre los elementos de una sentencia para hacerla más legible.
•Los números de tipo real no deben utilizarse para comprobar relaciones de igualdad
o desigualdad (==, !=, < o >), ya que éstos números son manejados en forma
aproximada por la computadora.
•Es conveniente verificar posibles divisiones entre cero, así como raíces cuadradas
de números negativos dentro del programa, lo cual puede provocarnos errores. Esto
se puede evitar mediante el uso de rutinas de validación y de captura de
excepciones.
•Asegurarse que cada sentencia o línea termine con punto y coma (;).
UNIVERSIDAD AUTONOMA DE SINALOA
FACULTAD DE INFORMÁTICA DE MAZATLAN

PROGRAMACIÓN I
Sentencias de Control
TITULAR DE LA MATERIA:
DR. JOSÉ NICOLÁS ZARAGOZA GONZÁLEZ
SENTENCIAS DE CONTROL.

Las sentencias de control o estructuras de control, son las


encargadas de controlar las acciones que llevan a cabo un método o un
programa. También se les denomina estructuras lógicas de la
programación y su función principal es la de crear programas que
realicen acciones en forma lógica y ordenada. Básicamente se clasifican
en tres grupos o tipos y, cada una de estas estructuras puede estar a su
vez, compuesta por una o varias sentencias:
A) Estructuras Secuénciales.
B) Estructuras Selectivas.
C) Estructuras Repetitivas.
A) Estructuras Secuénciales.
Una secuencia es la indicación de un proceso, el cual puede involucrar
una o más acciones. También podemos decir que es la ejecución de una
tarea, seguida inmediatamente por otra. Una secuencia o bloque puede
ser muy simple e indicar una sola acción o instrucción; o puede ser muy
compleja e implicar un conjunto de acciones.

B) Estructuras Selectivas.
Las estructuras selectivas, también llamadas de selección o de
comparación, se basan en la evaluación de expresiones lógicas a través
del uso de los operadores de relación y operadores lógicos. Existen
varios tipos de estructuras de selección, las cuales veremos a
continuación:
1. SENTENCIA: if
Esta estructura indica la elaboración de un proceso de acuerdo a una
expresión que se evalúa denominada expresión condicional. La expresión
condicional puede tomar dos posibles valores, estos valores son: verdadero
y falso.
En Java, una expresión es verdadera cuando al evaluarse devuelve un
valor true; y es falsa, cuando devuelve un valor false.
En su forma más simple, la sentencia if permite que un programa ejecute
condicionalmente una sentencia. A continuación se muestra la forma más
simple de if.

if (expresión) sentencia;

La expresión puede ser cualquier expresión válida de Java. Si la expresión


se evalúa como verdadera, se ejecutará la sentencia. Si no lo es, se pasa
por alto la sentencia y se ejecuta la línea de código que sigue a if.
Normalmente, la expresión evaluada por el if compara un valor con otro
utilizando un operador de relación. Los operadores de relación (también
llamados de comparación) se utilizan para relacionar o comparar dos
expresiones u operandos. Los operandos pueden ser de cualquier tipo
primitivo. Aún cuando no se recomienda el uso de números reales. los
operadores de relación son:
Significado Símbolo Usado Símbolo Usado en
en Java Matemáticas
Mayor que > >
Mayor o igual que >= ≥
Igual a (igualdad) == =
Diferente de o Distinto a != ≠
Menor o igual que <= ≤
Menor que < <

if ( numero > 0 ) System.out.println("El numero es: Positivo");


if ( numero < 0 ) System.out.println("El numero es: Negativo");
2. SENTENCIA: if - else
Se puede añadir una sentencia else a un if. Cuando se hace esto, la
sentencia queda de la siguiente forma:

if (expresión) sentencia1;
else sentencia2;

De acuerdo al valor que tome la expresión condicional, es el camino que


seguirá nuestro programa. Si la expresión evaluada es verdadera, realizará
el proceso o procesos indicados. De lo contrario, si la expresión condicional
es falsa, procederá a ejecutar el proceso o procesos correspondientes. En
ningún caso se ejecutarán las dos sentencias.

if ( numero > 0 ) System.out.println("El numero es: Positivo");


else System.out.println("El numero es: Negativo");
En Java se pueden enlazar dos o más sentencias. Esto se llama un bloque de
código. Para crear un bloque de código, se delimitan las sentencias en el bloque
con llaves de apertura y de cierre. Una vez hecho esto, las sentencias forman una
unidad lógica, que se puede utilizar en cualquier lugar donde pueda hacerlo una
sentencia sencilla.
La forma general de if utilizando bloques de código es:

if (expresión) {
sentencia1;
sentencia2;
. . .
sentenciaN;
}
else {
sentencia1;
sentencia2;
. . .
sentenciaN;
}

Si la expresión se evalúa como verdadera, entonces se ejecutarán todas las


sentencias contenidas en el bloque de código asociado con if. Si la expresión es
falsa, entonces se ejecutarán todas las sentencias del bloque else.
EL OPERADOR: ?
Java, al igual que C tiene un operador ternario ( ? : ), que puede sustituir a
las sentencias if - else y se utiliza en expresiones condicionales, que tienen
la forma:
valor = operando1 ? operando2 : operando3 ;

La expresión operando1 debe ser de tipo primitivo. La evaluación se realiza


de la siguiente manera:
* Si el resultado de la evaluación de operando1 es verdadera o true, el
resultado de la expresión condicional es operando2 y se asigna a valor.
* Si el resultado de la evaluación de operando1 es falsa o false, el resultado
de la expresión condicional es operando3 y se asigna a valor.
La diferencia fundamental entre la sentencia if y el operador ? : es que este
último tiene un valor. Las expresiones de resultado (operando2 y
operando3) deben tener tipos de asignación compatibles. El tipo de una
expresión de resultado debe ser asignable al tipo de la otra sin una
conversión explícita, con independencia de cuál sea asignable al otro. El
tipo del resultado del operador condicional es el más general de los dos
tipos. El operador ? solo acepta ejecutar una sola sentencia como
resultado de la evaluación.
mayor = (a > b) ? a : b;
SENTENCIAS: if "anidadas"
Cuando una sentencia if se encuentra dentro de otra sentencia if o de un
else, se dice que está anidada dentro del if. Un if anidado puede aparecer
dentro de un bloque de sentencias que se encuentren dentro de un if más
externo. Aunque Java acepta varios niveles de anidamiento de if, no se
recomiendan anidamientos muy largos. También es conveniente sangrar los
if anidados y sus bloques de código para hacer más claros y entendibles los
programas. Con los if anidados, un else siempre se asocia al if más
cercano dentro del mismo bloque que aún no tenga un else asociado a él.
La forma general de la sentencia if anidada es la siguiente:

if (expresión) sentencia;
else
if (expresión) sentencia;
else
if (expresión) sentencia;
...
else sentencia;
* Uso de sentencias if anidadas:
if ( a > b )
if ( a > c )
mayor = a;
else
mayor = c;
else
if ( b > c )
mayor = b;
else
mayor = c;

System.out.println("El mayor es: "+mayor);

* Combinación de sentencia if y operador ? :


if ( a > b )
mayor = ( a > c ) ? a : c;
else
mayor = ( b > c ) ? b : c;

System.out.println("El mayor es: "+mayor);


import java.io.*;
class Compara
{
public static void main(String args[ ]) throws IOException
{
BufferedReader Leer = new BufferedReader (new InputStreamReader (System.in));
int a, b, c, mayor;
String num = " ";
System.out.println("Programa que compara tres numeros y define cual es el mayor.\n\r");

System.out.print("Dame el primer numero: ");


num = Leer.readLine();
a = Integer.parseInt(num);
System.out.print("Dame el segundo numero: ");
num = Leer.readLine();
b = Integer.parseInt(num);
System.out.print("Dame el tercer numero: ");
num = Leer.readLine();
c = Integer.parseInt(num);

if ( a > b )
mayor = ( a > c ) ? a : c;
else
mayor = ( b > c ) ? b : c;
System.out.println("El mayor es: "+mayor);
} /* fin del main */
} /* fin de la clase */
3. SENTENCIA: switch
La sentencia switch es la sentencia de selección múltiple de Java. Se usa
para seleccionar y ejecutar una sola opción de entre múltiples opciones.
Este tipo de estructura se utiliza comúnmente en los menús, donde según la
opción seleccionada, se ejecutará una (y solo una) secuencia de
instrucciones. Corresponde a la estructura de control En Caso De.
El formato general de la sentencia switch es el siguiente:

switch (variable) {
case (constante1) : conjunto de sentencias 1;
break;
case (constante2) : conjunto de sentencias 2;
break;
. . .
case (constanteN) : conjunto de sentencias N;
break;
default : sentencias por defecto;
}
Cada conjunto de sentencias puede contener una o más instrucciones o
sentencias. la parte default es opcional y equivale a de lo contrario.
La sentencia switch funciona comparando la variable con todas las
constantes. Tan pronto como encuentra una igualdad, se ejecuta el
correspondiente conjunto de sentencias. Si se omite la sentencia break, la
ejecución continúa hasta el final del switch, ejecutando todas las
sentencias antes y después de la igualdad. Se puede considerar a los case
como etiquetas. La ejecución del conjunto de sentencias continúa hasta que
se encuentra un break o el final del switch. La principal aplicación de esta
instrucción es en los menús de opciones.
La diferencia entre if y switch, es que la sentencia switch solo puede
probar una igualdad, mientras que if puede evaluar una expresión con
operadores de relación o lógicos.
switch (op) {
case ('a') : a = x + y;
System.out.println("la suma es: "+a);
break;
case ('b') : b = x - y;
System.out.println("la resta es: "+b);
break;
case ('c') : c = x * y;
System.out.println("la multiplicacion es: "+c);
break;
case ('d') : d = (y != 0) ? x / y : 0 ;
System.out.println("la division es: "+d );
break;
case ('e') : z = x % y;
System.out.println("el modulo es: "+z);
break;
default : System.out.println("No seleccionaste ninguna operación.");
}
C) Estructuras Repetitivas.
Las estructuras de control que permiten la repetición de una serie de
sentencias se denominan ESTRUCTURAS DE REPETICION O DE
ITERACION, y los procesos que se ejecutan dentro de estas estructuras se
denominan ciclos, bucles, gazas, iteraciones o lazos (en inglés, loop). El
cuerpo del ciclo contiene las sentencias que se repiten, hasta que se
cumpla o deje de cumplirse una cierta condición. Esta condición puede
estar o no predefinida.
Java proporciona tres estructuras de control repetitivas:
1.- while (estructura: Mientras - Haz).
2.- do (Haz – Hasta, funciona de manera similar a la estructura: Repite -
Hasta Que).
3.- for (estructura: Desde - Hasta - Haz).
1. SENTENCIA: while
La estructura repetitiva while (mientras), indica la repetición de una
sentencia o bloque de sentencias MIENTRAS se cumpla una determinada
condición. Cuando la sentencia while se ejecuta, lo primero que hace es
evaluar una expresión lógica o booleana. La secuencia se ejecuta
UNICAMENTE si la expresión condicional es verdadera (true). Esto es,
PRIMERO SE PREGUNTA POR LA CONDICION Y SI ESTA ES
VERDADERA, ENTONCES SE EJECUTA LA SECUENCIA O PROCESOS.
Puede darse el caso de que el proceso inscrito dentro de esta estructura no
se ejecute nunca, lo cual sucede cuando la expresión evaluada resulta falsa
(false).
La forma general de esta sentencia es:
while (condición) sentencias;

La condición puede ser cualquier expresión booleana y la sentencia puede


ser una sentencia simple o un bloque de sentencias que hay que repetir;
cuando se trate un bloque de sentencias, estas deben ir encerradas entre
llaves { }. El proceso se repite mientras la expresión sea verdadera.
Después de cada iteración, se evalúa la expresión, si es verdadera, el ciclo
se repite de nuevo; si cambia de verdadera a falsa, la sentencia while
termina y el programa continúa en la siguiente sentencia del programa.
class Ciclo1
{

public static void main(String args[ ]) {


int i = 1;
System.out.println("Programa que imprime la lista del 1 al 10, usando
WHILE:");
while ( i <= 10 ) { /* MIENTRAS (i<=10) */
System.out.println("Numero "+i);
i++; /* esta instruccion equivale a: i = i + 1 */
} /* fin del ciclo WHILE */
} /* fin del main */
} /* fin de la clase */
2. SENTENCIA: do - while
La estructura do - while indica la acción repetitiva de una secuencia
MIENTRAS QUE una condición sea cumplida. PRIMERO SE EJECUTA LA
SECUENCIA O PROCESO Y DESPUES SE PREGUNTA POR LA
EXPRESION CONDICIONAL. De modo que la secuencia SIEMPRE se
ejecuta por lo menos una vez antes de preguntar por la condición. La forma
general del ciclo do - while es la siguiente:
do {
sentencias;
} while (condición);
La condición puede ser cualquier expresión booleana y la sentencia puede
ser una sentencia simple o una sentencia compuesta, cuando se trata de
una sentencia compuesta, se debe encerrar entre llaves. Si solo se está
repitiendo una sentencia, no es necesario colocar las llaves, pero siempre
se acostumbra su uso para delimitar el principio y fin de los procesos
inscritos dentro de la estructura. La sentencia do - while especifica un ciclo
condicional que se repite mientras la condición evaluada es verdadera
(true). Después de cada iteración, se evalúa la condición. Si la condición es
verdadera, el cuerpo del ciclo se repite. Si la condición es falsa, el ciclo
termina y se sale de él, continuando la ejecución del programa en la
siguiente línea después del while.
class Ciclo2
{

public static void main(String args[ ]) {


int i = 1;
System.out.println("Programa que imprime la lista del 1 al 10, usando
DO - WHILE:");
do { /* HAZ */
System.out.println("Numero "+i);
i++; /* esta instruccion equivale a: i = i + 1 */
} while ( i <= 10 ); /* MIENTRAS (i<=10) */
} /* fin del main */
} /* fin de la clase */
3. SENTENCIA: for
La sentencia for se utiliza para repetir una sentencia o bloque de
sentencias un número determinado de veces. La forma general del ciclo for
es:
for (Valor_Inicial; Comprobación_Condicional; Incremento) sentencia;

El Valor_Inicial o sección de Inicialización, se utiliza para dar un valor inicial


a la variable que controlará el ciclo. A esta variable se le conoce como
variable de control del ciclo o simplemente, variable de control. La sección
de inicialización se ejecuta solo una vez, antes de que comience el ciclo. La
parte de comprobación condicional del ciclo verifica la variable de control
del ciclo frente a un valor objetivo cada vez que se ejecuta el ciclo. Si la
comprobación condicional se evalúa como verdadera, el ciclo se repite. Si
es falsa, el ciclo se detiene y la ejecución del programa se reanuda en la
siguiente línea de programa que sigue al ciclo. La comprobación condicional
se lleva a cabo al principio del ciclo cada vez que el ciclo se repite. La parte
de incremento del for se ejecuta al final de cada ciclo, esto es, después de
que se haya ejecutado la sentencia o bloque de sentencias, pero antes de
la comprobación condicional. La sección de incremento permite aumentar (o
disminuir) el valor de la variable de control en una cierta cantidad, cada vez
que se ejecuta el ciclo.
class Ciclo3
{

public static void main(String args[ ]) {


int i;
System.out.println("Programa que imprime la lista del 1 al 10, usando
FOR:");
for ( i = 1; i <= 10; i++ ) { // DESDE: i=1; MIENTRAS: i<=10; INCREMENTA+1: i++
System.out.println("Numero "+i);
} /* fin del ciclo FOR */
} /* fin del main */
} /* fin de la clase */
DISEÑO DE CICLOS.

Existen una serie de reglas que es conveniente conocer y seguir si se


desean diseñar ciclos sin errores, algunas de ellas se presentan a
continuación.
1.- Inicialización de variables.
Siempre que se trabaje con cualquier tipo de variables deben inicializarse.
Ejemplo: i = 1;

2.- Ciclos infinitos.


Un ciclo que se repite continuamente y no se termina nunca se llama ciclo
infinito. Los ciclos infinitos son en la mayoría de los casos, producto de un
error lógico en la comparación de la condición que se evalúa.

3.- Terminación de un ciclo.


Si un programa está leyendo una lista de valores o ejecutando una serie de
cálculos dentro de un ciclo, se debe de incluir algún tipo de instrucción para
terminar el ciclo.
En general, existen dos métodos para controlar o terminar un ciclo:
a) Ciclos controlados por contador.
b) Ciclos condicionales.
a) Ciclos controlados por contador (ciclos de conteo).
Un ciclo controlado por un contador o ciclo de conteo, es un ciclo cuyas
iteraciones se controlan por una variable cuyo valor representa a un
contador. Esto se hace mediante una variable de control del ciclo que actúa
como contador.
Un ciclo controlado por un contador consta de tres partes, además del
cuerpo y de la condición de salida.
i. Inicialización de la variable de control del ciclo.
ii. Comprobación del valor de la variable de control del ciclo.
iii. Incremento del valor de la variable de control del ciclo.

El formato de estos ciclos es:


1. Inicializar la variable contadora (Establecer la Variable contadora a un
valor inicial).
2. while ( Variable Contadora < Valor Final ) {
...
Incrementar la Variable Contadora (normalmente en 1)
}
Se utiliza un ciclo controlado por contador cuando se conoce con
anticipación el número exacto de iteraciones que se deben ejecutar. Estos
ciclos pueden construirse con estructuras while, do – while o for, sin
embargo, las estructuras más adecuadas para este tipo de ciclos son los
ciclos for. Cada vez que el cuerpo de un ciclo se ejecuta el valor del
contador se incrementa. Aunque normalmente el contador se incrementa
en 1, también podemos hacer que se incremente en 2, 3 o más.
Normalmente los contadores se inicializan a 0 ó 1, dependiendo del
diseño del programa. En el uso de contadores se deben tener en cuenta
los siguientes factores:
i. El valor inicial.
ii. El valor final.
iii. El operador relacional utilizado para la comprobación de la terminación
del ciclo.
b) Ciclos condicionales.
Los ciclos condicionales o ciclos controlados por condición, se utilizan
cuando no se sabe con anticipación, el número exacto de iteraciones a
realizar. Existen diferentes técnicas para realizar el control del ciclo.
i). Solicitar al usuario la continuación del ciclo.
Este método consiste en preguntar al usuario si existen más entradas. Este
ciclo se ejecutará mientras la respuesta a la pregunta, sea ‘S’ o ‘s’.
ii). Valor centinela.
Un centinela es un valor utilizado para señalar el final de una lista de datos.
El valor elegido debe ser totalmente diferente de los posibles valores de la
lista para que pueda ser usado para señalar el fin de la lista. Por ejemplo, si
el ciclo lee y suma una lista de números positivos, se puede utilizar un
número negativo como valor centinela para indicar el fin de la lista.
iii). Uso de banderas o interruptores.
Una bandera o interruptor (flag), es una variable lógica o booleana que se
utiliza para conservar el estado (verdadero o falso) de una condición. Se
denomina bandera o interruptor por asociarse con un interruptor
(encendido/apagado) o con una bandera (arriba/abajo). El valor del
interruptor debe inicializarse antes de comenzar el ciclo y debe cambiar su
valor (estado) dentro del cuerpo del ciclo para preparar la siguiente
iteración.
4.- Condiciones compuestas.
En algunas ocasiones, las expresiones de control de un ciclo pueden ser
condiciones lógicas compuestas.
Ejemplos:
1. while (( Datos >= 100 ) && ( Datos <= 1000 )) {
2. while ! ( A <= 100 ) {
3. while (( A < B ) && ( B < C )) {
4. while (( Opcion != ‘N’ ) && ( Opcion != ‘n’ ) || Terminado ) {

Comparación de los ciclos while y do-while.


Los ciclos while y do-while funcionan de la misma manera. La elección de
uno u otro dependerá del tipo de problema y del diseño del programa.
Aunque con la sentencia while se pueden escribir casi todos los
algoritmos repetitivos, en muchas ocasiones la sentencia do-while facilita
la escritura de algoritmos. Con la sentencia do-while, el ciclo siempre se
ejecuta al menos una vez. A continuación se presenta una comparación
entre los ciclos while y do-while.
Ciclos while Ciclos do-while
1. La condición (expresión lógica) se 1. La condición se verifica después de
verifica antes de que se ejecute el que el cuerpo del ciclo se ha ejecutado.
cuerpo del ciclo.
2. Puede suceder que cuerpo del ciclo no 2. El cuerpo del ciclo se ejecutará al
se ejecute nunca (si la condición es menos una vez, sin importar cual sea el
falsa). valor de la condición.
3. Las variables de la condición, deben 3. Las variables de la condición no
haber sido inicializadas antes de entrar necesitan ser inicializadas antes de
en el ciclo while, de modo que la empezar el ciclo do-while. A esas
condición pueda ser verificada. variables se les pueden asignar valores
en el cuerpo del ciclo, que se ejecutarán
antes de que se verifique la condición.
4. Si la condición es verdadera, el cuerpo 4. Si la condición es falsa, el cuerpo del
del ciclo se ejecutará y continuará el ciclo se ejecutará y se dará por
ciclo. terminado, continuando en la siguiente
sentencia.
5. Para evitar un ciclo infinito, la 5. Para evitar un ciclo infinito, la
condición debe contener una variable condición debe contener una variable
cuyo valor se modifique dentro del cuyo valor se modifique dentro del
cuerpo del ciclo, cambiando su valor a cuerpo del ciclo, cambiando su valor a
falso. falso.
Complementar una condición.
En un ciclo while o do-while, se puede complementar una condición
utilizando la lógica inversa. La complementación de una condición simple
se puede hacer cambiando el operador relacional de la forma siguiente:
Operador Operador que complementa
< >=
<= >
> <=
>= <
== !=
!= ==

Por ejemplo, el complemento de x <= y es x > y.


Si la expresión es: Bandera, el complemento es ( ! Bandera ).
El Teorema de Morgan sirve para complementar una expresión compuesta:
Expresión Compuesta Complemento
( Expresión 1 ) && ( Expresión 2 ) ( Expresión 1 ) || ( Expresión 2 )
( Expresión 1 ) || ( Expresión 2 ) ( Expresión 1 ) && ( Expresión 2 )

Las siguientes expresiones lógicas compuestas tiene el mismo valor:


! ( Expresión1 && Expresión2 ) = ( ! Expresión1 ) || ( ! Expresión2 )
! ( Expresión1 || Expresión2 ) = ( ! Expresión1 ) && ( ! Expresión2 )
Sintaxis del ciclo for.
La sentencia for representa una estructura de repetición, donde las
sentencias se ejecutan un número fijo de veces, el cual depende del
contador del ciclo (variable de control) y del valor inicial y condición final del
mismo.
Número de iteraciones de un ciclo for con incremento (i++).

for Iteraciones
Valor Inicial < Valor Final Valor Final - Valor Inicial + 1
Valor Inicial = Valor Final 1
Valor Inicial > Valor Final 0

Número de iteraciones de un ciclo for con decremento (i--).

for iteraciones
Valor Inicial < Valor Final 0
Valor Inicial = Valor Final 1
Valor Inicial > Valor Final Valor Inicial - Valor Final + 1
Ciclos Anidados.
El cuerpo de un ciclo puede contener cualquier tipo de sentencias de
secuencia (simples o compuestas), selectivas o repetitivas. Cuando un
ciclo está contenido dentro de otro ciclo, se denominan ciclos o ciclos
anidados. Cualquiera de los ciclos de Java puede estar anidado dentro de
cualquier otro ciclo. El siguiente fragmento de programa escribe 10 veces
en pantalla los números del 1 al 10.
for (i=1; i<=10; i++) {
for (j=1; j<=10; j++)
System.out.println( j ); }

Selección del Tipo de Ciclo Adecuado.


1. El ciclo for es el más rápido de ejecutar, por lo que sí el número de
iteraciones se conoce de antemano, se debe utilizar for.
2. Si el ciclo siempre se debe ejecutar al menos una vez y el número de
iteraciones no se conoce por adelantado, se utilizará do-while.
3. Si el ciclo no se debe ejecutar mientras la condición sea falsa y se
desconoce el número de iteraciones por adelantado, se utiliza while. Este
tipo de ciclo es el más lento de los tres tipos.
Uso de la sentencias break y continue en un ciclo.
La sentencia break se puede utilizar en Java de tres formas diferentes. En
primer lugar para finalizar una secuencia de sentencias en una sentencia
switch. En segundo lugar, para salir desde cualquier punto dentro de un
ciclo, pasando por alto su expresión de terminación normal. Cuando la
sentencia break se encuentra dentro del cuerpo de un ciclo, el ciclo termina
inmediatamente y el control del programa continúa en la sentencia siguiente
al fin del ciclo. La sentencia break se puede utilizar con cualquiera de los
tres ciclos de Java (for, do-while y while). En tercer lugar, se puede utilizar
en vez de la instrucción goto que no existe en Java. Su formato es:
break etiqueta;

El siguiente programa muestra la lista de números del 1 al 10, a pesar de


que la condición indica llegar hasta el 100. Esto es debido a que al llegar al
número 10 y verificar la condición, da por terminado el ciclo.
int i;
...
for ( i = 1; i < 100; i++ ) {
System.out.println("Numero "+i);
if (i == 10) break; }
El siguiente es un programa que entra en un ciclo infinito hasta que se oprime
la tecla 'N'.
char tecla = ‘ ‘;
...
for ( ; ; ) {
try{ tecla = (char) System.in.read(); /* lee un carácter */ }
catch(IOException e){ System.err.println("Error: " + e.getMessage());
}
if ((tecla == 'n') || (tecla =='N')) break; }

El tercer uso de la sentencia break, normalmente tiene que ver con la salida
de ciclos anidados, para poder llevarlo a cabo, el bloque de código debe
contener la sentencia break. No se puede transferir el control a un bloque del
código que no encierre la sentencia break.
boolean t = true;
...
uno : {
dos : {
if (t) break uno; // Sale del bloque dos al uno.
}
}
La sentencia continue funciona de manera un tanto opuesta a la sentencia
break ya que obliga a que se produzca la siguiente iteración del ciclo,
saltándose todas las instrucciones entre la sentencia y la condición de
prueba. En los ciclos while y do-while, una sentencia continue hará que el
control vaya directamente a la condición de prueba y que continúe después
el proceso del ciclo. En el ciclo for, se lleva a cabo el incremento del valor
de la variable de control del ciclo, se ejecuta la prueba condicional y el ciclo
continúa.
El siguiente programa muestra todos los números nones entre 1 y 100.
int i;
...
for ( i = 1; i < 101; i++ ) {
if ( i%2 == 0) continue;
System.out.println("Numero "+i); }

La sentencia continue, al igual que la sentencia break, puede definir una


etiqueta para indicar qué ciclo es el que debe continuar. El formato es:
continue etiqueta;
Depuración de Programas que usan Ciclos.
1. Es conveniente diseñar primero el ciclo en pseudocódigo y ver como
funciona. Una vez depurado el algoritmo, puede seleccionarse la estructura
adecuada en Java.
2. Debe tenerse cuidado con los ciclos infinitos, los cuales se pueden
producir por alguna de las siguientes razones:
a) No haber inicializado la variable de control del ciclo while (error en
compilación) antes de comenzar el ciclo.
b) No modificar el valor de la variable de control dentro del ciclo. En un
ciclo while la condición que no cambia de verdadera a falsa, produce un
ciclo infinito. En un ciclo do-while la condición que no cambia de verdadera
a falsa, producirá un ciclo infinito.
c) Las condiciones de igualdad o desigualdad pueden producir ciclos
infinitos, sobre todo si trabajamos con números reales.
3. Si se utiliza un ciclo controlado por un valor centinela o bandera, se debe
indicar al usuario mediante un mensaje, que valor debe introducir para
terminar el ciclo.
4. Si el cuerpo del ciclo contiene más de una sentencia, éstas deben
encerrarse entre llaves de inicio { y de fin }. De lo contrario sólo se repetirá
la primera sentencia del ciclo.
5. Asegurarse de inicializar a cero una variable utilizada como acumulador
en una sumatoria y de inicializar a uno una variable usada como
acumulador en una productoria (multiplicación repetida).
6. Revisar las condiciones de frontera de las expresiones lógicas, para
evitar que sobre o que falte de contar un elemento.
7. Las variables de control de los ciclos for pueden ser de cualquier tipo
entero.
8. La condición lógica de while, debe cumplirse la primera vez para que se
pueda ejecutar el ciclo.
9. No se recomienda el uso de un ciclo do-while, a menos que se tenga la
seguridad de que el ciclo siempre se ejecuta al menos una vez.
10. Inicializar adecuadamente una variable antes de que comience el ciclo.
11. Si se utilizan número reales como variables de control, nunca debe
hacerse una prueba de igualdad para terminar el ciclo.
UNIVERSIDAD AUTONOMA DE SINALOA
FACULTAD DE INFORMÁTICA DE MAZATLAN

PROGRAMACIÓN I
Clases y Métodos
TITULAR DE LA MATERIA:
DR. JOSÉ NICOLÁS ZARAGOZA GONZÁLEZ
CLASES Y MÉTODOS.

Las clases son la base de la programación orientada a objetos.


Una clase es un tipo definido por el usuario que describe los atributos y
los métodos de los objetos que se crearán a partir de la misma.
Los atributos o variables de instancia definen el estado de un
determinado objeto y los métodos son las operaciones que definen su
comportamiento. Forman parte de estos métodos los constructores, que
permiten iniciar un objeto, y los destructores, que permiten destruirlo.
Los atributos y métodos se denominan en general miembros de la clase.
MÉTODOS.

Un método es un bloque de código que tiene un nombre, un tipo de


acceso, un tipo de retorno y una lista de argumentos o parámetros.
También pueden contener palabras clave asociadas como static, abstract
y final. Los métodos en Java son similares a las funciones y
procedimientos en la programación modular. Una definición de un método
consta de dos partes: cabecera y cuerpo. La sintaxis para definir un método
es la siguiente:

[modificador] tipo_devuelto método ( Lista de parámetros )


{
Declaración de variables locales
Sentencias ejecutables
return expresión; // No se escribe si el método es de tipo void.
}
modificador Es una palabra clave que especifica desde donde puede ser llamado
el método. Existen cuatro niveles de acceso: public, protected,
private o por omisión, que son los mismos definidos en la
declaración de variables.
tipo_devuelto Especifica el tipo de dato devuelto por el método. Éste puede ser
cualquier tipo primitivo o referenciado. Para indicar que un método
no devuelve nada se utiliza la palabra reservada void, en este caso
se omite la sentencia return o se escribe sola, sin ninguna
expresión.
método El nombre de un método puede ser cualquier identificador válido,
pero no puede ser una palabra reservada Java. Entre los
programadores se tiene el convenio de que la primera letra del
nombre del método se escribe con minúsculas. Un método puede
tener palabras reservadas asociadas como: static, abstract y final.
Lista de La lista de parámetros de un método son las variables que reciben
parámetros los valores de los argumentos especificados cuando se llama o
invoca. Estos pueden ser: cero, uno o más identificadores con sus
tipos, separados por comas. Aunque los identificadores sean del
mismo tipo, cada uno debe ser antecedido por su tipo. Si el método
no tiene parámetros, entonces la lista de parámetros estará vacía.
Todos los programas en Java tienen un método principal llamado main().
Este método es el primero que se llama cuando el programa comienza a
ejecutarse, por lo que la ejecución de cualquier programa java se inicia
siempre llamando al método main(). Si no se encuentra ningún método
main() en la clase dada, el programa no se puede ejecutar y se visualizará
un mensaje de error. El método main() se declara static, ya que es llamado
por la máquina java en tiempo de ejecución antes de que se cree cualquier
objeto. Los argumentos que se pasan al método main() pueden ser
cualquiera de la línea de órdenes que se introduce cuando se ejecuta el
programa.
Sintaxis de main():
public static void main (String args[ ])
{
Declaración de variables locales
Sentencias ejecutables
}

El lenguaje java exige que el método main() se declare como public static
void. Las sentencias incluidas entre las llaves { … } se denominan bloque
de sentencias o simplemente bloque.
class Suma
{
public static void main(String args[ ])
{
int a = 3, b = 5, c;
c = a + b;
System.out.println("Este programa suma los números: "+a+" y "+b);
System.out.println("La suma es: "+c);
}
}

El programa muestra lo siguiente:


Este programa suma los números: 3 y 5
La suma es: 8

La sentencia return se utiliza para salir del método actual y devolver el valor
especificado por el tipo de retorno del método, cuando el tipo de retorno es void, la
palabra return se utiliza sola, sin ninguna variable, o no se utiliza. Sin embargo, los
métodos que devuelven a la rutina llamadora un tipo de datos diferente de void
deben utilizar una sentencia return con la siguiente sintaxis:
return expresión;
expresión Es una expresión con el valor que devuelve el método.
Los métodos se pueden sobrecargar, esto significa que dos métodos con diferentes
listas de parámetros pueden tener el mismo nombre. Los métodos, para ser
ejecutados, han de ser llamados o invocados. Cualquier expresión puede contener
una llamada a un método, lo cual redirige el control del programa al método
nombrado. Normalmente, la llamada a un método se realiza desde un método de
otra clase, desde el método principal main(), o inclusive, desde un método de la
misma clase. Un método que llama a otro método se llama método invocador y el
método llamado se denomina método invocado.
El método llamado recibe el control del programa, se ejecuta desde el principio y
cuando termina, el control del programa devuelve el control y regresa al método
llamador. La llamada a un método desde otro de la misma clase y para el mismo
objeto se lleva a cabo escribiendo el nombre y entre paréntesis la lista de
argumentos o parámetros actuales. La llamada a un método desde un objeto se
realiza con el nombre del objeto, el operador punto (.) y el nombre del método con
sus argumentos actuales.
objeto.nombreMétodo (lista de parámetros actuales);
Los métodos static de una clase no son métodos de los objetos de la clase, sino
que son métodos de la clase. Por esta razón la llamada a un método static se hace
con el nombre de la clase, el operador punto (.) y el nombre del método con sus
argumentos actuales.
nombreClase.nombreMétodo (lista de parámetros actuales);
Los métodos siempre deben declararse dentro de una clase. Aunque la sentencia en
el interior de un método puede ser una llamada a otro método, no se puede definir
un método dentro de otro método.
Acceso a métodos.
Cada método tiene un tipo asociado que se utiliza para controlar el acceso
al método. El tipo de acceso puede ser por omisión (no se especifica),
public, private o protected.
• Un método public (público) se puede llamar por cualquier código que
tenga acceso a la clase. El método main() se declara public, ya que se
llama por el sistema en tiempo de ejecución.
• Un método private (privado) solo se puede llamar desde otro método de la
clase en que se define el método privado.
• Un método protected (protegido) se puede llamar desde otro método de
la clase en que el método está definido y por cualquier otro método de las
clases que heredan de la clase en que está definido. También está
disponible en cualquier objeto de las clases pertenecientes al mismo
paquete que la clase en que está definido el método.
• Si no se especifica ningún tipo de acceso, se utiliza el acceso por omisión
o por defecto, que significa que el método es accesible a todas las clases
contenidas en el mismo paquete, pero no es accesible fuera de ese
paquete.
Paso de argumentos a métodos.
El paso de argumentos a los métodos en Java se hace por valor. Esto a
través de una copia que se hace del tipo de dato primitivo (int, float, …) o la
referencia al objeto de la clase o arreglo y se pasa al método.
Java proporciona un mecanismo de paso de parámetros para permitir dar a
los métodos valores iniciales. Si bien, no todos los métodos necesitan
parámetros, la mayoría sí, ya que esto permite la generalización de los
métodos. Esto significa que un método con parámetros puede operar sobre
una gran variedad de datos y/o ser utilizado en un buen número de
situaciones diferentes. En la declaración de un método, se pueden pasar
cero, uno o más parámetros, cuando se pasen más de un parámetro, estos
deberán separarse por comas y cada uno deberá tener definido su tipo.
El paso de parámetros por valor, también llamado paso por copia, significa
que cuando Java compila el método, el método recibe una copia de los
valores de los parámetros. Si se cambia el valor de un parámetro variable
local, el cambio solo afecta al método y no tiene efecto fuera del método. En
la técnica de paso de parámetros por valor, el método receptor no puede
modificar la variable del método (parámetro pasado).
Al declarar parámetros en un método, realmente estamos declarando
variables para ser utilizadas dentro de ese método. Ya dentro del cuerpo del
método, el parámetro o argumentos se utilizan como cualquier otra variable,
de modo que si se desea que el valor pasado a la variable no se cambie,
será necesario que en la declaración de parámetros, se anteceda con la
palabra reservada final el parámetro declarado. Esto hará que el valor de la
variable no se pueda modificar después que haya sido inicializada. Si no se
coloca la palabra reservada final el valor del parámetro se puede modificar
dentro del cuerpo del método. El tipo de parámetro es elegido por el
programador de acuerdo al contexto en que se ejecuta el método.
double cubo(final double x)
{
return (x * x * x);
}

Un método declarado final, permite que una clase se ejecute con más
eficiencia ya que el método no va a cambiar. Los métodos abstractos se
designan con la palabra reservada abstract y no tienen cuerpo. Se utilizan
en clases abstractas para permitir una cierta funcionalidad a las subclases
derivadas de estas clases abstractas. La implementación de los métodos
abstractos se deja a las subclases.
Ejemplo:
Si en una clase Figura se definen los métodos abstractos area() y
perímetro() que devuelven el área y perímetro del objeto Figura. Las
subclases Círculo y Rectángulo se pueden definir como subclases de
Figura. Ya que las áreas de un rectángulo y de un círculo se calculan
utilizando fórmulas matemáticas diferentes, así, las clases Rectángulo y
Círculo proporcionarán sus propias implementaciones de los métodos
area() y perímetro(). Esto es, los métodos area() y perímetro() se definen en
cada subclase (Rectángulo y Círculo) para calcular las propiedades
respectivas de cada figura.

Figura Definición de los métodos abstractos:


area() y perímetro()

Implementación de los métodos


Círculo Rectángulo abstractos:
area() y perímetro()
Sobrecarga de métodos.
Se dice que dos o más métodos están sobrecargados, cuando tienen el
mismo nombre dentro de la misma clase y las declaraciones de sus
parámetros son diferentes. Esto se conoce como sobrecarga de métodos y
es uno de los procedimientos mediante el cual Java implementa el
polimorfismo.
En las llamadas a los métodos sobrecargados, el compilador determina
cuál es el método invocado basándose en el número o tipo de argumentos
pasados. Por lo tanto, los métodos sobrecargados deben tener diferencias
en el número o tipo de sus parámetros, así, cuando Java encuentra una
llamada a un método sobrecargado, ejecuta la versión del método cuyos
parámetros (número y tipo) coinciden con los argumentos utilizados en la
llamada. Esto significa que una llamada a un método sobrecargado debe
ser concreta, de manera que el compilador pueda decidir sin error, cuál es
el método que está siendo llamado.
Sobrecarga de constructores.
Además de la sobrecarga de métodos normales, también se pueden
sobrecargar los constructores. El método que realiza la inicialización de un
objeto es el constructor o método constructor. Éste tiene el mismo nombre
que la clase y no tiene tipo de retorno. Para las clases creadas en la
práctica, la sobrecarga de métodos constructores es la norma y no la
excepción. Incluso, una clase puede definirse sin constructor y entonces
implícitamente queda definido un constructor sin argumentos.
Sobrecarga de métodos: Sobrecarga de constructores:

// Cálculo del volumen class Cubo


{
int volumen (int la) double lado;
{ int la;
return (la * la * la);
} // Constructores para el objeto Cubo

double volumen () Cubo() {


{ lado = 1;
return (Math.pow(lado,3)); la = 1;
} }

double volumen (double lado) Cubo(int l) {


{ la = l;
return (Math.pow(lado,3)); }
}
Cubo(double l) {
lado = l;
}
Ámbito de una variable.
El ámbito o alcance de una variable determina cuales son los métodos que
reconocen ciertas variables. Si un método reconoce una variable, la
variable es visible en ese método. El ámbito es la parte de un programa en
la que es visible una variable. En Java se consideran tres tipos de ámbitos:

a) Ámbito de clase.
Las variables de instancia declaradas en una clase tienen alcance en todos los
métodos de la clase. Pueden ser referenciadas por cualquier método en la clase
completa, estas variables se pueden considerar variables globales de la clase.
b) Ámbito de método.
Una variable que tiene ámbito de método se puede referenciar desde cualquier
parte del método. Las variables declaradas dentro del cuerpo del método son
locales al método. Las variables locales no se pueden utilizar fuera del ámbito en
que están definidas.
c) Ámbito de bloque.
Un bloque es un grupo de sentencias delimitadas por una llave de apertura ( { ) y
otra llave de cierre ( } ); dentro de un bloque se puede declarar cualquier tipo de
variable, el ámbito de dicha variable queda limitado al bloque y puede ser
referenciada en cualquier parte del bloque, de hecho, una variable declarada dentro
de un bloque solo puede ser llamada dentro del bloque, fuera de él no es
reconocida y el compilador genera un error de tipo: identificador no declarado.
Variables locales.
Las variables definidas dentro de un método o en un bloque son variables
locales al método o al bloque. Además de tener un ámbito restringido, solo
existen en memoria cuando el método está activo (esto es, mientras se
ejecutan las sentencias del método). Cuando el método no se está
ejecutando, sus variables locales no ocupan espacio en memoria ya que no
existen. Algunas reglas que siguen las variables locales son:
No se puede cambiar el valor de una variable externa al método en el
interior de un método.
Los nombres de las variables locales no son únicos. Dos o más métodos
pueden definir variables con el mismo nombre, como ocurre con las
variables de control i y j que se utilizan como contadores. Cada variable es
distinta y pertenece a su método específico.
Las variables locales de los métodos no existen en memoria hasta que se
ejecute el método. Por esta razón, múltiples métodos pueden compartir la
misma memoria para sus variables locales, aunque no al mismo tiempo.
Las variables que se declaran dentro de un método se dice que son
automáticas, esto significa que se les asigna espacio de memoria
automáticamente a la entrada del método y se les libera el espacio tan
pronto se sale de dicho método.
Recursividad.
La recursividad es una técnica de
programación en la cual un método se
llama a sí mismo directa o
class Factorial
indirectamente desde el mismo cuerpo {
del método. Es importante que un
proceso recursivo tenga una condición Factorial() {
de terminación, ya que de lo contrario }
continuará indefinidamente ciclando la
máquina. El algoritmo típico que sirve long calcula(int a) {
para implementar un método recursivo if ( a > 1 )
es el cálculo del factorial de un número. return (a * calcula(a - 1));
return (1);
Ejemplo:
}
Hacer un programa que calcule el
factorial de un número. } /* fin de la clase */
Donde N! = N * (N - 1)!
N! = N * (N – 1) * (N – 2) * … * 3 * 2 * 1
CLASES.

Las clases son los bloques de construcción fundamentales de los


programas orientados a objetos. Una clase contiene la especificación de los
datos (variables) que describen un objeto junto con la descripción de las
acciones (métodos) que un objeto conoce cómo ha de ejecutar. La clase
incluye también todos los datos necesarios para describir los objetos
creados a partir de la clase. Estos datos se conocen como atributos,
variables o variables de instancia. El término atributo se utiliza en el análisis
y diseño orientado a objetos y el término variable instancia se usa
normalmente en programas orientados a objetos. Por su parte, las acciones
que ejecuta un objeto y que son definidas dentro de la clase se conocen
como métodos.
Antes de que un programa pueda crear objetos de cualquier clase, la clase
debe ser definida. Estro significa que se debe dar un nombre a la clase, así
como darle también nombre a los elementos que almacenan sus datos y
describir los métodos que realizarán las acciones consideradas en los
objetos. Una clase se declara mediante la palabra clave class. Las clases
más sencillas pueden contener solamente código o solamente datos, pero
en la práctica, las clases contienen datos y código, y el código de una clase
define la interfaz con sus datos.
[modificador] class NombreClase
{
tipo Variable_miembro_de_la_clase_1
tipo Variable_miembro_de_la_clase_2
• • •
tipo Variable_miembro_de_la_clase_N

[modificador] tipo_devuelto método1 ( Lista de parámetros )


{
Declaración de variables locales
Sentencias ejecutables
}

[modificador] tipo_devuelto método2 ( Lista de parámetros )


{
Declaración de variables locales
Sentencias ejecutables
}
• • • Definición de métodos (operaciones) dentro de la clase.

[modificador] tipo_devuelto métodoN ( Lista de parámetros )


{
Declaración de variables locales
Sentencias ejecutables
}
}
Declaración de objetos.
Cuando se crea una clase, se está creando un nuevo tipo de datos que se
utilizará para declarar objetos de ese tipo. La creación de objetos a partir
de una clase es un proceso que consta de dos etapas. En primer lugar, se
debe declarar una variable del tipo de la clase, ya que la clase es un tipo
de dato. Esta variable no define un objeto, sino que simplemente es una
referencia a un objeto. En segundo lugar, se debe obtener una copia física
del objeto y asignarla a esa variable. Para eso se utiliza el operador new.
new asigna dinámicamente memoria a un objeto y devuelve una referencia
al mismo. A continuación se almacena esta referencia en la variable. Todos
los objetos de una clase java se asignan dinámicamente. El objeto
permanecerá activo siempre que esté referenciado por una variable del tipo
de la clase.
Formato para definir una referencia:
NombreClase varReferencia;
Formato para crear un objeto:
varReferencia = new NombreClase(Argumentos_del_constructor);

Ejemplo:
Proyectil2 calculaP;
calculaP = new Proyectil2();
La siguiente sentencia combina las dos etapas descritas anteriormente y es
la más comúnmente utilizada:

NombreClase varReferencia = new NombreClase(Argumentos_del_constructor);

Ejemplo:
Proyectil2 calculaP = new Proyectil2();

El operado punto (.) es el operador de acceso a un miembro y selecciona


un miembro individual de un objeto de la clase. El operador punto se utiliza
con los nombres de los métodos y variables de instancia para especificar
que son miembro de un objeto.

Ejemplo:
Proyectil2 calculaP = new Proyectil2(a1,v01); // Se crea el objeto calculaP
r1 = calculaP.distancia(); // Llama al método distancia()
Acceso a miembros de la clase: Encapsulamiento.
Uno de los principios fundamentales de la programación orientada a objetos
es el ocultamiento de información, lo que significa que a determinados
datos del interior de una clase no se les puede acceder por métodos
externos a la clase. El principal mecanismo para ocultar datos es ponerlos
en una clase y hacerlos privados. A los datos o métodos privados sólo se
les puede acceder desde dentro de una clase. Por el contrario, los datos o
métodos públicos son accesibles desde el exterior de la clase. Esto significa
que los datos y métodos públicos forman la interfaz externa del objeto,
mientras que los elementos privados son los aspectos internos del objeto
que no necesitan ser accesibles para usar el objeto.

Privado
No son accesibles desde el exterior
Datos o Métodos
de la clase (acceso denegado)

Público
Son accesibles desde el exterior de
Datos o Métodos
la clase
Se utilizan tres diferentes especificadotes de acceso para controlar el
acceso a los miembros de la clase, estos son: public, private y protected.
Cada miembro de la clase está precedido del especificador de acceso que
le corresponde. Se utiliza el siguiente formato general en definiciones de la
clase, situando primero las variables de instancia, seguidas por los
métodos.
class NombreClase
{
private declaración miembro privado; // miembros privados
protected declaración miembro protegido; // miembros protegidos
public declaración miembro público; // miembros públicos
}
La tabla muestra los accesos permitidos a los tipos de miembros definidos
en la clase:
Tipo de Miembro de la Miembro de una Miembro de clase Miembro de clase
miembro misma clase clase derivada del paquete de otro paquete

private X
en blanco X X
protected X X X
public X X X X
Métodos de una clase.
En Java, los métodos siempre son miembros de clases y nunca habrá
métodos o funciones fuera de las clases, incluyendo al método main(). Las
declaraciones de los métodos en Java son también definiciones, ya que se
incluye el cuerpo de cada método.
Los métodos miembro que pueden aparecer en la definición de una clase
se clasifican en función del tipo de operación que representan.
• Constructores, son métodos miembro a los que se llama cuando un
operador crea un objeto.
• Selectores, son los que devuelven los valores de los miembros dato.
• Modificadores o mutadores, permiten a un programa cliente cambiar los
contenidos de los miembros dato.
• Iteradotes, procesan colecciones de objetos, tales como arreglos o listas.
• Cálculo, representan un algoritmo o realiza una operación en la que
normalmente intervienen las variables instancia.
Los métodos de las clases siempre se definen dentro del cuerpo de la
definición de la clase. El código fuente conteniendo la definición de una
clase, con todos sus métodos y variables miembro, se almacena en
archivos de texto que tienen el mismo nombre de la clase y con extensión
.java. Normalmente, se coloca la implementación de cada clase en un
archivo independiente. Cada implementación de un método tiene la misma
estructura general, comienza con una línea de cabecera que contiene, entre
otras cosas, el nombre del método y su cuerpo o bloque de sentencias está
acotado por llaves de apertura y cierre. Las clases pueden originarse de
diferentes fuentes:
• Se pueden declarar e implementar en sus propias clases. Así, el código
fuente siempre estará disponible y se pueden organizar por paquetes.
• Se pueden utilizar clases que hayan sido escritas por otras personas o
incluso que se han comprado. En este caso, se puede disponer del código
fuente o solamente el bytecode de la implementación. Es necesario
disponer del paquete donde se encuentran.
• Se pueden utilizar clases de los diversos paquetes que acompañan al
entorno de desarrollo de Java.
En cualquier caso, se debe disponer de las versiones de texto de las
declaraciones de clase para que pueda utilizarlas el compilador.
Paquetes.
Las definiciones de clases normalmente se almacenen en sus propios
archivos de código fuente con la extensión .java que tienen el mismo
nombre de la clase. El compilador de Java javac, transforma el código
fuente en bytecode y lo almacena en un archivo con el mismo nombre y la
extensión .class.
a) Clases públicas.
La definición de una clase puede incluir el modificador public como prefijo
en la cabecera de la clase:

public class NombreClase


{
// miembros de la clase
}

Normalmente, las clases se definen public para poder utilizarlas en


cualquier programa, a menos que se quiera restringir su uso a las clases del
paquete, de hecho, el especificador de acceso public es el único que se
puede especificar en la cabecera de una clase.
b) Sentencia package.
Java incorpora varios paquetes predefinidos, por ejemplo: java.lang, con
las clases básicas para construir programas: System, String, Integer, etc.
El paquete java.io, con las clases necesarias para entrada y salida. Sin
embargo, nosotros podemos definir nuestros propios paquetes, para esto
se utiliza la sentencia package. En primer lugar se debe incluir la
sentencia package como primera línea en el archivo fuente de cada una
de las clases del paquete. El formato es el siguiente:

package NombrePaquete;

Por ejemplo, supongamos que las clases Triángulo, Cuadrado, Rectángulo


y Círculo se van a organizar formando el paquete Figuras, el esquema de
cada una de las definiciones es:
// Archivo fuente: Triangulo.java
package figuras;
public class Triangulo
{
// variables y métodos miembro de la clase Triangulo
}
// Archivo fuente: Cuadrado.java
package figuras;
public class Cuadrado
{
// variables y métodos miembro de la clase Cuadrado
}
// Archivo fuente: Rectangulo.java
package figuras;
public class Rectangulo
{
// variables y métodos miembro de la clase Rectángulo
}
// Archivo fuente: Circulo.java
package figuras;
public class Circulo
{
// variables y métodos miembro de la clase Círculo
}
En segundo lugar, una vez creado el archivo fuente de cada clase del
paquete, éstos se deben ubicar en un subdirectorio o carpeta que tenga el
mismo nombre que el paquete. Así, los archivos Triangulo.java,
Cuadrado.java, Rectangulo.java y Circulo.java se ubicarán en el
subdirectorio figuras y se compilarán. El uso de paquetes tiene dos
beneficios importantes:

• Las restricciones de visibilidad son menores entre clases que están


dentro del mismo paquete. Así, desde cualquier clase del paquete, los
miembros protected y los miembros sin modificador de visibilidad son
accesibles, aunque no lo son desde otros paquetes.
• La designación de las clases de un paquete se puede abreviar con la
sentencia import del paquete.
c) Sentencia import.
Las clases que se encuentran en los paquetes se identifican utilizando el
nombre del paquete, el operador punto (.) y a continuación el nombre de la
clase. Sin embargo, la identificación completa de la clase puede resultar
tediosa cuando hay que escribir mucho texto. La sentencia import facilita la
selección de una clase, permitiendo escribir únicamente su nombre y
evitando el nombre del paquete. Así la sentencia import simplifica la
selección de una clase de un paquete de tal forma que escribiendo el
nombre de la clase, ésta ya queda seleccionada. En un programa en Java,
pueden aparecer cualquier número de sentencias import, las cuales deben
escribirse antes de cualquier definición de clase. La sintaxis general de la
sentencia import es la siguiente:
import nombrePaquete.nombreClase;
import nombrePaquete.*;

El primer formato especifica una clase de un paquete. El segundo formato


especifica que para todas las clases de un paquete no hace falta definir el
nombre de la clase con el nombre del paquete. Es frecuente utilizar el
formato: .* para todas las clases de un paquete.
Sin embargo, aunque aparezca la sentencia import nombrePaquete.*; el
compilador genera bytecode sólo para las clases utilizadas.
Constructores.
Un constructor es un método miembro que se ejecuta automáticamente
cuando se crea un objeto de una clase y sirve para inicializar los miembros
dato o variables de instancia de una clase. Los constructores tienen el
mismo nombre de la clase. Un constructor nunca devuelve un valor, por lo
que jamás debe especificarse un valor de retorno, ni siquiera void. Los
constructores pueden tener cero, uno, dos o más parámetros.
Al definir un objeto, se aplica el operador new al constructor que se desee,
si tiene parámetros se pasan los valores de los parámetros al constructor
utilizando una sintaxis similar a la llamada normal a un método:
Cono miCono = new Cono(2, 5);

Esta definición crea una instancia del objeto Cono, invocando al constructor
de la clase y pasándole los parámetros con valores específicos para
inicializarlo, la referencia al objeto se asigna a miCono.
A un constructor que no tiene parámetros se le llama constructor por
defecto. Java crea automáticamente un constructor por defecto cuando no
existen otros constructores. Un constructor por defecto normalmente
inicializa los miembros dato asignándoles valores por defecto. A las
variables de tipo numérico las inicializa a cero, las variables de tipo boolean
a false y las referencias a null.
También se puede sobrecargar el constructor de la clase. Solo se
ejecuta un constructor, aunque se hayan definido varios constructores.
Ejemplo:
class Cono
{
double radio, altura;
// Constructores para el objeto Cono.
Cono() {
radio = 1;
altura = 1;
}
Cono(int r, int h) {
radio = r;
altura = h;
}
Cono(double r, double h) {
radio = r;
altura = h;
}
// Definiciones de otros métodos de la clase.
}
Aunque también pueden inicializarse las variables de instancia, es más
conveniente inicializar las variables de los constructores. Si se necesita
proteger el valor de alguna variable de instancia, entonces se inicializa y se
le antepone la clausula final para proteger su valor.
Un objeto se puede crear a partir de los datos de otro objeto. Se puede
inicializar el objeto asignándole otro objeto de su misma clase en el
momento de su creación, para esto debe intervenir un constructor. El
prototipo para este constructor tiene la forma:

NombreClase (NombreClase Referencia_Objeto);

Este constructor tiene un solo parámetro que es una referencia a un objeto


de su misma clase y por tratarse de un constructor no hay un valor
retornado. A un constructor que se invoca para iniciar un nuevo objeto
creado a partir de otro existente se le denomina: constructor copia.

Ejemplo:
Cono miCono = new Cono(2, 5);
Cono miCono2 = new Cono(miCono);
Destrucción de objetos.
Los objetos en Java siempre se crean llamando a un constructor de la
clase. Así, un objeto en Java siempre ha de estar referenciado por una
variable, en el momento en que un objeto deja de ser referenciado se activa
la rutina de recolección de memoria o basura, se puede decir que el objeto
es destruido y la memoria que ocupa puede ser reutilizada.
Cuando un objeto es destruido ocurren varias cosas: se llama al método
finalize y después, el recolector de basura se encarga de eliminar el objeto,
liberando los recursos que el objeto tenga adjudicados. Un objeto es
destruido automáticamente cuando se eliminan todas las referencias al
mismo, ya sea porque el flujo de ejecución salga fuera del ámbito donde
ella está declarada o porque explícitamente se le asigne el valor de null. El
proceso de recolección lo realiza el método System.gc (garbage
collection).
Un destructor es un método especial de una clase que se ejecuta antes de
que un objeto de esa clase sea eliminado físicamente de la memoria. Un
destructor se distingue fácilmente porque tiene el nombre predeterminado
finalize. Cuando en una clase no especificamos un destructor, el
compilador, el compilador proporciona uno a través de la clase Object cuya
sintaxis es la siguiente:
protected void finalize() throws Throwable { /* sin código */ }
El método finalize() es un método especial que se llama automáticamente
si ha sido definido en la clase, justo antes que la memoria del objeto
recolectado vaya a ser devuelta al sistema. El método tiene las siguientes
características:
• No devuelve ningún valor.
• No tiene argumentos.
• No puede sobrecargarse.
• Su definición es opcional.
Como ya vimos, la el método finalize se puede redefinir en una clase para
ser usado como destructor, posteriormente, puede ser llamado y aplicado
en un programa, antes del proceso de recolección de basura. A
continuación se muestra la definición del método y el código que podemos
aplicar para la recolección de basura:
class NombreClaseX
{
// atributos y métodos de la clase
• • •
protected void finalize() throws Throwable { /* sin código */ }
} // fin de la clase.
Un aspecto importante es que solo se llama al método finalize() justo antes
de que actúe el sistema de recolección de basura, y no, por ejemplo,
cuando un objeto está fuera de contexto. Esto significa que no se puede
saber exactamente cuando será, o incluso si será, ejecutado el método
finalize(). Por lo tanto, el programa debe incluir otros medios que permitan
liberar los recursos del sistema, etc., utilizados por el objeto, y no apoyarse
exclusivamente en el método finalize() para la operación normal del
programa.
La recolección de basura sólo se produce esporádicamente, si es
necesario, durante la ejecución del programa. No se producirá simplemente
por que haya uno o dos objetos que no se utilicen más. Los diferentes
intérpretes de Java tienen distintos procedimientos para la recolección de
basura, por lo que no debemos preocuparnos por ello mientras se escribe
el programa.

Clases compuestas.
Una clase compuesta es aquella que contiene miembros dato que son
asimismo referencias a objetos de clases. Estas pueden estar definidas en
el paquete actual o en otro paquete. Estas referencias se inicializan por
defecto a null.
Referencia this.
Para que un método conozca la identidad del objeto particular para el que
ha sido invocado, Java proporciona una referencia al objeto denominado
this. this es una referencia al objeto que envía un mensaje, o simplemente
una referencia al objeto que llama a un método (y que no debe ser static).
Así, la referencia this al objeto es constante y no se puede modificar,
cualquier intento de modificación será erróneo. Internamente está definida
de la siguiente manera:
final NombreClase this;
Básicamente, this nos sirve para seleccionar explícitamente un miembro de
una clase con el fin de dar más claridad o de evitar colisión de
identificadores (variables de instancia y parámetros o variables locales con
el mismo nombre).
En el ejemplo se evita una colisión entre los argumentos del método
constructor y las variables de instancia.

class Cono
{
double radio, altura;

// Constructor para el objeto Cono.

Cono(double radio, double altura) {


this.radio = radio;
this.altura = altura;
}

// Definiciones de otros métodos de la clase.

}
Variables, métodos y clases finales.
Las variables finales (definidas final), también son denominadas constantes
porque nunca cambian su valor.
final double G = 9.81;

También pueden declararse static para hacer que la constante sea solo de
la clase y no del objeto. Así, declarar una referencia final a un objeto,
supone que esa referencia sólo pueda utilizarse para referenciar ese objeto;
cualquier intento de modificar dicha referencia para que señale a otro objeto
será detectado durante la compilación y marcará error.
Un método podrá ser cambiado por una subclase si esta lo redefine, para
poder hacerlo, el método no deberá ser declarado final. Declarar un método
final supone que la clase se ejecute con más eficiencia porque el
compilador puede colocar el código de bytes del método directamente en el
lugar del programa donde se llame a dicho método, ya que se garantiza que
el método no va a cambiar.
Cuando una clase se declara final estamos impidiendo que de esa clase se
puedan derivar subclases. Además, todos sus métodos se convierten
automáticamente en final. Sin embargo, al declarar una clase final, se
sacrifica una de las características más potentes de la Programación
Orientada a Objetos, la reutilización del código.
Miembros static de una clase.
Cada objeto o instancia de clase tiene su propia copia de las variables de
instancia de la clase. Cuando interese que haya miembros que no estén
ligados a los objetos, sino a la clase, y por lo tanto comunes a todos los
objetos, éstos se declaran static. Así, un atributo static no es un atributo
específico de un objeto, sino más bien es un atributo de la clase, esto
significa que es un atributo del que solo hay una copia que comparten
todos los objetos de la clase. Por esta razón, un atributo static existe y
puede ser utilizado aunque no exista ningún objeto de la clase.
a) Variables de instancia static.
Las variables de clase static son compartidas por todos los objetos de la
clase, lo que significa que básicamente, son variables globales. Se declaran
igual que cualquier otra variable, solo se añade la palabra reservada static.
Así, las variables miembro static no forman parte de los objetos de la clase,
sino de la misma clase. Esto significa que si un objeto modifica el valor de
una variable de instancia calificada static, los demás objetos de la clase se
verán afectados por dicha modificación. Dentro de la clase se accede a
ellas de la manera habitual, simplemente con su nombre. Desde fuera de la
clase se accede a las variables static (si la visibilidad lo permite <public>),
con el nombre de la clase, el operador punto (.) y el nombre de la variable.
NombreClase.NombreVariable

class Cubo
{
static double lado;
• • •
}

La llamada sería: Cubo.lado = …;


b) Métodos static.
Los métodos de las clases se llaman a través de los objetos. Sin embargo,
en ocasiones interesa definir métodos que estén controlados por la clase,
sin que haga falta crear un objeto para llamarlos, estos son los métodos
static.
En las clases de la biblioteca Java, muchos métodos están definidos como
static, tal es el caso de los métodos de la clase Math que representan
funciones matemáticas.
La llamada a un método static se realiza a través de la clase, respetando
las reglas de visibilidad:
NombreClase.metodo(<argumentos>)

El siguiente ejemplo accede al método toRadians de la clase Math, para


convertir a radianes, un ángulo que está en grados:
AnguloRad = Math.toRadians(ang);

También se pueden llamar con un objeto de la clase, lo cual no es


recomendable debido a que son métodos dependientes de la clase y no de
los objetos.
Un método declarado static carece de la referencia this por lo que no
puede ser invocado para un objeto de su clase, sino que se invoca en
general allí donde se necesite utilizar la operación para la había sido
escrito. Así, es imposible que un método static pueda acceder a un
miembro no static de su clase, pero si puede acceder a un miembro
static.
Los métodos declarados como static tienen varias restricciones:
• Sólo pueden llamar a otros métodos declarados como static.
• Sólo deben acceder a datos declarados como static.
• No pueden referirse a this o super de ninguna manera.
Fuera de la clase en la que se han definido, los métodos y las variables
static se pueden utilizar independientemente de cualquier objeto. Para
hacerlo sólo es necesario especificar el nombre de su clase seguido por el
operador punto (.), tal como se indicó anteriormente.
Biblioteca de clases Java de uso común.
Java incorpora una amplia biblioteca de clases e interfaces denominada
Java API (Application Programming Interface). Estas clases se pueden
utilizar para definir nuevas clases, crear objetos o utilizar sus métodos. La
biblioteca de clases está organizada por paquetes (packages), cada
paquete contiene una colección de clases y para hacer uso de esas clases
sin tener que anteponerles el nombre del paquete se utiliza la sentencia
import. Los nombres de algunos de los principales paquetes son:
Paquete Explicación
java.applet Este paquete contiene la clase Applet, la cual proporciona todo lo necesario para programar applets.
java.awt En este paquete se encuentran todas las herramientas gráficas AWT (Abstract Window Toolkit) que
proporcionan el soporte gráfico para los applets. Esto es, los métodos y clases que permiten crear y
manejar ventanas, gráficos y texto.
java.io El paquete java.io contiene el sistema básico de Entrada/Salida de Java, incluyendo la E/S con
archivos.
java.lang Las clases, interfaces y métodos básicos, necesarios para desarrollar un programa en Java se
encuentran en este paquete. Las clases de este paquete son importadas de forma automática por lo
que no es necesaria una sentencia import que importe este paquete.
java.math Este paquete contiene clases para realizar operaciones con números enteros de diferente precisión y
aritmética de punto flotante.
java.net El paquete java.net proporciona el soporte para el trabajo en red y las conexiones del protocolo
TCP/IP.
java.util Este es uno de los paquetes más usados. Contiene un conjunto de clases e interfaces de utilerías para
diversas aplicaciones como son: la generación de números pseudoaleatorios, manejo de fecha y hora,
observación de eventos, manipulación de conjuntos de bits y operaciones con cadenas.
El paquete java.lang es el paquete más importante. Se considera el
paquete estándar y por eso todos los programas lo importan
automáticamente. Este paquete contiene las clases que encapsulan a los
tipos de datos primitivos: Double, Float, Long, etc. Las clases String y
StringBuffer para el tratamiento de cadenas. La clase Math con las
funciones matemáticas más importantes y las clases Object, System,
Thread y Throwable.
El paquete java.util define un conjunto de clases útiles para diversos
cometidos. Como la clase Date para manejo de fechas en distintos formatos
y la clase Random para generar números aleatorios, entre otras. Este
paquete si es necesario importarlo si se utiliza alguna clase o interfaz de él.

import java.util.*; para cualquier clase del paquete


import java.util.Date; para utilizar solo la clase Date
a) Clase Object.
La clase Object es la superclase base de todas las clases definidas en
Java; toda clase definida en Java hereda de la clase Object. En Java, una
variable que referencia a una clase se convierte automáticamente al tipo de
la clase base, por lo tanto es posible cualquier asignación a una variable de
tipo Object. La clase Object tiene dos métodos importantes: equals() y
toString(). Normalmente estos métodos se redefinen en las clases para
especializarlos.

i) Método equals()
Compara el objeto que hace la llamada, con el objeto que pasa como
argumento, devuelve trae si son iguales:

boolean equals(Object cadena);


String cad1 = new String(“Informática”);
String cad2 = “Computación”;
if (cad1.equals(cad2)) // Devuelve false por que no se cumple.
ii) Método toString().
Este método construye (o convierte a) una cadena (String) que es la
representación del objeto, devolviendo la cadena. Normalmente se redefine
en las clases para dar detalles explícitos de los objetos de la clase.
String toString()

En el siguiente ejemplo, un objeto Double llama al método toString() y


asigna la cadena a una variable.

Double num = new Double(2.5);


String numcad;
numcad = num.toString();
b) Clase System.
Esta clase se utiliza con frecuencia ya que tiene los objetos asociados con
la entrada y salida estándar. No se pueden crear objetos de la clase
System ya que los miembros de la clase que se utilizan están definidos
como static, por lo que para hacer referencia a ellos se antepone el nombre
de la clase: System.
i) System.in.
Este objeto está definido: static final InputStream in. Normalmente
corresponde a la entrada por teclado y se utiliza como argumento para el
constructor que crea un objeto de entrada con buffer:
BufferedReader entrada = new BufferedReader (
new InputStreamReader (System.in));

ii) System.out.
Este objeto queda definido: static final PrintStream out. Corresponde
normalmente a la salida por pantalla. Se hacen llamadas a dos métodos
para salida de datos por pantalla, los cuales previamente son convertidos
en cadenas de caracteres. El segundo se diferencia del primero en que una
vez mandada la cadena a la pantalla, el cursor salta a la línea siguiente:
System.out.print()
System.out.println()
iii) exit().
El método exit() termina la ejecución de una aplicación, esta declarado
como: static void exit (int status). El argumento status se acostumbra
que se cero si la terminación es sin errores, y un valor distinto de cero para
indicar un código de error.
iv) gc().
El método gc() (garbage collector) está declarado: static void gc(). Una
llamada a este método (System.gc()) hace que se active la liberación de
objetos que no estén referenciados por ninguna variable.

c) Clase Math.
La clase Math contiene constantes matemáticas y funciones matemáticas,
no se instancian objetos de esta clase. En esta clase se encuentran
agrupadas constantes y métodos (funciones matemáticas). Estas
constantes y métodos están declaradas con el modificador static y se hace
referencia a ellos mediante su nombre, anteponiendo Math.
Las dos constantes más utilizadas son Math.E y Math.PI, ambas son de
tipo double. Math.E, representa el número e que es la base de los
logaritmos naturales, su valor es: 2.718281828459045. Math.PI, es el
número pi cuyo valor es: 3.141592653589793.
Método Descripción
static double E Valor del número e (base del logaritmo neperiano o
natural). 2.718281828459045
double PI Valor del número π. 3.141592653589793
tipo abs (tipo a) Valor absoluto de a. El tipo igual en todos los casos,
puede ser int, long, float o double.
double ceil (double a) Valor double sin decimales más pequeño que es mayor
o igual que a (redondeo hacia arriba).
double floor (double a) Valor double sin decimales más grande que es menor o
igual que a (redondeo hacia abajo).
tipo max (tipo a, tipo b) Valor mayor de a y b. El tipo igual en todos los casos,
puede ser int, long, float o double.
tipo min (tipo a, tipo b) Valor menor de a y b. El tipo igual en todos los casos,
puede ser int, long, float o double.
double random () Valor aleatorio mayor o igual que 0.0 y menor que 1.0

double rint (double a) Valor double sin decimales más cercano a a (redondeo
de a).
long round (float a) Valor long más cercano a a.
int round (float a) Valor int más cercano a a.
double sqrt (double a) Raíz cuadrada de a (a no puede ser negativo).
Método Descripción
double exp (double a) Valor de ea.
double log (double a) Logaritmo neperiano (natural) de a.
double pow (double a, double b) Valor de ab.
double IEEEremainder (double f1, Resto de una división entre números reales: f1/f2,
double f2) siendo el resultado, el valor entero más cercano al valor
real de f1/f2; por lo tanto el resto puede ser positivo o
negativo.
double acos (double a) Devuelve el ángulo (de 0.0 a π) cuyo coseno viene dado
por a.
double asin (double a) Devuelve el ángulo (de – π/2 a π/2) cuyo seno viene
dado por a.
double atan (double a) Devuelve el ángulo (de – π/2 a π/2) cuya tangente viene
dada por a.
double atan2 (double a, double b) Devuelve el ángulo cuya tangente es a/b.

double sin (double a) Devuelve el seno de a, en radianes.


double cos (double a) Devuelve el coseno de a, en radianes.
double tan (double a) Devuelve la tangente de a, en radianes.
double toDegrees (double rads) Convierte un ángulo de radianes a grados.
double toRadians (double grados) Convierte un ángulo de grados a radianes.
Clases anidadas.
Una clase definida dentro de otra clase se conoce como clase anidada. El
campo de acción de una clase anidada se limita a la clase que la contiene.
Esto es, si la clase B se define dentro de la clase A, entonces B es conocida
dentro de A, pero no fuera de A. Una clase anidada tiene acceso a los
miembros, incluyendo miembros privados, de la clase en la que está
anidada. Sin embargo, la clase que la contiene no tiene acceso a los
miembros de la clase anidada.

Clase B
UNIVERSIDAD AUTONOMA DE SINALOA
FACULTAD DE INFORMÁTICA DE MAZATLAN

PROGRAMACIÓN I
Herencia y Polimorfismo
TITULAR DE LA MATERIA:
DR. JOSÉ NICOLÁS ZARAGOZA GONZÁLEZ
HERENCIA Y POLIMORFISMO.

La herencia es uno de los aspectos básicos de la programación orientada a


objetos (POO), ya que permite la creación de clasificaciones jerárquicas.
Mediante la herencia se puede crear una clase general que defina rasgos
generales para un conjunto de términos relacionados. Esta clase puede ser
heredada por otras clases más específicas, cada una de las cuales añadirá
nuevos elementos que la distingan o que necesite. En la terminología de
Java, una clase que es heredada se denomina superclase o clase base y la
clase que hereda se denomina subclase o clase derivada. Por lo tanto, una
subclase es una versión especializada de una superclase, la cual hereda
todas las variables de instancia y métodos definidos por la superclase, y
añade los suyos propios.
La utilización de subclases y métodos definidos en una clase y redefinidos
en sus clases derivadas es el concepto básico de la programación orientada
a objetos. En cambio, la facultad de llamar a una variedad de métodos
utilizando exactamente el mismo medio de acceso, la cual es proporcionada
por los métodos redefinidos en las subclases, es lo que se denomina
polimorfismo.
HERENCIA.
La herencia es la relación que existe entre dos clases, en la que una clase
denominada subclase o derivada se crea a partir de otra ya existente,
denominada clase base o superclase. Este concepto nace de la necesidad
de construir una nueva clase, cuando existe una clase que representa un
concepto más general; en este caso, la nueva clase puede heredar de la
clase ya existente. Evidentemente, la clase base y la clase derivada tienen
código y datos comunes, de modo que si se creara la clase derivada como
otra clase independiente, se duplicaría gran parte del código que ya se ha
escrito para la clase base. Java soporta el mecanismo de extensión
(extend), que permite crear clases derivadas o subclases que son
extensión de otra clase, de modo que la nueva clase hereda todos los
miembros dato y los métodos que pertenecen a la clase ya existente.
En Java, la declaración de derivación de clases debe incluir la palabra
reservada extends en la línea de declaración de la clase derivada y a
continuación el nombre de la clase base de la que se deriva. Esta palabra
reservada produce que todos los miembros no privados (private) en la
clase base sean heredados en la clase derivada. La primera línea de cada
declaración de subclase debe incluir el formato siguiente:
class NombreSubClase extends NombreClaseBase
La sintaxis para la declaración de una subclase o clase derivada es:
class NombreSubClase extends NombreClaseBase
{
// miembros específicos de la subclase.
}

La clase base o superclase (NombreClaseBase) es el nombre de la clase


de la cual se deriva la nueva clase. Los miembros private de la clase base
son los únicos que no se heredan a la subclase, ni se puede acceder a ellos
desde métodos de la clase derivada. Los miembros con visibilidad public,
protected o la visibilidad por defecto (entre clases del mismo paquete) se
incorporan a la subclase con la misma categoría de visibilidad que tienen en
la clase base. Así mismo, al declarar la clase, el modificador public como
prefijo indica que la clase es visible en otros paquetes.
Una vez que se ha creado una clase derivada, el siguiente paso es añadir
los nuevos miembros que se requieran para cumplir las necesidades
específicas de la nueva clase.
Una vez que se ha creado una superclase que define los aspectos
generales de un objeto, esa superclase puede ser heredada para formar
clases especializadas. Cada subclase añade sus propios y únicos atributos.
Esto es la base de la herencia.
Así, por ejemplo, si existe una clase Figura y se desea crear una clase
Triángulo, esta clase Triángulo puede derivarse de Figura, ya que tendrá en
común con ella un estado y un comportamiento, aunque luego tendrá
también sus propias características. En la definición de la clase Triángulo
sólo se especifican los nuevos miembros (datos y métodos). Todos los
miembros dato y los métodos miembro no privados de la clase Figura son
heredados automáticamente a la clase Triangulo.

class Triangulo extends Figura


{
public
// miembros públicos (nuevas variables de instancia y nuevos métodos).
protected
// miembros protegidos (nuevas variables de instancia y nuevos métodos).
• • •
}
Figura

Triángulo
Herencia pública.
En una clase existen secciones públicas, privadas, protegidas y con
visibilidad por defecto. Los elementos públicos son accesibles a todos los
métodos de cualquier clase; los elementos privados son accesibles solo a
los miembros de la clase en que están definidos, los elementos protegidos
pueden ser accedidos por clases del mismo paquete y subclases del mismo
o de otro debido a la propiedad de la herencia; los elementos con la
visibilidad por defecto son accesibles desde cualquier clase del mismo
paquete, pero no son visibles en clases derivadas de otros paquetes.
Una clase derivada no puede acceder a variables y métodos privados de su
clase base. Una clase base utiliza elementos protegidos para de esa
manera ocultar los detalles de la clase respecto a clases no derivadas de
otros paquetes. Los elementos protegidos son accesibles a los miembros
de todas las clases derivadas. Una subclase tiene acceso a los elementos
públicos y protegidos de su clase base. Los elementos públicos se heredan
como elementos públicos; los elementos protegidos permanecen
protegidos. Así, en Java, la herencia siempre es pública y los miembros de
la subclase, heredados de la clase base, tienen la misma protección que en
la superclase o clase base.
Acceso a variables y métodos según el tipo de herencia
Tipo de Accesible a Accesible a Accesible a clase
elemento clase de clase derivada de otro
paquete derivada paquete

public si si si
protected si si si
private no no no
por defecto si si no

Las clases para ser visibles desde otro paquete se declaran con el
modificador public, en caso contrario la clase está restringida al paquete
donde se declara.

modificador class NombreSubClase extends NombreClaseBase


{
// miembros propios de la subclase.
}
Constructores de las subclases.
Cuando se crea un objeto de una clase se invoca a su constructor y los
constructores de la clase base no son heredados por sus subclases. En
cambio, cuando se crea un objeto de una subclase, se invoca a su
constructor, que a su vez invoca al constructor sin parámetros de la
superclase, el cual a su vez invoca al constructor de su superclase y así
sucesivamente. Esto significa que primero se ejecutan los constructores de
las superclases de arriba hacia abajo en la jerarquía de clases y finalmente
el de la subclase. Esto ocurre así porque una subclase contiene todos los
atributos de su superclase y todos tienen que ser iniciados, por esta razón
el constructor de la subclase tiene que llamar implícita o explícitamente al
de la superclase.
Cuando se definen constructores con parámetros, tanto en las clases
derivadas como en las clases base, se puede construir un objeto de la
subclase iniciándolo con unos valores determinados. En este caso, la
definición para los constructores de una clase cualquiera se extiende ahora
para permitir al constructor de la subclase invocar explícitamente al
constructor de la superclase. Esto se hace utilizando la palabra reservada
super. La palabra clave super tiene dos formas generales. La primera
llama al constructor de la superclase. La segunda se usa para acceder a un
miembro de la superclase que ha sido escondido por un miembro de una
subclase.
Una subclase puede llamar a un método constructor definido por su
superclase utilizando la siguiente forma de super:

modificador NombreSubClase ( Lista_de_Parámetros )


{
super ( lista_de_parámetros );
// cuerpo del constructor de la subclase.
}

La definición anterior corresponde a un constructor con parámetros de una


subclase. La lista_de_parámetros especifica cualquier parámetro que el
constructor necesite en la superclase. La sentencia super(), debe ser
siempre la primera sentencia que se ejecute dentro de un constructor de la
subclase, después se colocará el cuerpo del constructor de la subclase. Si
la superclase no tiene un constructor de forma explícita o tiene uno que no
requiere parámetros, no se necesita invocarlo explícitamente, ya que Java
lo invocará automáticamente mediante super() sin argumentos. Por el
contrario, sí es necesario invocarlo cuando se trate de un constructor con
parámetros, para poder así pasar los argumentos necesarios en la llamada.
class Resta
{
double a, b;
Resta (double x, double y) {
a = x;
b = y; }
void operacion () {
double c = 0.0;
c = a - b;
System.out.println("La resta de: "+a+" - "+b+" = "+c); }
} /* fin de la clase */

class Resta2 extends Resta


{
Resta2 (double x, double y) {
super(x,y); }
void operacion () {
double c = 0.0;
c = b - a;
System.out.println("La resta de: "+b+" - "+a+" = "+c); }
} /* fin de la clase */
La segunda forma de super() actúa de una forma parecida a this, excepto
que siempre se refiere a la superclase de la subclase en la que se usa.
Esta utilización tiene la siguiente forma general:

super.miembro

Donde miembro puede ser un método o una variable de instancia.


Esta segunda forma de super tiene una mayor aplicación en situaciones
en las que los nombres de miembros de una subclase ocultan miembros
del mismo nombre en la superclase.
También puede ocurrir que haya métodos de la clase base que no interesa
que sean heredados en la subclase, debido a que se quiere que tengan
funcionalidad adicional. Lo que se hace es simplemente sobrescribir el
método en la subclase. En ese caso se puede llamar al método ocultado
de la superclase precediendo al método con la palabra reservada super
seguida del operador punto, tal como se indicó anteriormente.
class Valor
{
double a;
} /* fin de la clase */

class Valor2 extends Valor


{
double a;

Valor2 (double x, double y) {


super.a = x; // valor a de la clase Valor
a = y; // valor a de la clase Valor2
}

void muestra() {
System.out.println("a en la superclase: "+super.a);
System.out.println("a en la sublcase: "+a);
}
} /* fin de la clase */
Jerarquía de clases.
Una subclase puede ser una superclase de otra clase y así sucesivamente.
El conjunto de clases así definido da lugar a una jerarquía de clases.
Cuando cada subclase lo es de una solo superclase, como ocurre en Java,
la estructura jerárquica recibe el nombre de árbol de clases. La raíz del
árbol es la clase que representa el tipo más general, y las clases terminales
en el árbol (nodos hoja) representan los tipos más especializados. Sean,
por ejemplo, las clases A, B, C y D, donde C y D pueden ser unas
subclases de B, que a su vez es una subclase de A. Cuando se produce
esta situación, cada subclase hereda todos los atributos encontrados en
todas sus superclases. En este caso, C y D heredan todas las
características de B y A.

Clase A

Clase B

Clase C Clase D
Sobreescritura de métodos.
Un problema que se plantea cuando se manejan clases derivadas es la
dominación o prioridad, que se produce cuando existen métodos en clases
derivadas con el mismo nombre que otros métodos de las clases base. Así,
cuando en una jerarquía de clases, un método de una subclase tiene el
mismo nombre y tipo que un método de su superclase, entonces se dice
que el método de la subclase sobrescribe al método de la superclase.
Cuando se llama a un método sobrescrito desde una subclase, esta
llamada se refiere a la versión de ese método definida en la subclase.
Utilizamos nuevamente las clases Resta y Resta2, y definimos el método
operación(). Cuando se invoca a operación() en un objeto del tipo Resta2,
se utiliza la versión de operación() definida en Resta2; es decir, la versión
de operación() dentro de Resta2 domina sobre la versión declarada en
Resta.
Se puede acceder a la versión de la superclase de un método dominado
utilizando el método super en el método sobrescrito de la subclase.
También podemos hacerlo accediendo directamente al método definido en
la superclase, como muestra el programa. La sobreescritura de métodos
aparece únicamente cuando los nombres y tipos de los dos métodos son
iguales. Si no lo son, entonces los dos métodos están simplemente
sobrecargados.
class Resta
{
double a, b;
Resta (double x, double y) {
a = x;
b = y; }
void operacion () {
double c = 0.0;
c = a - b;
System.out.println("La resta de: "+a+" - "+b+" = "+c); }
} /* fin de la clase */

class Resta2 extends Resta


{
Resta2 (double x, double y) {
super(x,y); }
void operacion () {
double c = 0.0;
c = b - a;
System.out.println("La resta de: "+b+" - "+a+" = "+c); }
} /* fin de la clase */
Clases abstractas.
Hay ocasiones en las que se quiere definir una superclase en la que se
declare la estructura de una determinada abstracción sin implementar
completamente cada método, es decir, en la que solo se defina una forma
generalizada que será compartida por todas las subclases, dejando que
cada subclase complete los detalles necesarios. Una clase de este tipo
determina la naturaleza de los métodos que las subclases deben
implementar. Un caso en el que se puede producir esta situación es aquel
en que una superclase no es capaz de crear una implementación de un
método que tenga un significado completo. Así, las clases abstractas suelen
representar conceptos generales, las características comunes de una serie
de objetos.
Las clases abstractas pueden definir métodos y variables de instancia, y
normalmente tienen métodos no abstractos. Cualquier clase que contenga
uno o más métodos abstractos, se debe definir como abstracta. Para
declarar una clase abstracta, se utiliza la palabra clave abstract
anteponiéndola a la palabra clave class en el comienzo de la declaración
de la clase.
abstract class NombreClase {
// sentencias de la clase abstracta.
}
No puede haber objetos de clase abstracta, es decir, no se pueden crear
instancias de dichas clases directamente con el operador new. Tales
objetos no tienen ninguna utilidad, ya que una clase abstracta no está
completamente definida. El compilador marcará un error siempre que se
intente crear un objeto de una clase abstracta. Tampoco se pueden declarar
constructores abstractos o métodos estáticos abstractos. Cualquier
subclase de una clase abstracta debe implementar todos los métodos
abstractos de la superclase, o bien ser declarada ella misma como
abstract. Así, en el caso de que una clase derivada no redefina su propia
versión de un método abstracto declarado en la clase base, se convierte
también en clase abstracta, ya que hereda el método abstracto.
Por su parte, los métodos abstractos se declaran de la siguiente manera:
abstract tipo NombreMétodo (lista_de_parámetros);
import java.math.*;

abstract class Cubo4


{
// Cálculo del volumen.
double volumen (double lado) {
return (Math.pow(lado,3)); }

// Cálculo del área de una cara (método abstracto).


abstract double calculaArea(double lado);

} // Fin de la clase.

class Cubo5 extends Cubo4


{
// Cálculo del área de una cara (implementación del método abstracto).
double calculaArea(double lado) {
return (lado * lado); }

} // Fin de la clase.
Utilización de la palabra clave final con la herencia.
La palabra clave final tiene tres aplicaciones. La primera, como ya se vio,
anteponiéndola en la definición de una variable, lo que crea el equivalente de
una constante con nombre. La segunda aplicación de final es para evitar que
un método sea sobrescrito, así, los métodos que se declaran como final no
pueden ser sobrescritos. Si se intenta la sobreescritura, el compilador
marcará error.
class EjemploFinal
{
final void mensaje() {
System.out.println(“Este es un método final y no puede ser sobrescrito”);
}
} // fin de la clase.
Los métodos declarados como final pueden proporcionar en ocasiones una
mejora del rendimiento, ya que el compilador puede realizar llamadas en
línea a dichos métodos porque sabe “sabe” que no pueden ser sobrescritos
por una subclase. Comúnmente, cuando se llama a una pequeña función
final, el compilador Java puede copiar el código binario de la subrutina
directamente en línea con el código del compilado del método que lo llama,
eliminando la sobrecarga asociada a la llamada del método. Esta es una
opción de la que disponen solamente los métodos declarados como final.
La tercera aplicación de final es para evitar que una clase sea heredada.
Para ello, basta con que al nombre de la clase se le anteponga la palabra
clave final. Al declarar una clase como final se declaran también todos sus
métodos como final. Por lo tanto, no es válido declarar una clase
simultáneamente como abstract y final, ya que una clase abstracta está
incompleta por definición y se basa en sus subclases para proporcionar sus
implementaciones completas.

final class EjemploFinal2


{
// Implementación de la clase…
} // fin de la clase.

class EjemploFinal3 extends EjemploFinal2


{
// Esto es un error ya que no puede haber subclases de EjemploFinal2.
// Implementación de la clase…
} // fin de la clase.
POLIMORFISMO.

La palabra polimorfismo significa “muchas formas” y podemos definirla


como la facultad de asumir muchas formas, y en el caso de la programación
orientada a objetos (POO), se refiere a la facultad de llamar a muchos
métodos diferentes utilizando una sola sentencia. Como se vio
anteriormente, cuando se invoca a un método que está definido en la
superclase y redefinido en sus subclases, la versión que se ejecuta
depende de la clase del objeto referenciado, no del tipo de la variable que lo
referencia. Asimismo, una referencia a una subclase puede ser convertida
implícitamente por Java en una referencia a su superclase directa o
indirecta. Esto significa que es posible referirse a un objeto de una subclase
utilizando una variable del tipo de su superclase.
El polimorfismo es esencial en la programación orientada a objetos, porque
permite que una clase general especifique métodos que serán comunes a
todas las clases que se deriven de la misma; de manera que las subclases
podrán definir la implementación de algunos o todos esos métodos, así, los
métodos sobrescritos son otra de las formas en que Java implementa el
aspecto del polimorfismo.
Aunque existe menos libertad que en otros lenguajes de programación, el
polimorfismo en Java es una herramienta muy potente que puede ser
utilizada en muchas situaciones diferentes. Por lo que a manera de
resumen diremos que las aplicaciones más frecuentes del polimorfismo son:
a) Especialización de subclases.
El uso más común del polimorfismo es derivar clases especializadas de
clases que han sido definidas. Así, por ejemplo, si definimos una clase
cuadrado que es una especialización de una clase llamada rectángulo (ya
que cualquier cuadrado es un tipo de rectángulo). Esta clase de
polimorfismo aumenta la eficiencia de la subclase y conserva un alto grado
de flexibilidad y permite un medio uniforme de manejar rectángulos y
cuadrados.
b) Estructuras de datos heterogéneos.
A veces es muy útil poder manipular conjuntos similares de objetos. Con
polimorfismo se pueden crear y manejar fácilmente estructuras de datos
heterogéneos, que son fáciles de diseñar y dibujar, sin perder la
comprobación de tipos de los elementos utilizados.
c) Gestión de una jerarquía de clases.
Las jerarquías de clases son colecciones de clases altamente
estructuradas, con relaciones de herencia que se pueden extender
fácilmente.
INTERFACES.

Podemos definir una interfaz como: un dispositivo o un sistema utilizado


por entidades independientes entre sí para interactuar entre ellas. Java
incorpora una construcción del lenguaje llamada interface, que permite
declarar un conjunto de constantes y de cabeceras de métodos abstractos.
Éstos deben implementarse en las clases y constituyen la interfaz de la
clase, permitiendo interactuar a objetos no relacionados entre sí. Las
interfaces Java en realidad definen un conjunto de mensajes que se
pueden aplicar a muchas clases de objetos, a los que cada una de ellas
debe responder de forma adecuada. Por eso, una interfaz recibe también
el nombre de protocolo.
Definición de una interfaz.
La definición de una interfaz es similar a la de una clase (clase abstracta); la
única diferencia es que en la cabecera se utiliza la palabra clave interface
en vez de class:

acceso interface NombreInterfaz


{
constante1;
• • •
constanteN;
tipo nombreMétodo1 (argumentos);
• • •
tipo nombreMétodoN (argumentos);
}

Donde acceso es la visibilidad de la interfaz definida, normalmente es


public, por eso no acostumbra ponerse. En una interfaz todos los métodos
declarados son, por defecto, públicos y abstractos; por eso no está
permitido anteponerles un modificador.
Implementación de una interfaz.
La interfaz especifica el comportamiento común que tiene un conjunto de
clases. Dicho comportamiento tiene que ser implementado en cada una de
las clases, lo que se define como implementación de una interfaz. Se utiliza
una sintaxis similar a la derivación de una clase, con la palabra reservada
implements en lugar de extends.

class NombreClase implements NombreInterfaz


{
// definición de atributos (variables).
// implementación de métodos de la clase.
// implementación de métodos de la interfaz.
}

La clase que implementa una interfaz tiene que especificar el código (la
implementación) de cada uno de los métodos de la interfaz. De no hacerlo,
la clase se convierte en clase abstracta y entonces debe declararse
abstract, lo que es una forma de obligar a que cada método de la interfaz
se implemente.
Java no permite la herencia múltiple, esto es, no permite que una clase
derive de dos o más clases. Sin embargo, una clase sí puede implementar
más de una interfaz y sí puede tener el comportamiento común de varias
interfaces. Lo que se hace, es escribir a continuación de la palabra
reservada implements las interfaces separadas por comas. La clase tiene
que implementar los métodos de todas las interfaces.

class NombreClase implements Interfaz1, Interfaz2, …, InterfazN


{
// definición de atributos (variables).
// implementación de métodos de la clase.
// implementación de métodos de la interfaz.
}

Una clase puede implementar tantas interfaces como se desee, se deben


implementar todos los métodos como public debido a que Java no permite
reducir la visibilidad de un método cuando se sobrescribe.
Las interfaces también se pueden organizar en forma jerárquica, de tal
forma que los métodos se heredan de una interfaz a la descendente. A
diferencia de las clases que solo pueden heredar de una superclase
(herencia simple), las interfaces pueden heredar de tantas interfaces como
se desee. También se utiliza la palabra reservada extends para
especificar la herencia de la interfaz.

interface SuperClase1 { … }
interface Clase1 extends SuperClase1 { … }
interface Clase2 extends SuperClase1 { … }
• • •
interface ClaseDerivada extends Clase1, Clase2 { … }
Debe tenerse en cuenta que una clase que implementa la interfaz
ClaseDerivada tiene que definir los métodos propios y los derivados de sus
interfaces antecedentes. Debido a que las interfaces no son clases, solo
especifican un comportamiento (métodos) que va a tener la clase que lo
implementa. Por esta razón, una clase puede heredar de su clase base y a
la vez implementar una interfaz. En este caso, se ha de especificar primero
la clase de la que hereda (extends) y a continuación la interfaz que
implementa (implements).

public interface InterfazA { … }


public class ClaseB { … }
public class ClaseC extends ClaseB { … }
public class ClaseD extends ClaseB implements InterfazA { … }
InterfazA

ClaseB

ClaseC ClaseD
MANEJO DE EXCEPCIONES.

El lenguaje Java incorpora soporte para manejar situaciones anómalas, conocidas


como excepciones, las cuales pueden ocurrir durante la ejecución de un programa.
Una excepción, en Java, es un objeto que describe una condición anormal que
surge en una secuencia de código durante la ejecución de un programa. Así, cuando
surge una condición excepcional, se crea un objeto que representa esa excepción y
se envía al método que ha originado el error. Ese método puede decidir entre
manejar el mismo la excepción o pasarla. En cualquiera de los dos casos, en algún
punto, la excepción es capturada y procesada. Las excepciones pueden ser
generadas por el intérprete Java o por el propio código. Las excepciones generadas
por Java se refieren a errores fundamentales que violan las reglas del lenguaje Java
o las restricciones del entorno de ejecución de Java. Las excepciones generadas
por el código se usan normalmente para informar de alguna condición de error en la
parte del código que llama al método.
El manejo de excepciones en Java se lleva a cabo mediante cinco palabras clave:
• try. Bloque donde se colocan las sentencias del programa que se quieren
controlar.
• catch. Bloque donde se captura la excepción y se maneja de forma racional.
• throw. Expresión para enviar manualmente la excepción.
• throws. Indica las excepciones que se envían desde un método.
• finally. Bloque opcional para código que el programador desee que se ejecute
siempre.
La forma general de un bloque de manejo de excepciones es la siguiente:

try {
••• // Bloque de código que controla los errores.
}
catch ( Tipo_de_excepción_1 e ) {
••• // Código de tratamiento de la excepción 1.
}
catch ( Tipo_de_excepción_2 e ) {
••• // Código de tratamiento para otra excepción 2.
}
// …
finally {
// Bloque de código que se debe ejecutar antes de que el bloque try termine.
}

Donde Tipo_de_excepción es el tipo de excepción que se ha producido.


Todos los tipos de excepciones son subclases de la clase incorporada por
Java, Throwable (lanzable). Además, esta clase se encuentra en la parte
superior de la jerarquía de clases Exception. Inmediatamente después de
Throwable se encuentran dos subclases que dividen las excepciones en
dos grupos. Un grupo es encabezado por Exception. Esta clase se utiliza
para condiciones excepcionales que los usuarios de programas deben
capturar. De esta clase se derivan también las subclases necesarias para
crear los propios tipos de excepciones. Una subclase importante de
Exception es RuntimeException. Las excepciones de este tipo son
definidas por los programas, e incluyen, por ejemplo, la división entre cero,
o la utilización de un índice no válido de un arreglo.
a) Bloques try.
Un bloque try debe encerrar las sentencias que pueden lanzar
excepciones. Un bloque try comienza con la palabra reservada try seguida
por una secuencia de sentencias de programa encerradas entre llaves. A
continuación del bloque try hay una lista de manejadores llamados
cláusulas catch. Al menos un manejador catch debe aparecer
inmediatamente después de un bloque try para manejar las excepciones
lanzadas, o si no hay manejador catch debe de especificarse el manejador
finally; en caso contrario, el compilador genera errores. Cuando un tipo de
excepción lanzada coincide con el tipo de excepción para un manejador
catch, el control se reanuda dentro del bloque del manejador catch. Si
ninguna excepción se lanza desde un bloque try, una vez que terminan las
sentencias del bloque, prosigue la ejecución a continuación del último
catch. Si hay un manejador finally (que es opcional), la ejecución sigue por
sus sentencias; una vez terminadas, continúa la ejecución en la sentencia
siguiente.
try {
num = LeerCad.readLine();
}
catch (IOException e) {
System.err.println ("Error: " + e.getMessage());
}
b) Bloques catch.
Un manejador de excepciones Java es una sentencia de captura catch.
Cuando una excepción se lanza desde sentencias dentro de un bloque try,
la lista de cláusulas catch que siguen al bloque try se buscan para
encontrar una cláusula que pueda manejar la excepción. Un bloque catch
consta de tres partes: la palabra reservada catch, la declaración de un
único argumento, que ha de ser un objeto para manejo de excepciones,
dentro del paréntesis (denominado como declaración de excepciones), y un
conjunto de sentencias dentro de una sentencia compuesta. Si la cláusula
catch se selecciona para manejar una excepción, se ejecuta la sentencia
compuesta. La especificación del manejador catch se asemeja a una
definición de una función o método en Java.
catch ( Tipo_de_excepción_1 e ) {
••• // Código de tratamiento de la excepción 1.
}
catch ( Tipo_de_excepción_2 e ) {
••• // Código de tratamiento para otra excepción 2.
}
•••
catch ( Exception e ) {
••• // Código de tratamiento para excepción por defecto.
}
El manejador de excepciones consta de la palabra reservada catch y de las
sentencias que le siguen (código del bloque o cuerpo manejador). Al
contrario del bloque try, el bloque catch sólo se ejecuta bajo circunstancias
especiales. El Tipo_de_excepción es la declaración de la excepción que
puede ser capturada, una referencia a un objeto de una clase ya definida, o
bien derivada de la clase base o superclase Exception.
Al igual que con los métodos sobrecargados, el manejador de excepciones
se activa sólo si el argumento que se pasa (o se lanza) corresponde con la
declaración del argumento. El último catch significa “cualquier excepción”,
ya que Exception es la superclase base de la jerarquía de clases que
tratan los errores. Se puede utilizar como manejador de excepciones por
defecto, ya que captura todas las excepciones no capturadas. La sintaxis
completa de try y catch permite escribir cualquier número de manejadores
de excepciones al mismo nivel.
c) Lanzamiento de excepciones, sentencia throw.
Un programa puede lanzar explícitamente una excepción mediante la
sentencia throw. La forma general de esta es la siguiente:
throw objeto

Donde objeto ha de ser un objeto de una clase derivada de la clase


Exception, del tipo Throwable o una subclase de Throwable. No se
pueden utilizar como excepciones tipos sencillos como int o char, ni
tampoco clases String y Object que no son Throwable. Se puede obtener
un objeto de la clase Throwable de dos formas: utilizando un parámetro en
la cláusula catch, o creando un nuevo objeto con el operador new.
La ejecución del programa se para inmediatamente después de una
sentencia throw; y cualquiera de las sentencias que siguen no se
ejecutarán. A continuación se inspecciona el bloque try más próximo que la
encierra, para ver si contiene una sentencia catch que coincida con el tipo
de excepción. Si es así, el control se transfiere a esa sentencia. Si no, se
inspecciona el siguiente bloque try que la engloba, y así sucesivamente. Si
no se encuentra una sentencia catch cuyo tipo coincida con el de la
excepción, entonces el gestor de excepciones por defecto interrumpe el
programa e imprime el trazado de la pila.
d) Sentencia throws.
Si un método puede dar lugar a una excepción que no es capaz de
manejar él mismo, se debe especificar este comportamiento de forma que
los métodos que llamen al primero puedan protegerse contra esa
excepción. Para ello, se incluye una cláusula throws en la declaración del
método. Una cláusula throws da un listado de los tipos de excepciones
que el método podría lanzar. Esto es necesario para todas las
excepciones, excepto las del tipo Error o RuntimeException, o cualquiera
de sus subclases. Todas las demás excepciones que un método puede
lanzar se deben declarar en la cláusula throws. Si esto no se hace así, el
resultado es un error de compilación.
e) Cláusula finally.
En un bloque try se ejecutan sentencias de todo tipo, llamadas a métodos,
creación de objetos; en ciertas aplicaciones se pedirán recursos al sistema
para ser utilizados. En aplicaciones que procesan información se abren
archivos para leerlos. Todos estos recursos deberán ser liberados cuando
termine el bloque try en que se han asignado; si no se ejecutan
normalmente todas las sentencias del bloque porque ha habido alguna
excepción, la sentencia catch que la captura debe encargarse de liberar
los recursos.
Java proporciona la posibilidad de definir un bloque de sentencias que se
ejecutarán siempre, ya sea que termine el bloque try normalmente o se
produzca una excepción. La cláusula finally crea un bloque de código que
se ejecutará después de que se haya completado un bloque try/catch y
antes de que se ejecute el código que sigue al bloque try/catch. El bloque
finally se ejecuta independientemente de que se haya lanzado o no alguna
excepción.
Si se ha lanzado una excepción, el bloque finally se ejecuta, incluso
aunque ninguna sentencia catch coincida con la excepción. Cuando un
método está a punto de devolver el control al método que lo llamó desde
dentro de un bloque try/catch por medio de una excepción no capturada o
de una sentencia return explícita, se ejecuta también la cláusula finally
justo antes de que el método devuelva el control. Esta acción tiene utilidad
para desbloquear archivos o liberar cualquier recurso que se hubiera
asignado al comienzo de un método, para liberarlo antes de devolver el
control. La cláusula finally es opcional. Sin embargo, cada sentencia try
requiere, al menos, una sentencia catch o finally.

// …
finally {
// Sentencias.
// Desbloqueo de archivos.
// Liberación de recursos.
}

Dentro del paquete estándar java.lang. Java define varias clases de


excepciones. Las principales excepciones definidas en java.lang se
detallan en la siguiente tabla.
Excepciones Significado
ArithmeticException Error aritmético, como, por ejemplo, división entre cero.
ArrayIndexOutOfBoundsException Índice del arreglo fuera de su límite o rango.
ArrayStoreException Se ha asignado a un arreglo un tipo incompatible.
ClassCastException Conversión o casting inválido.
IllegalArgumentException Uso inválido de un argumento a llamar a un método.
IllegalMonitorStateException Operación de monitor inválida, tal como esperar un hilo no
bloqueado.
IllegalStateException El entorno o aplicación están en un estado incorrecto o
inválido.
IllegalThreadStateException La operación solicitada es incompatible con el estado actual
del hilo.
IndexOutOfBoundsException Algún tipo de índice está fuera de rango o de su límite.
NegativeArraySizeException El arreglo tiene un tamaño negativo.
NullPointerException Uso incorrecto de una referencia a null.
NumberFormatException Conversión incorrecta de una cadena a un formato numérico.

SecurityException Intento de violación de seguridad.


StringIndexOutOfBounds Intento de sobrepasar el límite o rango de una cadena.
UnsupportedOperationException Operación no soportada.
La siguiente tabla muestra un listado de excepciones definidas por
java.lang que deben ser incluidas en la lista de un método throws si ese
método puede generar una de esas excepciones y no puede manejarla por
si mismo. A estas excepciones se les denomina excepciones comprobadas.
Java define otros tipos de excepciones en otros paquetes de su biblioteca
de clases.
Excepciones Significado
ClassNotFoundException No se ha encontrado la clase.
CloneNotSupportedException Intento de duplicación de un objeto que no
implementa la interfaz Clonable.
IllegalAccessException Se ha denegado el acceso a una clase.
InstantiationException Intento de crear un objeto de una clase abstracta o
interfaz.
InterruptedException Hilo interrumpido por otro hilo
NoSuchFieldException No existe el campo solicitado.
NoSuchMethodException No existe el método solicitado.
Aunque las excepciones del núcleo Java manejan la mayor parte de los errores más
habituales, el usuario puede querer crear sus propios tipos de excepciones para
tratar situaciones específicas que se presenten en sus aplicaciones. Esto se puede
hacer definiendo una subclase de Exception, que es una subclase de Throwable.
No es necesario que estas subclases creadas por el usuario implementen nada;
simplemente, su existencia en el sistema permitirá usarlas como excepciones.
La clase Exception no define por sí misma ningún método, pero hereda los
métodos que proporciona la clase Throwable, y todas las excepciones, incluyendo
las creadas por el usuario, pueden disponer de los métodos definidos por la clase
Throwable. Dichos métodos se muestran en la siguiente tabla. Además, éstos
métodos se pueden sobrescribir en las clases de excepción propias.
Método Descripción
Throwable fillInStackTrace() Devuelve un objeto de la clase Throwable que contiene el
trazado completo de la pila.
String getLocalizedMessage() Devuelve una cadena con la descripción localizada de la
excepción.
String getMessage() Devuelve una cadena con la descripción de la excepción.
void printStackTrace() Presenta en pantalla el trazado de la pila.
void printStackTrace(PrintStream stream) Envía el trazado de la pila a un determinado flujo.
void printStackTrace(PrintWriter stream) Envía el trazado de la pila a un determinado flujo.
String toString() Devuelve una cadena con la descripción de la excepción.
Este método es llamado por println() cuando se desea
imprimir un objeto de la clase Throwable.
La gestión de excepciones proporciona un mecanismo muy potente para
controlar programas complejos, con muchas características dinámicas,
durante la ejecución. Es importante considerar a try, throw y catch como
formas limpias de gestionar errores y problemas inesperados en la lógica de
un programa.
Resumiendo, el esquema general para el manejo o gestión de excepciones
usando los bloques try y catch, es:
1. Cuando una excepción se produce en sentencias del bloque try hay un
salto al primer manejador (la parte catch) cuyo parámetro coincida con el
tipo de excepción.
2. Cuando las sentencias en el manejador se han ejecutado, se termina el
bloque try y la ejecución prosigue en la sentencia siguiente. No se produce
nunca un salto hacia atrás al lugar en que ocurrió la interrupción.
3. Si no hay manejadores para tratar con una excepción, se aborta el
bloque try y la excepción se relanza.
4. El manejador opcional finally, en caso de utilizarse, se escribe después
del último catch. La ejecución del bloque try, se lance o no una excepción,
siempre termina con las sentencias de finally.
5. Si se produce una nueva excepción en el bloque try o dentro de algún
catch, sólo se propaga ésta última excepción.
UNIVERSIDAD AUTONOMA DE SINALOA
FACULTAD DE INFORMÁTICA DE MAZATLAN

PROGRAMACIÓN I
Arreglos
TITULAR DE LA MATERIA:
DR. JOSÉ NICOLÁS ZARAGOZA GONZÁLEZ
ARREGLOS.

Un arreglo es un conjunto de datos del mismo tipo a los cuales se les


denominada con un nombre común. Los datos se llaman elementos del
arreglo, y a un elemento específico de un arreglo se accede mediante un
índice. El tipo de elementos almacenados en el arreglo puede ser cualquier
tipo de dato simple de Java o de algún tipo previamente declarado, como un
objeto. Normalmente los arreglos se utilizan para almacenar datos de tipo
char, int o float.
En Java, los arreglos tienen que declararse. La declaración del arreglo
especifica su nombre y el tipo de elementos del mismo. Los arreglos
pueden tener una, dos o más dimensiones. De acuerdo a la dimensión del
arreglo estos se dividen en:

a) Arreglos Unidimensionales.
b) Arreglos Multidimencionales.
a) Arreglos Unidimensionales.
Como su nombre lo indica, son arreglos de una sola dimensión. También se
conocen con el nombre de vectores o listas. La forma general de
declaración de un arreglo unidimensional es cualquiera de las dos
siguientes:
tipo[ ] nombre;
tipo nombre[ ];
Donde tipo indica el tipo de los elementos del arreglo, los cuales pueden
ser de cualquier tipo primitivo o referenciado; y nombre es un identificador
que nombra al arreglo. Los corchetes modifican la definición normal del
identificador para que sea interpretado por compilador como un arreglo.
Colocando los corchetes a continuación del tipo de datos, indica que todos
los identificadores son arreglos de ese tipo.
Colocando los corchetes a continuación del nombre del arreglo, indica que
solo el identificador que tiene el nombre es un arreglo.
Java no permite en la declaración de una variable de arreglo definir su
dimensión o número de elementos, ya que en este caso el compilador
producirá un error.
Ejemplo:
int[ ] a;
float x[ ];
Después de haber declarado un arreglo, el siguiente paso es crearlo o
construirlo. Crear un arreglo significa reservar la cantidad de memoria
necesaria para guardar todos sus elementos y asignar al nombre del arreglo
una referencia a ese bloque. Esto se expresa de la siguiente manera:
nombre = new tipo[ tamaño ];
Donde nombre es el nombre del arreglo declarado; tipo es el tipo de los
elementos del arreglo; y tamaño es el tamaño o dimensión del arreglo, y
será una expresión entera positiva menor o igual que la precisión de un int,
especificando el número máximo de elementos que puede tener el arreglo.
El hecho de utilizar el operador new significa que Java implementa las
matrices como objetos, por lo tanto son tratadas como cualquier otro objeto.
a = new int[10];
x = new float[50];
Normalmente, se declaran y crean los arreglos en una misma línea. Esto se
hace de la siguiente manera:
tipo[ ] nombre = new tipo[ tamaño ];
tipo nombre[ ] = new tipo[ tamaño ];
Ejemplo:
int[ ] a = new int[10];
float x[ ] = new float[50];
Cuando se crea un arreglo, el tamaño del mismo también puede ser
especificado durante la ejecución a través de una variable a la que se
asignará como valor el número de elementos requeridos, el siguiente
fragmento de código ejemplifica esta caso, creando un arreglo con el
número de elementos especificados por n.
int n;
•••
System.out.print("Cuantos elementos tiene el vector: ");
n = LeerDato.numInt();
int arreglo[ ] = new int [n];

En todos los arreglos, el primer elemento tiene el 0 como índice. Por


ejemplo:
int p[ ] = new int[10];
Se está declarando un arreglo de caracteres que tiene diez elementos,
desde p[0] para el primer elemento hasta p[9] para el último elemento.
Debido a que los elementos del arreglo se guardan en posiciones contiguas
de memoria, y el arreglo tiene 10 elementos, tendríamos lo siguiente:
p [0] p [1] p [2] p [3] p [4] p [5] p [6] p [7] p [8] p [9]
valor 1 valor 2 valor 3 valor 4 valor 5 valor 6 valor 7 valor 8 valor 9 valor 10
Debido a que un arreglo es un objeto, cuando es creado, sus elementos
son automáticamente inicializados, al igual que sucede con las variables
miembro de una clase. Si el arreglo es numérico, sus elementos son
inicializados a 0 y si no es numérico, a un valor equivalente a 0; por
ejemplo, los caracteres son inicializados a ‘\u0000’, un elemento booleano
a false y las referencias a objetos, a null.
Si deseamos inicializar un arreglo con otros valores diferentes a los
predeterminados, podemos hacerlo de la siguiente manera:

double[ ] x = {5.2, 8.4, 1.5, 2.2, 10.1, 3.6, 4.8, 7.7, 6.4, 9.1};

Crea el arreglo unidimensional x de tipo double con diez elementos los


cuales se especifican entre llaves.
Acceso a los elementos de un arreglo.
Para acceder al valor de un elemento de un arreglo, se utiliza el nombre del
arreglo, seguido de un subíndice entre corchetes. Si se intenta acceder a un
elemento con un subíndice menor que cero o mayor que el número de
elementos del arreglo menos uno, Java lanzará una excepción de tipo
ArrayIndexOutOfBoundsException, indicando que el subíndice está fuera
de los límites establecidos cuando se creo el arreglo.

Para evitar errores, podemos verificar la longitud del arreglo mediante la


variable estática length, a la cual se puede acceder desde cualquier
arreglo. El formato es:
nombre_arreglo.length
class Arreglos3
{
public static void main(String args[ ])
{
int arreglo [ ] = new int [10];
int i;
System.out.println("Este programa imprime solamente los elementos de
la longitud que tiene el arreglo.");
System.out.println("En JAVA los arreglos comienzan en el elemento 0.");
System.out.println("Utiliza la variable estática: length");
System.out.println();
for (i = 0; i < arreglo.length; i++) {
arreglo[i] = i + 1;
System.out.println("Elemento ["+i+"] del arreglo = "+arreglo[i]);
}
} /* fin del main */
} /* fin de la clase */
CADENAS Y ARREGLOS DE CARACTERES.

Un arreglo es un conjunto de datos del mismo tipo y una cadena es un


conjunto de caracteres. En Java, las cadenas son objetos de la clase String
la cual está implementada en el paquete java.lang. Existe diferencia entre
los arreglos de caracteres y las cadenas de caracteres. Las cadenas o
strings son objetos en los que se almacenan cadenas de texto, tienen
diversos constructores y métodos derivados de las clases String y
StringBuffer. Los arreglos de caracteres son arreglos de tipo char en los
cuales se almacenan caracteres y tienen las mismas características que los
arreglos de otro tipo.
String cadena = “Informatica”; // declaración de una cadena de caracteres.
char[ ] arreglo = new char[ ]; // declaración de un arreglo de caracteres.
Básicamente, un arreglo de caracteres se almacena como un arreglo
unidimensional de elementos de tipo char. Al igual que con los otros tipos de
arreglos, puede ser inicializada al momento de ser definida.
char[ ] arreglo = {‘A’, ‘B’, ‘C’, ‘D’};

Debido a que cada carácter es un entero, también podemos inicializar el


arreglo de la siguiente manera:
char[ ] arreglo = { 65, 66, 67, 68};

Cada carácter tiene asociado un entero entre 0 y 65535 (código Unicode), y


los primeros 128 códigos Unicode coinciden con los primeros 128 códigos
ASCII y ANSI. Así, a la ‘A’ le corresponde el valor 65, a la ‘B’ el 66, y así
sucesivamente. Cuando se crea un arreglo de caracteres y se le asigna un
número de caracteres menor que su tamaño, el resto de los elementos
quedan con el valor ‘\0’ (carácter nulo) con el que fueron inicializados. Por
ejemplo, en los siguientes programas, la llamada a println imprime una
cadena visualizando todos los caracteres hasta finalizar el arreglo, incluidos
los nulos (‘\0’), aunque estos se visualizan como espacios en blanco. Si
intentamos acceder a un elemento con un subíndice fuera de los límites
establecidos al crear el arreglo, Java lanzará una excepción durante la
ejecución.
class Arreglos4
{
public static void main(String args[ ])
{
char[ ] arreglo = new char[10];
arreglo[0] = 'A';
arreglo[1] = 'B';
arreglo[2] = 'C';
arreglo[3] = 'D';

System.out.println("Programa que maneja un arreglo de caracteres.");


System.out.println(arreglo);
System.out.println();
} /* fin del main */
} /* fin de la clase */
class Arreglos5
{
public static void main(String args[ ])
{
char[ ] arreglo = new char[10];
arreglo[0] = 65;
arreglo[1] = 66;
arreglo[2] = 67;
arreglo[3] = 68;

System.out.println("Programa que maneja un arreglo de caracteres.");


System.out.println(arreglo);
System.out.println();
} /* fin del main */
} /* fin de la clase */
La lectura y escritura de arreglos de caracteres requiere del manejo de
ciclos, ya que dichos procesos se llevan a cabo leyendo, y escribiendo,
carácter por carácter. Para leer, ejecutamos el método read del flujo in y
almacenamos cada carácter leído en la siguiente posición libre del arreglo
de caracteres. Asimismo, para imprimir el arreglo de caracteres, utilizamos
el método print del flujo out.
El manejo de arreglos de caracteres puede resultar complicado ya que se
debe trabajar con los caracteres que se encuentran en el arreglo, elemento
por elemento. En el caso de las cadenas de caracteres, existen dos clases
que proporcionan los métodos para el manejo de cadenas, estas clases
son: String y StringBuffer.
El siguiente programa imprime los caracteres ASCII del 32 al 128.
class Arreglos7
{
public static void main(String args[ ])
{
char[ ] arreglo = new char[130];
private int i = 0;
System.out.println("Programa que muestra los caracteres imprimibles
del código ASCII.");
System.out.println();
for (i=32;i<=128;i++){
arreglo[i] = (char) i;
System.out.println("Caracter: "+arreglo[i]+" Valor ASCII: "+i);
}
System.out.println();
} /* fin del main */
} /* fin de la clase */
b) Arreglos Multidimencionales.
Un arreglo multidimensional, como su nombre lo indica, es un arreglo de
dos o más dimensiones, y en consecuencia, tienen más de un índice. La
definición de un arreglo de varias dimensiones se hace de la forma
siguiente:
tipo[ ][ ]…[ ] nombre_arreglo = new tipo[dim1][dim2]…[dimN];
tipo nombre_arreglo[ ][ ]…[ ] = new tipo[dim1][dim2]…[dimN];

Donde tipo es un tipo primitivo (entero, real o carácter). El número de


elementos de un arreglo multidimensional es el producto de las
dimensiones indicadas por sus dimensiones: dim1, dim2, …, dimN.
Sin embargo, dentro de los arreglos multidimensionales, los más utilizados
son los arreglos bidimensionales. Un arreglo bidimensional es en realidad
un arreglo de arreglos unidimensionales, donde cada elemento del arreglo
es otro arreglo. También se conocen como matrices o tablas. Los arreglos
bidimensionales se declaran utilizando la siguiente forma general:
tipo_dato[ ][ ] nombre_arreglo;
tipo_dato nombre_arreglo[ ][ ];
Las declaraciones no reservan memoria para los elementos de la matriz o
tabla, solo son referencias. Para reservar memoria y especificar el número
de filas y columnas se utiliza el operador new.
nombre_arreglo = new tipo[renglón][columna];

La sintaxis completa para definir una matriz utilizando el operador new es:
tipo_dato[ ][ ] nombre_arreglo = new tipo[renglón][columna];
tipo_dato nombre_arreglo[ ][ ] = new tipo[renglón][columna];

Los arreglos bidimensionales se almacenan en matrices fila-columna, en las


que el primer índice indica la fila y el segundo indica la columna. Por
ejemplo, si imaginamos un arreglo en formato matricial de renglones y
columnas, al declarar un arreglo entero de 4x5 llamada matriz, tenemos lo
siguiente:
int matriz[ ] [ ] = new int [4] [5];

matriz Columna 0 Columna 1 Columna 2 Columna 3 Columna 4


Fila 0 matriz [0] [0] matriz [0] [1] matriz [0] [2] matriz [0] [3] matriz [0] [4]
Fila 1 matriz [1] [0] matriz [1] [1] matriz [1] [2] matriz [1] [3] matriz [1] [4]
Fila 2 matriz [2] [0] matriz [2] [1] matriz [2] [2] matriz [2] [3] matriz [2] [4]
Fila 3 matriz [3] [0] matriz [3] [1] matriz [3] [2] matriz [3] [3] matriz [3] [4]
Los arreglos multidimensionales se pueden inicializar, al igual que los de
una dimensión, cuando se declaran. La inicialización se hace utilizando
llaves, encerrando entre llaves la lista de constantes separadas por comas,
definiendo cada fila. Por ejemplo, el arreglo matriz1 de tres columnas por
tres renglones, se inicializará con los valores del 1 al 9 utilizando orden de
filas y puede hacerse de las siguientes maneras:
int matriz1 [ ] [ ] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };

int matriz1 [ ] [ ] = { {1, 2, 3},


{4, 5, 6},
{7, 8, 9} };

int matriz1 [ ] [ ] = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};

Esta inicialización hace que matriz1[0] [0] tenga el valor de 1, matriz1[0] [1]
tenga el valor de 2, matriz1[0] [2] tenga el valor de 3, y así sucesivamente.
Debido a que Java trata los arreglos de dos o más dimensiones como
arreglos de arreglos, se pueden crear arreglos de dos dimensiones no
cuadradas, incluso en varias sentencias.

1. Se define una matriz de dos filas, la primera con dos columnas y la


segunda con tres:
double m1[ ][ ] = { {1.5, 2.5}, {5.0, 7.5, 10.5} };

2. Se define el arreglo a de tres elementos, el b de cuatro elementos y la


matriz mab de dos filas, la primera con tres columnas y la segunda con
cinco.
int[ ] a = { 1, 3, 5}, b = { 2, 4, 6, 8, 10};
int mab[ ] [ ] = { a, b};

3. Se define primero la matriz mat de tres filas. A continuación, los


elementos de cada fila.
double[ ] [ ] mat = new double[3] [ ];
mat[0] = new double[3];
mat[1] = new double[4];
mat[2] = new double[5];
4. El siguiente ejemplo muestra la aplicación del atributo length en un
arreglo bidimensional. Al tratarse de un arreglo de arreglos, el atributo
length de la matriz tabla contiene el número de filas, y el atributo length de
cada arreglo de fila contiene el número de columnas.
double tabla[ ][ ] = { { 1., 1., 1.}, { 2., 2.}, { 3., 3., 3., 3.} };

System.out.println(tabla.length); // escribe 3
System.out.println(tabla[0].length); // escribe 3
System.out.println(tabla[1].length); // escribe 2
System.out.println(tabla[2].length); // escribe 4

En la definición de un arreglo bidimensional no se debe omitir el número de


filas. La siguiente declaración es errónea, ya que no se han especificado el
número de filas y el tamaño queda indeterminado:
double m[ ][ ] = new double[ ][5];
Manejo de tablas y matrices.
El orden natural de procesar los vectores es el orden secuencial, esto es,
del primero al último elemento. Sin embargo, en el caso de los arreglos
multidimensionales existen diferentes órdenes para su recorrido. Estos son:
recorrido por filas (renglones) que es como se almacenan en memoria y
recorrido por columnas.
Recorrido por filas/columnas.
Los elementos de la primera fila/columna se procesan primero, a
continuación los de la segunda fila/columna, y así sucesivamente.
Ejemplo:
Sea el arreglo A de 3 filas y 4 columnas, los posibles recorridos son:
Recorrido por filas (renglones):
A [0,0] → A [0,1] → A [0,2] → A [0,3]
A [1,0] → A [1,1] → A [1,2] → A [1,3]
A [2,0] → A [2,1] → A [2,2] → A [2,3]

int matriz [ ] [ ] = new int [3] [4];


int fila, columna;
...
for (fila = 0; fila < 3; fila++)
for (columna = 0; columna < 4; columna++)
matriz[fila][columna ] = LeerDato.numInt();
Recorrido por columnas:
A [0,0] A [0,1] A [0,2] A [0,3]
↓ ↓ ↓ ↓
A [1,0] A [1,1] A [1,2] A [1,3]
↓ ↓ ↓ ↓
A [2,0] A [2,1] A [2,2] A [2,3]

int matriz [ ] [ ] = new int [3] [4];


int fila, columna;
...
for (columna = 0; columna < 4; columna++)
for (fila = 0; fila < 3; fila++)
matriz[fila][columna ] = LeerDato.numInt();
Arreglos como parámetros.
En Java, todas las variables de tipos primitivos: double, float, char, int,
boolean, etc., se pasan por valor. Los objetos siempre se pasan por
referencia, debido a que en Java los arreglos son objetos, siempre se pasan
por referencia (dirección). Esto significa que cuando se llama a un método o
función y se utiliza un arreglo como parámetro, se debe tener cuidado de no
modificar el arreglo en la función que lo llama.
El argumento del método que le corresponde a un arreglo se declara
poniendo el tipo de los elementos del arreglo, el identificador o nombre del
arreglo y los corchetes en blanco, se ponen tantos corchetes como
dimensiones. Aunque el arreglo completo se pasa por referencia, los
elementos individuales de un arreglo de tipo de datos primitivos se pasan
por valor como si fueran variables del tipo de datos del arreglo.
Normalmente, el número de elementos del arreglo no se pasa como
argumento, ya que el tamaño del arreglo se conoce con el atributo length.
Sin embargo, en algunos programas se pueden pasar el número de
elementos del arreglo mediante una variable entera independiente, esto se
hará solo cuando el arreglo haya sido declarado con una dimensión mayor y
solo se estén utilizando unas cuantas posiciones de los elementos del
arreglo, ya que no todos los elementos pueden ser significativos. Un
arreglo, puede ser declarado después de leer sus dimensiones y hasta ese
momento definir su tamaño.
Arreglos bidimensionales de caracteres.
También se pueden manejar arreglos bidimensionales de caracteres, en las
que cada fila se corresponde con una cadena de caracteres. Así, una fila
puede ser un objeto arreglo unidimensional, un objeto String o un objeto
StringBuffer. Al igual que con los arreglos bidimensionales numéricos, la
definición de un arreglo bidimensional de cadenas de caracteres puede
hacerse de la forma siguiente:
char nombre_arreglo = new char[filas][longitud_fila];
ORDENAMIENTO DE UN ARREGLO.

La ordenación o clasificación de datos (sort en inglés) es una operación


consistente en disponer un arreglo en algún determinado orden
(ascendente o descendente). Los elementos numéricos se pueden ordenar
en forma creciente o decreciente de acuerdo al valor numérico del
elemento, y las letras y cadenas, alfabéticamente según su valor ASCII. El
elemento por el cual está ordenado un conjunto de datos se denomina
clave.
Un conjunto de datos puede ser almacenado en un archivo, un arreglo
(vector o matriz) o un arreglo de objetos. Cuando los datos están
almacenados en un arreglo, se denomina ordenación interna. Si los datos
están almacenados en un archivo, el proceso de ordenación se llama
ordenación externa.
Una lista se dice que está ordenada por la clave X, si la lista está en orden
ascendente o descendente con respecto a esta clave. La lista se dice que
está en orden ascendente si:
i < j implica que X [i] <= X[j]
y se dice que está en orden descendente si:
i < j implica que X [i] >= X[j]
para todos los elementos de la lista.
Existen varios métodos (algoritmos) de ordenación, con diferente nivel de
eficiencia. La eficiencia es el factor que mide la calidad y rendimiento de un
algoritmo, normalmente son dos los criterios que nos permiten determinar
cual algoritmo es más eficiente:
1) Tiempo menor de ejecución.
2) Menor número de instrucciones.
Los métodos de ordenación se dividen en dos grandes grupos:
a) Directos: burbuja, selección, inserción, etc.
b) Indirectos (avanzados): shell, ordenación rápida, ordenación por mezcla, etc.
En el caso de listas pequeñas, los métodos directos son eficientes y sus
algoritmos son sencillos.

Ordenamiento por Burbuja.


Este método es clásico y muy sencillo aunque poco eficiente. La ordenación
por burbuja (“bubble sort”) se basa en comparar los elementos adyacentes
de la lista (vector) e intercambiar sus valores si están desordenados. De
esta manera se dice que los valores más pequeños suben como burbujas
hacía la parte superior de la lista (hacía el primer elemento), mientras que
los valores más grandes se hunden hacía el fondo de la lista.
// Ordenamiento por Burbuja simple en forma ascendente.

public void burbujaFor (int A[ ])


{
int Aux, i = 0, j = 0;
for (i=0;i<A.length -1;i++){
for (j=0;j<A.length -1;j++){
if (A[j] > A[j+1]){
Aux = A[j];
A[j] = A[j+1];
A[j+1] = Aux;
} // fin del if
} // fin del for interno
} // fin del for externo
}
La técnica de ordenación por burbuja compara elementos consecutivos de
la lista, de modo que si en una pasada no ocurrieran intercambios, significa
que la lista está ordenada. El algoritmo de burbuja se puede mejorar si
contamos con algún tipo de indicador que nos diga si se han producido
intercambios en la pasada. Cuando se explore la lista y el indicador no
muestre intercambios, la lista ya estará ordenada y se terminarán las
comparaciones. El ciclo externo Desde (for) se sustituye por ciclos
Mientras (while) o Haz-Mientras (do-while), con una variable llamada
Intercambio de tipo lógica (boolean) como indicador o bandera, con valores
de Verdadero (true) y Falso (false).
El siguiente método ordena un arreglo con el método de
burbuja mejorado usando: while.

public void burbujaWhile (int A[ ])


{
int Aux = 0, j = 0, paso = 1;
boolean intercambio = true;
while ((paso <= A.length -1) && (intercambio == true)){
intercambio = false;
for (j=0;j<A.length -paso;j++){
if (A[j] > A[j+1]){
intercambio = true;
Aux = A[j];
A[j] = A[j+1];
A[j+1] = Aux;
} // fin del if
} // fin del for
paso++;
} // fin del while
}
El método ordena un arreglo con el método de burbuja mejorado usando:
do - while.
public void burbujaDo (int A[ ])
{
int Aux = 0, j = 0, paso = 1;
boolean intercambio = true;
do {
intercambio = false;
for (j=0;j<A.length -paso;j++){
if (A[j] > A[j+1]){
intercambio = true;
Aux = A[j];
A[j] = A[j+1];
A[j+1] = Aux;
} // fin del if
} // fin del for
paso++;
} while ((paso <= A.length -1) && (intercambio == true)); // fin del do-while
}
Ordenamiento por Selección.
El algoritmo de ordenación por selección de una lista de n elementos, tiene
los siguientes pasos:
1. Encontrar el elemento menor de la lista.
2. Intercambiar el elemento menor con el elemento de subíndice n (o con el
elemento mayor en el subíndice 1).
3. A continuación se busca el elemento menor en la sublista de subíndices
1 ... n - 1, y se intercambia con el elemento de subíndice n - 1; colocándose
el segundo elemento menor en la posición n -1.
4. Se continúa la búsqueda con el elemento menor de la sublista 1 ... n - 2,
y así sucesivamente hasta terminar con todos los elementos.
Programa que ordena un arreglo de elementos con el método de selección.
public void seleccion (int A[ ])
{
int Aux = 0, j = 0, k = 0, menor = 0, posicion = 0;
for (j=0;j<A.length -1;j++){
menor = A[j];
posicion = j;
for (k=j+1;k<A.length ;k++){
if (menor > A[k]){
menor = A[k];
posicion = k;
} // fin del if
} // fin del for interno
Aux = A[j];
A[j] = A[posicion];
A[posicion] = Aux;
} // fin del for externo
}
BÚSQUEDA EN UN ARREGLO.

Un problema común al manejar arreglos, es la búsqueda de un determinado


elemento para determinar si se encuentra contenido en el arreglo.
Para buscar algún elemento cualquiera del arreglo (llamémoslo elemento
B), se debe comparar el elemento dado, con cada uno de los diferentes
elementos del arreglo según el tipo de búsqueda, para lo cual usamos
sentencias como la siguiente:
Si ( A[i] = B ) entonces . . .

Los dos tipos de búsqueda más usados son:


a) Búsqueda Lineal.
b) Búsqueda Binaria.
a) Búsqueda Lineal.
La búsqueda lineal o secuencial es la técnica más simple para buscar un
elemento en un arreglo (vector). El método consiste en el recorrido de todo
el arreglo, desde el primer elemento hasta el último, uno por uno. Si el
vector contiene el elemento, el proceso devolverá la posición del elemento
buscado dentro del vector, en caso contrario, mostrará un mensaje que
indique que el elemento no fue encontrado.
Mediante un ciclo Desde (for), podemos ir comparando el elemento B
buscado con A[i] donde i varía, desde 1 hasta el total de elementos. Sin
embargo, con el ciclo Desde se recorre el arreglo completo
(independientemente de si encuentra o no el elemento buscado). El proceso
de búsqueda se puede optimizar si se realiza mediante ciclos Mientras
(while) o Haz-Mientras (do-while), usando interruptores o banderas
(variables lógicas o booleanas) que detecten cuándo encuentre el
elemento, por lo que el ciclo se terminará por dos posibles causas:
1a. La bandera o indicador toma el valor verdadero (true) y el elemento es
encontrado.
2a. El valor del índice i es mayor que el número de elementos de la lista, lo
que significa que terminó de recorrer dicha lista y el elemento buscado no
fue encontrado.
Búsqueda de un elemento dentro de arreglo con el método de búsqueda
lineal usando: for. Inicializamos posicion = -1 porque en Java los arreglos
comienzan en la posición 0.

public int busquedaLinealFor (int A[ ], int b)


{
int i = 0, posicion = -1;
for (i=0;i<A.length ;i++)
if (A[i] == b) posicion = i;
return (posicion);
}
Búsqueda dentro de arreglo con el método de búsqueda lineal usando:
while.
public int busquedaLinealWhile (int A[ ], int b)
{
int i = 0, posicion = -1;
boolean encontrado = false;
while ((i < A.length ) && (encontrado == false)){
if (A[i] == b){
posicion = i;
encontrado = true;
}
i++;
}
return (posicion);
}
Búsqueda en un arreglo con el método de búsqueda lineal usando:
do - while.
public int busquedaLinealDo (int A[ ], int b)
{
int i = 0, posicion = -1;
boolean encontrado = false;
do {
if (A[i] == b){
posicion = i;
encontrado = true;
}
i++;
} while ((i < A.length ) && (encontrado == false));
return (posicion);
}
b) Búsqueda Binaria.
La búsqueda lineal es buena para listas de datos pequeñas, para listas
grandes es ineficiente. En estos casos el método de búsqueda binaria o
dicotómica es el ideal, el único inconveniente es que la lista de elementos
debe estar ordenada.
Se divide la lista en dos y se ve el elemento central, si no se ha acertado
se busca en que parte (la primera o la segunda) se encuentra el elemento
buscado. Se repite este proceso hasta que por divisiones o
aproximaciones sucesivas se encuentra el elemento buscado.
Búsqueda de un elemento dentro de arreglo con el método de
búsqueda binaria.
public int busquedaBinaria (int A[ ], int b)
{
int primero = 0, ultimo = A.length , puntomedio = 0, posicion = -1;
boolean encontrado = false;
while ((encontrado == false) && (primero <= ultimo)) {
puntomedio = (primero + ultimo) / 2;
if (A[puntomedio] == b)
encontrado = true;
else
if (A[puntomedio] > b)
ultimo = puntomedio - 1;
else
primero = puntomedio + 1;
}
if (encontrado == true)
posicion = puntomedio;
else
posicion = -1;
return (posición);
}
Clase Arrays.
La clase Arrays del paquete java.util contiene varios métodos static para
manejar arreglos. Estos métodos son: binarySearch, equals, fill y sort.
a) Método binarySearch.
Este método permite buscar un valor en un arreglo que este ordenado en forma
ascendente utilizando el algoritmo de búsqueda binaria visto anteriormente. La
sintaxis expresada de forma genérica para utilizar este método es la siguiente:
int binarySearch( tipo[ ] a, tipo clave)

donde a representa al arreglo, clave es el valor que se desea buscar y que debe ser
del mismo tipo que los elementos del arreglo, y tipo que es cualquier tipo de datos de
los siguientes: byte, char, short, int, long, float, double y Object.
El valor devuelto es un entero correspondiente al índice del elemento que coincide
con el valor buscado. Si el valor buscado no se encuentra, entonces el valor devuelto
es: -(punto de inserción) – 1. El valor de punto de inserción es el índice del elemento
de la matríz donde debería encontrarse el valor buscado. La expresión “-(punto de
inserción) – 1” garantiza que el índice devuelto será mayor o igual que cero solo si el
valor buscado es encontrado. Ejemplo:
int i;
int b[ ] = {9,12,15,34,45,45,46,64,96,107,456,784};
i = Arrays.binarySearch(b, 15); // i = 2
i = Arrays.binarySearch(b, 35); // i = -5
i = Arrays.binarySearch(b, 64); // i = 7
i = Arrays.binarySearch(b, 750); // i = -12
b) Método equals.
Este método permite verificar si dos arreglos son iguales. Dos arreglos se
consideran iguales cuando ambos tienen el mismo número de elementos y
en el mismo orden. Asimismo, dos arreglos también son considerados
iguales si sus referencias valen null. La sintaxis para este método
expresada en forma genérica es la siguiente:
boolean equals(tipo[ ] a1, tipo[ ] a2)

donde a1 y a2 son arreglos del mismo tipo y tipo que es cualquier tipo de
datos de los siguientes: byte, char, short, int, long, float, double y Object.
El valor devuelto será true si ambos arreglos son iguales y false en caso
contrario. Ejemplo:
int b[ ] = {9,12,15,34,45,45,46,64,96,107,456,784};
int c[ ] = {9,12,15,34,45,45,46,64,96,107,456,784};
if (Arrays.equals(b, c))
System.out.println("Los arreglos son iguales");
else
System.out.println("Los arreglos son diferentes");
c) Método fill.
Este método permite asignar un valor a todos los elementos de un arreglo,
o bien a cada elemento de un rango especificado. La sintaxis expresada de
forma genérica para utilizar este método es la siguiente:
void fill(tipo[ ] a, tipo valor)
void fill(tipo[ ] a, int desdeind, int hastaind, tipo valor)

donde a es el arreglo y valor es el valor a asignar. Cuando solo queramos


asignar el valor a un rango de elementos, utilizaremos el segundo formato
de fill donde desdeind y hastaind definen ese rango, tipo es cualquier tipo
de datos de los siguientes: byte, char, short, int, long, float, double y
Object. Ejemplo:
int c[ ] = {9,12,15,34,45,45,46,64,96,107,456,784};
Arrays.fill(c, 0); // rellena todo el arreglo con ceros
d) Método sort.
Este método permite ordenar los elementos de un arreglo en orden
ascendente utilizando el algoritmo quicksort (ordenamiento rápido), el cual
es más eficiente que los algoritmos de ordenamiento por burbuja y
selección. La sintaxis expresada en forma genérica para utilizar este
método es la siguiente:
void sort(tipo[ ] a)
void sort(tipo[ ] a, int desdeind, int hastaind)

donde a es el arreglo a ordenar. Cuando solo queremos ordenar un rango


de elementos, utilizaremos el segundo formato de sort donde desdeind y
hastaind definen los límites de ese rango, tipo es cualquier tipo de datos de
los siguientes: byte, char, short, int, long, float, double y Object.
Ejemplo:
int a[ ] = {46,64,456,96,45,15,107,34,12,784,9,45};
Arrays.sort(a);
UNIVERSIDAD AUTONOMA DE SINALOA
FACULTAD DE INFORMÁTICA DE MAZATLAN

PROGRAMACIÓN I
Cadenas
TITULAR DE LA MATERIA:
DR. JOSÉ NICOLÁS ZARAGOZA GONZÁLEZ
CADENAS.

Una cadena es un conjunto de caracteres. Debido a que Java no tiene el


tipo cadena incorporado como tipo primitivo, una cadena es un objeto de
tipo String, la cual está implementada en el paquete java.lang. Existe
diferencia entre los arreglos de caracteres y las cadenas de caracteres. Las
cadenas o Strings son objetos en los que se almacenan cadenas de texto,
tienen diversos constructores y métodos derivados de las clases String y
StringBuffer. por otra parte, los arreglos de caracteres son arreglos de tipo
char en los cuales se almacenan caracteres y tienen las mismas
características que los arreglos de otro tipo.

String cadena = “Informatica”; // declaración de una cadena de caracteres.


char[ ] arreglo = new char[ ]; // declaración de un arreglo de caracteres.
Los métodos de la clase String se utilizan para operar cadenas sin
modificar el objeto cadena, ya que un objeto cadena no puede modificarse,
esto significa que no se pueden cambiar los caracteres los caracteres que
lo conforman. Aunque esta parece ser una restricción importante, podemos
llevar a cabo todo tipo de operaciones con cadenas. La diferencia es que
cada vez que se necesite una versión modificada de una cadena existente,
se debe crear un nuevo objeto String que contenga las modificaciones. Así,
la cadena original se queda como estaba. Esto se hace así porque las
cadenas fijas se pueden manejar más eficientemente que las modificables.
En caso de que se desee una cadena modificable, existe otra clase
parecida a String, llamada StringBuffer, cuyos objetos contienen cadenas
que se pueden modificar una vez creadas.
Las clases String y StringBuffer, están definida en java.lang, por lo que se
encuentran disponibles para todos los programas automáticamente. Ambas
están declaradas como final, lo que significa que no se pueden crear
subclases a partir de ellas.
Los constructores String.
La clase String soporta varios constructores. Hay siete constructores de
objetos cadena que permiten construir desde un objeto cadena vacía hasta
un objeto a partir de otra cadena.
1. Constructor de cadena vacía.
Para crear una cadena vacía se puede utilizar el constructor por defecto.
Existen dos formas:
String s;
s = new String();

String s = new String();

Cualquiera de las formas anteriores crea un objeto cadena sin caracteres,


es una instancia de String sin ningún carácter en ella. Si a continuación
obtenemos su longitud con length(), ésta será cero.
2. Constructor de cadena a partir de otra cadena.
Con este constructor se crea un objeto cadena a partir de otro objeto
cadena ya creado y devuelve la referencia al objeto creado.
String cad1 = “Informática”, cad2;
• • •
cad2 = new String(cad1);

El objeto cadena que se pasa como argumento a este constructor puede ser
un literal, todo literal es un objeto cadena para Java.
String cad3 = new String(“Constante cadena”);

3. Constructor de cadena a partir de un objeto StringBuffer.


Los objetos de la clase StringBuffer tiene la característica de que son
modificables, mientras que los objetos String, una vez creados no pueden
cambiarse. Con este constructor, un objeto cadena String se crea a partir
de otro objeto StringBuffer.
StringBuffer cad5 = new StringBuffer(“Informática”);
String cad4 = new String(cad5); // Guarda: Informatica
4. Constructor de cadena a partir de un arreglo de caracteres.
Como vimos anteriormente, en Java un arreglo de caracteres no es una
cadena, pero sí se puede crear un objeto cadena a partir de un arreglo de
caracteres, pasando como argumento la variable arreglo.
char arreglo[ ] = { ‘I’, ’n’, ’f’, ’o’, ‘r’, ’m’, ’a’, ’t’, ’i’, ’c’, ’a’};
String cad6 = new String(arreglo); // Guarda: Informatica

5. Constructor de cadena a partir de un rango de caracteres.


El objeto cadena puede ser construido también con un rango de caracteres
pertenecientes a un arreglo. En este caso, al constructor se le pasa como
argumento el arreglo, copiando un determinado número de caracteres
desde una posición inicial.
String(char arregloCaracteres[ ], int posInicial, int númCaracteres);
char arreglo2[ ] = { ‘I’, ’n’, ’f’, ’o’, ‘r’, ’m’, ’a’, ’t’, ’i’, ’c’, ’a’};
String cad7 = new String(arreglo2,2,5); // Guarda: forma
6. Constructor de cadena a partir de un arreglo de bytes.
El tipo de dato primitivo byte puede almacenar los caracteres ASCII; sin
embargo, java utiliza caracteres Unicode de dos bytes. Aunque el tipo char
de java usa 16 bits para representar el conjunto de caracteres Unicode, el
formato típico para las cadenas de Internet usa arreglos de bytes de 8 bits
del conjunto de caracteres ASCII. Dado que las cadenas ASCII de 8 bits
son comunes, la clase String proporciona constructores que inicializan una
cadena cuando se les da un arreglo de bytes.
byte arregloBytes[ ];
String cadena = new String(byte arregloBytes[ ]);

byte arreglo3[ ] = { ‘I’, ’n’, ’f’, ’o’, ‘r’, ’m’, ’a’, ’t’, ’i’, ’c’, ’a’};
String cad8 = new String(arreglo3); // Guarda: Informatica
7. Constructor de cadena a partir de un rango de bytes.
Al igual que hay un constructor de cadena a partir de un rango de
caracteres, también hay un constructor a partir de un rango de bytes. En
este caso, el segundo argumento es el valor del byte más significativo que
usa el constructor para formar caracteres en unión de los bytes del arreglo.
byte arregloBytes[ ];
String cadena = new String(byte arregloBytes[ ], int posiciónInicial,
int numElementos);

byte arreglo4[ ] = { ‘I’, ’n’, ’f’, ’o’, ‘r’, ’m’, ’a’, ’t’, ’i’, ’c’, ’a’};
String cad9 = new String(arreglo4,5,4); // Guarda: mati

Los contenidos del arreglo se copian cada vez que se crea un objeto String
a partir de un arreglo. Si se modifican los contenidos del arreglo después de
creada la cadena, el objeto String no se modifica.
Lectura y escritura de cadenas.
La entrada de datos suele ser mediante una interacción con el usuario que
ejecuta el programa. La clase BufferedReader tiene diversos métodos
para lectura de datos. Cuando se ejecuta un programa, Java incorpora el
objeto System.in asociado con el flujo (stream) de entrada byte a byte.
Además la clase InputStreamReader convierte el flujo de bytes en una
cadena de caracteres. Esa es la razón por la cual se crea un objeto para la
lectura desde el teclado, que en este ejemplo llamamos entrada, y que se
muestra a continuación:
BufferedReader entrada = new BufferedReader (
new InputStreamReader ( System.in ) );

El método readLine() es el más utilizado para la entrada de datos desde el


teclado, pertenece a la clase BufferedReader, devuelve un objeto cadena
con los caracteres leídos hasta encontrar el carácter ‘\r’, ‘\n’ o los
caracteres ‘\r\n’ (fin de línea) introducidos al oprimir la tecla <ENTER>,
estos caracteres son leídos pero no son almacenados, solo se interpretan
como delimitadores.
Por su parte, la clase Scanner tiene el método next() para la lectura de
cadenas.
La clase System incorpora los objetos out, in y err que son creados
automáticamente al ejecutar un programa. El objeto in está asociado con la
entrada estándar, tiene métodos para la lectura de caracteres. El método
read() lee un carácter del dispositivo estándar de entrada, normalmente el
teclado, y devuelve el carácter leído. El método está sobrecargado para
poder leer de la entrada un arreglo de caracteres o solo un rango de
caracteres.
int read(byte[ ] cadena);
int read(byte[ ] cadena, int posición, int numCaracteres);

El objeto out está asociado con la salida estándar, los métodos print() y
println() se utilizan normalmente para salida de cadenas de caracteres. El
objeto System.out (que es una instancia de la clase PrintStream), además
de tener los métodos de salida print() y println() para cadenas caracteres,
sino que también tiene los métodos sobrecargados para dar salida a
caracteres individuales y datos de otros tipos primitivos (int, long, double,
etc.).
void print(String); void println(String);
void print(char); void println(char);
void print(char [ ]); void println(char [ ]);
void print(int); void println(int);
void print(long); void println(long);
void print(double); void println(double);
Ejemplo de lectura de una cadena con la clase BufferedReader:
BufferedReader leer = new BufferedReader (
new InputStreamReader ( System.in ) );
String cadena = “ “;
...
cadena = leer.readLine();

Ejemplo de lectura de una cadena usando la clase Scanner:


Scanner leer = new Scanner ( System.in );
String cadena = “ “;
...
cadena = leer.next();

Ejemplo de lectura de caracteres usando la clase System:


char c;
c = (char) System.in.read( );

Ejemplo de lectura de caracteres usando la clase Scanner:


char c;
String cadena = “ “;
cadena = leer.next();
c = (char) cadena.charAt(0);
Longitud de una cadena.
La longitud de una cadena es el número de caracteres que contiene. Para
obtener este valor se usa el método length(), mostrado a continuación:
int length( )

char arreglo5[ ] = { ‘I’, ’n’, ’f’, ’o’, ‘r’, ’m’, ’a’, ’t’, ’i’, ’c’, ’a’};
String cad10 = new String(arreglo);
System.out.println(cad10.length()); // Imprime: 11

Operaciones con cadenas.


Puesto que las cadenas son una parte común e importante de la
programación, Java proporciona dentro de su sintaxis un soporte especial
para diversas operaciones con cadenas. Estas operaciones incluyen la
creación automática de nuevas instancias String a partir de constantes de
cadena, la concatenación de múltiples objetos String mediante el uso del
operador +, así como la conversión de otros tipos de datos en una
representación de tipo cadena. Aunque hay disponibles métodos explícitos
para realizar todas estas funciones, Java lo hace automáticamente para
facilitar el trabajo del programador y para mayor claridad.
a) Constantes de cadena.
La forma más sencilla de crear una instancia String a partir de una
constante de cadena. Por cada constante de cadena que haya en un
programa, Java automáticamente construye un objeto String. Así se puede
usar una constante de cadena para utilizar un objeto String. Los siguientes
ejemplos crean dos cadenas equivalentes, la segunda forma es más
práctica y utiliza una constante de cadena.
byte arreglo[ ] = { ‘I’, ’n’, ’f’, ’o’, ‘r’, ’m’, ’a’, ’t’, ’i’, ’c’, ’a’};

String cadena = new String(arreglo);


String cadena = “Informática”; // Utiliza una constante de cadena.

Puesto que se crea un objeto String para cada constante de cadena, se


pueden usar constantes de cadena en cualquier sitio en el que se pueda
usar un objeto String. Por ejemplo, se puede llamar directamente a los
métodos con una cadena entre comillas como si fuera una referencia a un
objeto, como se muestra en la siguiente sentencia:
System.out.println(“Informatica”.length()); // Muestra: 11
b) Concatenación de cadenas.
En general, Java no permite aplicar operadores a los objetos String. La única
excepción a esta regla es el operador +, que concatena dos cadenas produciendo
un objeto String como resultado. Esto permite unir varias operaciones. También se
pueden concatenar cadenas pequeñas y formar una cadena más grande.
String temp = “30”;
String cadena = “Temperatura: ” + temp + ” grados.”;
System.out.println(cadena); // Imprime: Temperatura: 30 grados.

También se pueden concatenar cadenas con otro tipo de datos. Sin embargo, hay
que tener cuidado al mezclar otros tipos de datos de operaciones con expresiones
de concatenación de cadenas, ya que se pueden obtener resultados inesperados.
int temp = 30;
String cadena = “Temperatura: ” + temp + ” grados.”;
System.out.println(cadena); // Imprime: Temperatura: 30 grados.

String cadena = “Cuatro: ” + 2 + 2;


System.out.println(cadena); // Imprime: Cuatro: 22

Si queremos realizar primero la suma de enteros, hay que utilizar paréntesis y


colocar dentro la operación:
String cadena = “Cuatro: ” + (2 + 2);
System.out.println(cadena); // Imprime: Cuatro: 4
Clase String.

1. String toString()
Este método devuelve el propio objeto String que recibe el mensaje
toString.
String cad1 = “Informática”, cad2;
cad2 = cad1.toString(); // equivale a cad2 = cad1

2. String concat(String cadena)


Este método devuelve como resultado un nuevo objeto String resultado de
concatenar el String especificado a continuación del objeto String que
recibe el mensaje concat. Si alguno de los String tiene longitud 0, se
concatena una cadena nula.
String cad1 = “agua”, cad2 = “cate”;
cad1 = cad1.concat(cad2); // guarda en cad1: aguacate
3. int compareTo(String otroString)
Compara lexicográficamente el String especificado, con el objeto String
que recibe el mensaje compareTo (el método equals realiza la misma
operación). Esto significa que compara dos cadenas y permite saber si una
cadena está en orden alfabético antes (es menor) o después (es mayor)
que otra. La comparación se realiza sobre los valores Unicode de cada
carácter, diferenciando las mayúsculas de las minúsculas. El resultado
devuelto es un entero:
< 0 si el String que recibe el mensaje es menor que el otroString,
= 0 si el String que recibe el mensaje es igual que el otroString y
> 0 si el String que recibe el mensaje es mayor que el otroString.
Si en vez de utilizar el método compareTo() se utiliza el método
compareToIgnoreCase() no se hace diferencia entre mayúsculas y
minúsculas.
String cad1 = “Informatica”, cad2 = “informatica”;
if (cad1.compareTo(cad2) < 0)
Sistem.out.println(cad1); // Imprime cad1
4. int length()
Como vimos anteriormente, este método devuelve la longitud de una
cadena o el número de caracteres Unicode.
String cad = new String(“Informatica”);
System.out.println(cad.length()); // Imprime: 11

5. String toLowerCase()
Este método convierte a minúsculas las letras mayúsculas del objeto String
que recibe el mensaje toLowerCase. El resultado es un nuevo objeto
String en minúsculas.
String cad1, cad2 = “INFORMATICA”;
cad1 = cad2.toLowerCase(); // cad1: informatica

6. String toUpperCase()
Convierte las letras minúsculas del objeto String que recibe el mensaje a
mayúsculas, creando un nuevo objeto String.
String cad1, cad2 = “Informatica”;
cad1 = cad2.toUpperCase(); // cad1: INFORMATICA
7. String trim()
Este método devuelve un objeto String resultado de eliminar los espacios
en blanco que pudiera haber al principio y al final del objeto String que
recibe el mensaje trim.
String cad1 = “ Informatica ”, cad2 = “ “;
cad2 = cad1.trim(); // cad2: “Informatica” (sin espacios).

8. boolean startsWith(String prefijo)


Este método devuelve un valor true si el prefijo especificado coincide con el
principio del objeto String que recibe el mensaje startsWith.
String cad1 = “Informatica”;
if (cad1.startsWith(“In”)) System.out.println(cad1);

9. boolean endsWith(String prefijo)


Este método devuelve un valor true si el prefijo especificado coincide con el
final del objeto String que recibe el mensaje endsWith.
String cad1 = “Informatica”;
if (cad1.endsWith(“ca”)) System.out.println(cad1);
10. String subString(int IndiceInicial, int IndiceFinal)
El método devuelve un nuevo String que contiene una subcadena de la
cadena almacenada por el objeto String que recibe el mensaje subString.
La subcadena comienza en IndiceInicial y termina en IndiceFinal – 1, o
hasta el final si IndiceFinal no se especifica.
String cad1 = “Informatica”, cad2 = “ “;
cad2 = cad1.subString(2,6); // cad2: “forma”

11. char charAt(int índice)


Este método devuelve el carácter que está en la posición especificada en el
objeto String que recibe el mensaje charAt. El índice del primer carácter es
el 0. Por lo tanto, el parámetro índice tiene que estar entre los valores 0 y
length() – 1, de lo contrario Java lanzará una excepción.
char carácter;
String cad1 = “Informatica”;
carácter = cad1.charAt(5); // caracter: ‘m’
12. int indexOf(int carácter)
Devuelve el índice de la primera ocurrencia del carácter especificado por
carácter en el objeto String que recibe el mensaje indexOf. Si carácter no
existe, el método indexOf devuelve el valor -1. Se puede comenzar la
búsqueda por el final en lugar de hacerlo desde el principio utilizando el
método lastIndexOf.
int pos;
String cad1 = “Informatica”;
pos = cad1.indexOf(‘a’); // pos: 6
pos = cad1.lastIndexOf(‘a’); // pos: 10

13. String replace(char carácter, char nuevoCarácter)


Este método devuelve un nuevo String resultado de reemplazar todas las
ocurrencias de carácter por nuevoCarácter en el objeto String que recibe el
mensaje replace. Si el carácter no existiera, entonces se devuelve el objeto
String original.
String cad1 = “Informatica”;
cad1 = cad1.replace(‘a’,’e’); // cad1: “Informetice”
14. static String valueOf(tipo dato)
El método devuelve un nuevo String creado a partir del dato pasado como
argumento. Puesto que el método es static no necesita ser llamado para un
objeto String. El argumento puede ser de los tipos boolean, char, char[ ],
int, long, float, double y Object.
double pi = Math.PI;
String cad1 = String.valueOf(pi); // Guarda en cad1: 3.141592653589

15. char[ ] toCharArray()


Este método devuelve un arreglo de caracteres creado a partir del objeto
String que recibe el mensaje toCharArray().
String cad = “Informatica”;
char[ ] arreglocad = cad.toCharArray();
// arreglocad: {‘I’, ’n’, ’f’, ’o’, ‘r’, ’m’, ’a’, ’t’, ’i’, ’c’, ’a’}

16. byte[ ] getBytes()


Este método devuelve un arreglo de bytes creado a partir del objeto String
que recibe el mensaje de getBytes.
Clase StringBuffer.
Los objetos de la clase String no son modificables, los métodos que actúan
sobre los objetos String y que parecen modificarlos, no los modifican, sino
que devuelven un nuevo objeto con las modificaciones solicitadas. En
cambio, un objeto StringBuffer es un objeto modificable tanto en contenido
como en tamaño. Algunos de los principales métodos que proporciona la
clase StringBuffer, perteneciente al paquete java.lang, son los siguientes:

1. StringBuffer([argumento])
Este método permite crear un objeto de la clase StringBuffer. Así, cuando
StringBuffer se invoca sin argumentos construye un objeto vacío con una
capacidad inicial para 16 caracteres; cuando se invoca con un argumento
entero, construye un objeto vacío con la capacidad especificada; y cuando
se invoca con un String como argumento construye un objeto con la
secuencia de caracteres proporcionada por el argumento y una capacidad
igual al número de caracteres almacenados más 16.
StringBuffer cadena1 = new StringBuffer();
StringBuffer cadena2 = new StringBuffer(100);
StringBuffer cadena3 = new StringBuffer(“Informatica”);
2. int length()
Este método devuelve la longitud o número de caracteres Unicode (tipo
char) del objeto StringBuffer que recibe el mensaje length. Esta longitud
puede ser modificada por el método setLength cuando sea necesario.
StringBuffer cadena = new StringBuffer(“Informatica”);
System.out.println(cadena.length()); // Imprime: 11

3. int capacity()
Devuelve la capacidad en caracteres Unicode (tipo char) del objeto
StringBuffer que recibe el mensaje capacity.
StringBuffer cadena = new StringBuffer(“Informatica”);
System.out.println(cadena.capacity()); // Imprime: 27
4. StringBuffer append(tipo x)
Este método permite añadir la cadena de caracteres resultante de convertir
el argumento x en un objeto String, al final del objeto StringBuffer que
recibe el mensaje append. El tipo del argumento x puede ser boolean,
char, char[ ], int, long, float, double y Object. La longitud del objeto
StringBuffer se incrementa en la longitud correspondiente al String
añadido.
StringBuffer cadena = new StringBuffer(“Informatica”);
cadena.append(2006); // cadena = Informatica2006

5. StringBuffer insert(int índice, tipo x)


Permite insertar la cadena de caracteres resultante de convertir el
argumento x en un objeto String, en el objeto StringBuffer que recibe el
mensaje insert. Los caracteres serán añadidos a partir de la posición
especificada por el argumento índice. El tipo del argumento x puede ser
boolean, char, char[ ], int, long, float, double y Object. La longitud del
objeto StringBuffer se incrementa en la longitud correspondiente al String
insertado.
StringBuffer cadena = new StringBuffer(“Informatica”);
cadena.insert(6,”acion autom”); // cadena = “Informacion automatica”
6. StringBuffer delete(int pos1, int pos2)
El método elimina los caracteres que hay entre las posiciones pos1 y pos2
– 1 del objeto StringBuffer que recibe el mensaje delete. El valor pos2
debe ser mayor que pos1. Si pos1 es igual que pos2, no se efectuará
ningún cambio y si es mayor Java lanzará una excepción.
StringBuffer cadena = new StringBuffer(“Informatica”);
cadena.delete(7, cadena.length()); // cadena = “Informa”

7. StringBuffer replace(int pos1, int pos2, String cad)


Este método reemplaza los caracteres que hay entre las posiciones pos1 y
pos2 – 1 del objeto StringBuffer que recibe el mensaje replace, por los
caracteres especificados por cad. La longitud y la capacidad del objeto
resultante serán ajustadas automáticamente la valor requerido. El valor
pos2 debe ser mayor que pos1. Si pos1 es igual que pos2, la operación se
convierte en una inserción, y si es mayor Java lanzará una excepción.
StringBuffer cadena = new StringBuffer(“Informatica”);
cadena.replace(0, 4, “Tele”); // cadena = “Telematica”
8. StringBuffer reverse()
El método reemplaza la cadena almacenada en el objeto StringBuffer que
recibe el mensaje reverse, por la misma cadena pero invertida.
StringBuffer cadena = new StringBuffer(“Informatica”);
cadena.reverse(); // cadena = “acitamrofnI”

9. String subString(int IndiceInicial, int IndiceFinal)


El método devuelve un nuevo String que contiene una subcadena de la
cadena almacenada por el objeto StringBuffer que recibe el mensaje
subString. La subcadena comienza en IndiceInicial y termina en IndiceFinal
– 1, o hasta el final si IndiceFinal no se especifica.
StringBuffer cad1 = new StringBuffer(“Informatica”);
String cad2 = “ “;
cad2 = cad1.subString(2,6); // cad2: “forma”
10. char charAt(int índice)
Este método devuelve el carácter que está en la posición especificada en el
objeto StringBuffer que recibe el mensaje charAt. El índice del primer
carácter es el 0. Por lo tanto, el parámetro índice tiene que estar entre los
valores 0 y length() – 1.
char carácter;
StringBuffer cad1 = new StringBuffer(“Informatica”);
carácter = cad1.charAt(5); // caracter: ‘m’

11. void setCharAt(int índice, char carácter)


El método reemplaza el carácter que está en la posición especificada en el
objeto StringBuffer que recibe el mensaje setCharAt, por el nuevo
carácter especificado. El índice del primer carácter es el 0. Por lo tanto, el
parámetro índice debe estar entre los valores 0 y length() – 1.
StringBuffer cad1 = new StringBuffer(“Informatica”);
cad1.setCharAt(5, ’t’); // cad1: “Infortatica”

12. String toString()


Este método devuelve como resultado un nuevo String copia del objeto
StringBuffer que recibe el mensaje toString.
StringBuffer cad1 = new StringBuffer(“Informatica”);
String cad2 = cad1.toString(); // cad2: “Informatica”
Conversión de cadenas de caracteres a datos numéricos.
Cuando una cadena de caracteres representa un número y se necesita
realizar la conversión al valor numérico correspondiente, hay que utilizar los
métodos adecuados que son proporcionados por las clases del paquete
java.lang: clases Byte, Character, Short, Integer, Long, Float, Double y
Boolean, que encapsulan cada uno de los tipos primitivos. Resultan útiles
para la entrada de datos por el teclado, ya que tienen métodos que
convierten una cadena al tipo básico correspondiente a la clase.
String cad1 = “1234”;
int dato1 = Integer.parseInt(cad1); // Convierte a un int.

String cad2 = “12.34”;


double dato2 = Double.parseDouble(cad2); // Convierte a un double.
Clase Método
Byte parseByte(String)
Short parseShort(String)
Integer parseInt(String)
Long parseLong(String)
Float parseFloat(String)
Double parseDouble(String)
ARREGLOS DE CADENAS DE CARACTERES.

Las cadenas de caracteres, al igual que los tipos de datos primitivos y que
otros objetos, pueden agruparse para formar arreglos de caracteres. En
estos arreglos, cada fila se corresponde con una cadena de caracteres. Así,
una fila puede ser un objeto String o un objeto StringBuffer.
String[ ] nombre = new String[nFilas];

En el caso de utilizar objetos StringBuffer, se leen objetos String y se


guardan en el arreglo de objetos StringBuffer.
StringBuffer[ ] nombre = new StringBuffer[nFilas];
String cadNombre;
ORDENAMIENTO Y BUSQUEDA DE ARREGLOS
DE CADENAS.

Los procesos de ordenamiento y búsqueda son importantes en el manejo


de arreglos de cadenas, a continuación se presentan los métodos de
ordenamiento y búsqueda vistos anteriormente, aplicándolos a arreglos de
cadenas, teniendo en cuenta que la búsqueda es más eficiente si el arreglo
está ordenado.

Ordenación de un arreglo de cadenas.


Los arreglos de cadenas de caracteres, como los nombres, pueden
ordenarse alfabéticamente. El elemento por el cual está ordenado un
conjunto de datos se denomina clave. Las cadenas se comparan
lexicográficamente intercambiándolas si están desordenadas. Un arreglo de
cadenas se dice que está ordenado por la clave X, si la lista está en orden
ascendente o descendente con respecto a esta clave, considerando su
posición en el alfabeto, o su valor ASCII o Unicode.
La lista se dice que está en orden ascendente si:
i < j implica que X [i] <= X[j]
y se dice que está en orden descendente si:
i < j implica que X [i] >= X[j]
para todos los elementos de la lista.
Existen varios métodos (algoritmos) de ordenación, con diferente nivel de
eficiencia. A continuación se presentan nuevamente, los métodos de
ordenamiento por burbuja y ordenamiento por selección, ahora aplicados a
arreglos de cadenas por lo cual se les han hecho algunas modificaciones.
Así mismo, se aplican los métodos de las clases String y StringBuffer para
crear, comparar y copiar cadenas.
Los algoritmos de ordenación por burbuja, aplicando los ciclos for (simple),
while y do-while (mejorados) y por selección, se presentan a continuación:
Ordenamiento por Burbuja simple en forma ascendente.
public void burbujaFor (String A[ ])
{
int i = 0, j = 0;
String Aux = " ";
for (i=0;i<A.length -1;i++){
for (j=0;j<A.length -1;j++){
if (A[j].compareTo(A[j+1]) > 0){
Aux = A[j].toString();
A[j] = A[j+1].toString();
A[j+1] = Aux.toString();
} // fin del if
} // fin del for interno
} // fin del for externo
}
Ordenamiento por Burbuja mejorado usando while, en forma ascendente.
public void burbujaWhile (String A[ ])
{
int j = 0, paso = 1;
boolean intercambio = true;
String Aux = " ";
while ((paso <= A.length -1) && (intercambio == true)){
intercambio = false;
for (j=0;j<A.length -paso;j++){
if (A[j].compareTo(A[j+1]) > 0){
intercambio = true;
Aux = A[j].toString();
A[j] = A[j+1].toString();
A[j+1] = Aux.toString();
} // fin del if
} // fin del for
paso++;
} // fin del while
}
Ordenamiento por Burbuja mejorado usando do-while, en forma ascendente.
public void burbujaDo (String A[ ])
{
int j = 0, paso = 1;
boolean intercambio = true;
String Aux = " ";
do {
intercambio = false;
for (j=0;j<A.length -paso;j++){
if (A[j].compareTo(A[j+1]) > 0){
intercambio = true;
Aux = A[j].toString();
A[j] = A[j+1].toString();
A[j+1] = Aux.toString();
} // fin del if
} // fin del for
paso++;
} while ((paso <= A.length -1) && (intercambio == true)); // fin del
do-while
}
Ordenamiento por Selección en forma ascendente.
public void seleccion (String A[ ])
{
int j = 0, k = 0, posicion = 0;
String Aux = " ", menor = “ “;
for (j=0;j<A.length -1;j++){
menor = A[j].toString();
posicion = j;
for (k=j+1;k<A.length ;k++){
if (menor.compareTo(A[k]) > 0){
menor = A[k].toString();
posicion = k;
} // fin del if
} // fin del for interno
Aux = A[j].toString();
A[j] = A[posicion].toString();
A[posicion] = Aux.toString();
} // fin del for externo
}
Búsqueda en un Arreglo de Cadenas.
Un problema común al procesar los arreglos, es la búsqueda para
determinar si contiene un elemento de dato determinado.
Para buscar algún elemento cualquiera del arreglo (llamémoslo elemento
B), se debe comparar el elemento dado, con cada uno de los diferentes
elementos del arreglo según el tipo de búsqueda, para lo cual usamos
sentencias como la siguiente:
Si ( nombre[i] = b ) entonces . . .
Los dos tipos de búsqueda más usados son:
a) Búsqueda Lineal.
b) Búsqueda Binaria.

Los algoritmos de búsqueda lineal, aplicando los ciclos for (simple), while
y do-while (mejorados) y búsqueda binaria, se presentan a continuación:
Búsqueda lineal del elemento b, usando For.
public int busquedaLinealFor (String A[ ], String b)
{
// Inicializamos posicion = -1 porque los arreglos comienzan en la posición 0
int i = 0, posicion = -1;
for (i=0;i<A.length ;i++)
if (A[i].compareTo(b) == 0) posicion = i;
return (posicion);
}
Búsqueda lineal del elemento b, usando While.
public int busquedaLinealWhile (String A[ ], String b)
{
int i = 0, posicion = -1;
boolean encontrado = false;
while ((i < A.length ) && (encontrado == false)){
if (A[i].compareTo(b) == 0){
posicion = i;
encontrado = true;
}
i++;
}
return (posicion);
}
Búsqueda lineal del elemento b, usando Do-While.
public int busquedaLinealDo (String A[ ], String b)
{
int i = 0, posicion = -1;
boolean encontrado = false;
do {
if (A[i].compareTo(b) == 0){
posicion = i;
encontrado = true;
}
i++;
} while ((i < A.length ) && (encontrado == false));
return (posicion);
}
Búsqueda binaria del elemento b.
public int busquedaBinaria (String A[ ], String b)
{
int primero = 0, ultimo = A.length , puntomedio = 0, posicion = -1;
boolean encontrado = false;
while ((encontrado == false) && (primero <= ultimo)){
puntomedio = (primero + ultimo) / 2;
if (A[puntomedio].compareTo(b) == 0)
encontrado = true;
else
if (A[puntomedio].compareTo(b) > 0)
ultimo = puntomedio - 1;
else
primero = puntomedio + 1;
}
if (encontrado == true)
posicion = puntomedio;
else
posicion = -1;
return (posicion);
}
UNIVERSIDAD AUTONOMA DE SINALOA
FACULTAD DE INFORMÁTICA DE MAZATLAN

PROGRAMACIÓN I
Archivos
TITULAR DE LA MATERIA:
DR. JOSÉ NICOLÁS ZARAGOZA GONZÁLEZ
ARCHIVOS.

Desde el punto de vista computacional, un archivo es un conjunto de datos


o información que almacenamos en algún medio magnético, óptico o
electrónico, para poderla recuperar en cualquier momento. Esta información
se almacena como un conjunto de registros, conteniendo generalmente
todos ellos, los mismos registros. Cada campo almacena un dato de un tipo
predefinido o de un tipo definido por el usuario. En este caso, el registro
más simple estaría formado por un carácter.
Java proporciona clases y métodos que permiten leer y escribir archivos. En
Java, todos los archivos están orientados a bytes, y los métodos permiten
leer datos de un archivo y escribir datos en un archivo. Sin embargo, Java
también permite envolver un flujo de archivo orientado a bytes en un objeto
basado en caracteres.
Antes de iniciar el estudio de los archivos, debemos definir el concepto de
flujo. En Java, la entrada y salida se lee y se escribe a través de flujos
(streams). Java 2 define dos tipos de flujos: de bytes y de caracteres. Un
flujo es un objeto que hace de intermediario entre el programa y el origen o
destino de la información. Esto significa que el programa leerá o escribirá
en el flujo sin importarle desde dónde viene la información o adonde va, ni
el tipo de datos que se leen o escriben. Básicamente, la fuente de entrada
de datos es el teclado y la fuente de salida de resultados es la pantalla.
De esta manera, para que un programa pueda obtener información desde
un origen tiene que abrir un flujo y leer la información. Del mismo modo,
para que un programa pueda enviar información a un destino tiene que abrir
un flujo y escribir la información. Los algoritmos para leer y escribir datos
son siempre más o menos los siguientes:

Leer Escribir
Abrir un flujo desde un origen Abrir un flujo hacia un destino
Mientras haya información Mientras haya información
Leer información Escribir información
Cerrar el flujo Cerrar el flujo
Debido a que todas las clases relacionadas con flujos pertenecen al
paquete java.io de la biblioteca estándar de Java, un programa que utilice
flujos de Entrada/Salida (E/S), tendrá que importar este paquete:
import java.io.*;

Las clases del paquete java.io están divididas en dos grupos distintos. Uno
ha sido diseñado para trabajar con datos de tipo byte y el otro con datos de
tipo char.
Así mismo, la biblioteca de Java proporciona tres flujos estándar manejados
por la clase System del paquete java.lang. Estos flujos predefinidos son
automáticamente abiertos cuando se inicia un programa, y cerrados cuando
finaliza:
• System.in. Objeto entrada estándar del sistema, que normalmente es el
teclado. Se utiliza para leer datos introducidos por el usuario.
• System.out. Objeto salida estándar del sistema, que normalmente es la
pantalla. Se utiliza para mostrar los datos al usuario.
• System.err. Objeto para salida estándar de error del sistema, que
normalmente es el monitor. Se utiliza para mostrar mensajes de error al
usuario.
La apertura de un archivo supone establecer la conexión del programa con
el dispositivo que contiene al archivo; por el canal que comunica el archivo
con el programa van a fluir las secuencias de datos, de ahí el concepto de
flujo. Abrir un archivo supone crear un objeto y asociarlo con un flujo. Así,
un archivo en Java es un flujo externo, una secuencia de bytes
almacenados en un dispositivo externo (normalmente en un disco). Si el
archivo se abre para salida, es un flujo de archivo de salida. Si el archivo se
abre para entrada, es un flujo de archivo para entrada. Los programas leen
o escriben en el flujo, que puede estar conectado a un dispositivo o a otro.
El paquete java.io agrupa al conjunto de clases necesarias para el manejo
de entrada y salida; siempre que se vayan a procesar archivos, se tienen
que utilizar clases de este paquete, por lo que se debe de importar: import
java.io.*; para todas las clases.
Debido a que todo el proceso de entrada y salida en Java se hace a través
de flujos (streams). En los programas hay que crear objetos streams y en
muchas ocasiones hacer uso de los objetos in, out que se encuentran en la
clase System.
System.in para entrada por teclado.
System.out para salida por pantalla.
Los flujos de datos, de caracteres y de bytes se clasifican en flujos de
entrada (InputStream) y en flujos de salida (OutputStream). Las dos
clases relacionadas con flujos que se utilizan son InputStream y
OutputStream, derivadas directamente de la clase Object. Ambas son
clases abstractas que declaran métodos que deben redefinirse en sus
subclases. Además, InputStream es la superclase de todas las clases
definidas para flujos de entrada, y OutputStream es la superclase de todas
las clases de flujos de salida.

Flujos de entrada Flujos de salida


InputStream OutputStream
FileInputStream FileOutputStream
ByteArrayInputStream ByteArrayOutputStream
FilterInputStream FilterOutputStream
Clases FileInputStream y FileOutputStream.
Dos de las clases relacionadas con flujos que más se utilizan son
FileInputStream y FileOutputStream, las cuales crean flujos de bytes
asociados a archivos. Para abrir un archivo, simplemente hay que crear un
objeto de una de estas dos clases, especificando el nombre del archivo
como argumento del constructor.
La clase FileInputStream se utiliza para leer bytes desde un archivo.
Proporciona operaciones básicas para leer un byte o una secuencia de
bytes. Los constructores de la clase permiten crear objetos asociados a un
archivo. Si al crear un flujo de entrada, el archivo indicado no existe, se
lanza una excepción del tipo FileNotFoundException. A continuación se
muestran algunos de los métodos más importantes de esta clase, todos
son public, es importante tener en cuenta la excepción que puede lanzar
para que al momento que se manden llamar se considere el tratamiento a
la excepción.
Clases derivadas o subclases.
Descripción.
FileInputStream (String nombreArchivo) throws
FileNotFoundException;
Crea un objeto inicializado con el nombre nombreArchivo que se pasa como
argumento.
FileInputStream (File nombreArchivo) throws FileNotFoundException;
Crea un objeto inicializado con el objeto nombreArchivo que se pasa como
argumento.
int read( ) throws IOException;
Lee un byte del flujo asociado. Devuelve -1 si encuentra la marca de fin de
archivo.
int read(byte[ ] arreglo) throws IOException;
Lee una secuencia de bytes del flujo y los almacena en el arreglo. Devuelve
-1 si encuentra la marca de fin de archivo, o bien el total de bytes leído.

int read(byte[ ] arreglo, int orig, int longit) throws IOException;


Lee una secuencia de bytes del flujo y los almacena en el arreglo, desde la
posición orig y un máximo de longit bytes. Devuelve -1 si encuentra la
marca de fin de archivo, o bien el total de bytes leído.
Con la clase FileOutputStream se pueden escribir bytes en un flujo de
salida asociado a un archivo. Los constructores inicializan objetos con el
nombre del archivo, o bien con el archivo como objeto File. En el caso del
flujo de salida, si no se puede crear el archivo se genera una excepción
del tipo FileNotFoundException. Cuando se abre un archivo de salida, se
destruye cualquier archivo que existiera antes con ese mismo nombre. A
continuación se muestran los constructores y métodos más importantes
(todos tienen visibilidad public).
Clases derivadas o subclases.
Descripción.
FileOutputStream (String nombreArchivo) throws FileNotFoundException;
Crea un objeto inicializado con el nombre nombreArchivo que se pasa como
argumento.
FileOutputStream (String nombreArchivo, boolean añadir) throws
FileNotFoundException;
Crea un objeto inicializado con el nombre nombreArchivo que se pasa como
argumento. En el caso de que añadir = true permite añadir bytes a un archivo
existente.
FileOutputStream (File nombreArchivo) throws FileNotFoundException;
Crea un objeto inicializado con el objeto nombreArchivo que se pasa como
argumento.
int write(byte b) throws IOException;
Escribe el byte b en el flujo asociado.
int wite(byte[ ] arreglo) throws IOException;
Escribe el arreglo de bytes en el flujo.
int write(byte[ ] arreglo, int orig, int longit) throws IOException;
Escribe el arreglo de bytes en el flujo, desde la posición orig y un máximo de longit
bytes.
void flush( );
Limpia los buffers de salida.
Una vez que se crea un objeto stream se pueden hacer operaciones sobre
él (leer y escribir datos), no hay que hacer la operación de apertura de
forma separada; el constructor se encarga de abrir el flujo. Si no es posible
crear el objeto o el archivo de lectura no existe, el constructor lanza una
excepción.
Cuando se ha terminado de trabajar con un archivo, hay que cerrarlo
llamando al método close(), que está definido en las clases
FileInputStream y FileOutputStream, cualquier intento posterior de lectura
o escritura producirá una IOException.
void close( ) throws IOException
Clases ByteArrayInputStream y ByteArrayOutputStream.
Las clases ByteArrayInputStream y ByteArrayOutputStream permiten
asociar un flujo con un arreglo de bytes, en vez de un archivo. Se maneja
que un objeto stream de entrada lee del arreglo, y que un objeto stream de
salida escribe en un arreglo interno que crece dinámicamente. Los
métodos más importantes de esta clase son:

Clases derivadas o subclases.


Descripción.
ByteArrayInputStream(byte buffer[ ]);
Crea un objeto asociando el flujo con el arreglo que se pasa como
argumento.
int read( );
Lee un byte del flujo asociado.
int read(byte[ ] arreglo, int orig, int longit);
Lee una secuencia de bytes del flujo y se almacena en el arreglo, orig es
la posición a partir de la cual se almacena y longit es el máximo de bytes
a leer.
Clases FilterInputStream y FilterOutputStream.
Los flujos filtrados son simplemente envoltorios alrededor de flujos de
entrada o salida que proporcionan de forma transparente cierto grado
extendido de funcionalidad. A estos flujos acceden comúnmente métodos
que esperan un flujo genérico, que es una superclase de los flujos filtrados.
Extensiones típicas son los búferes, traducciones de caracteres y
traducciones de datos primitivos (int, long, double, etc.). Los flujos
filtrados leen de un flujo que previamente ha tenido que ser escrito por otro
flujo filtrado de salida. Los flujos de bytes filtrados son FilterInputStream
(flujo de entrada con filtro) y FilterOutputStream (flujo de salida con filtro).
Sus constructores son:
FilterInputStream(OutputStream flujoSalida);
FilterOutputStream(InputStream flujoEntrada);

Los métodos proporcionados en es tas clases son idénticos a los de


InputStream y OutputStream.
Clase PushbackReader.
La clase PushbackReader (derivada de FilterReader que a su vez se
deriva de Reader) se aplica para flujos de caracteres, y es útil cuando en
un flujo se necesita mirar el siguiente carácter en la entrada con el fin de
determinar qué hacer a continuación: para eso, se lee el carácter y
después se devuelve a la entrada para que pueda ser leído por el código
que tenga que ejecutarse a continuación. Algunos de los métodos que
proporciona la clase PushbackReader son:

Método Descripción
close Cierra el flujo.
read Lee un único carácter, o bien un arreglo de caracteres.
unread Devuelve a la entrada un único carácter, o bien todo o parte de
un arreglo de caracteres.
ready Devuelve true si se puede leer del flujo porque hay caracteres
disponibles; de lo contrario devuelve false.
Los siguientes ejemplos utilizan la clase PushbackReader para leer un
carácter y para limpiar el flujo de caracteres. Añadiendo estos métodos a
la clase LeerDato podremos leer caracteres y limpiar el buffer de entrada
después de haber leído un carácter. Los métodos definen un miembro
flujoE de la clase PushbackReader que se relaciona con el flujo abierto
desde el origen de los caracteres. Como en este caso el origen real de los
datos va ser el teclado (dispositivo vinculado con System.in que
proporciona bytes), la clase InputStreamReader establece un puente
para pasar flujos de bytes a flujos de caracteres.
/* Método para leer un carácter */
public static char caracter()
{
PushbackReader flujoE = new PushbackReader(new InputStreamReader(System.in));
int caracter = 0;
try {
caracter = flujoE.read();
}
catch (IOException e) {
caracter = 0;
}
return (char)caracter;
}

/* Método para limpiar el teclado */


public static void limpiar()
{
PushbackReader flujoE = new PushbackReader(new InputStreamReader(System.in));
int caracter = 0;
try {
while (flujoE.ready()) flujoE.read(); // limpia el flujo de entrada
}
catch (IOException e) {
System.err.println("Error: "+e.getMessage());
}
}
Flujos de datos.
Habrá ocasiones en que se desee escribir en un archivo datos de tipos
primitivos (boolean, byte, double, float, long, int y short) para
posteriormente recuperarlos como tales. Para estos casos, el paquete
java.io proporciona las clases DataInputStream y DataOutputStream, las
cuales permiten leer y escribir, respectivamente, datos de cualquier tipo
primitivo. Sin embargo, estas clases no pueden utilizarse con los
dispositivos ASCII de Entrada/Salida estándar. Un flujo DataInputStream
sólo puede leer datos almacenados en un archivo a través de flujo
DataOutputStream.
Los flujos de estas clases actúan como filtros; esto es, los datos obtenidos
del origen o enviados al destino son transformados mediante alguna
operación y convertidos a un formato portable (formato UTF-8 <Unicode
modificado>) cuando son almacenados, y a la inversa cuando son
recuperados. El procedimiento para utilizar un filtro es básicamente el
siguiente:
• Se crea un flujo asociado con un origen o destino de los datos.
• Se asocia un filtro con el flujo anterior.
• Finalmente, el programa leerá datos a través de ese filtro.
Clases DataOutputStream y DataInputStream.
Un flujo de la clase DataOutputStream, derivada indirectamente de
OutputStream, permite a una aplicación escribir en un flujo de salida
subordinado, datos de cualquier tipo primitivo. El siguiente ejemplo muestra
el código que define un filtro que permitirá escribir datos de tipo primitivo en
un archivo llamado datos.dat.
FileOutputStream fos = new FileOutputStream(“datos.dat”);
DataOutputStream dos = new DataOutputStream(fos);

Un programa que quiera almacenar datos en el archivo datos.dat, escribirá


tales datos en el filtro dos, que a su vez está conectado al flujo fos abierto
hacia ese archivo. Gráficamente podemos representarlo de la siguiente
manera.

Programa dos fos Archivo

Al terminar de escribir en el flujo, deberán cerrarse el flujo y el filtro, en el


orden inverso en el que fueron abiertos, utilizando el método close().
dos.close();
fos.close();
Todos los métodos proporcionados por esta clase están definidos en la
interfaz DataOutput implementada por la misma. Los métodos más
utilizados se resumen en la siguiente tabla:
Método Descripción
writeBoolean(boolean arg) Escribe un valor de tipo boolean.
writeByte(byte arg) Escribe un valor de tipo byte.
writeBytes(String arg) Escribe un String como una secuencia de bytes.
writeChar(char arg) Escribe un valor de tipo char.
writeChars(String arg) Escribe un String como una secuencia de
caracteres.
writeShort(short arg) Escribe un valor de tipo short.
writeInt(int arg) Escribe un valor de tipo int.
writeLong(long arg) Escribe un valor de tipo long.
writeFloat(float arg) Escribe un valor de tipo float.
writeDouble(double arg) Escribe un valor de tipo double.
writeUFT(String arg) Escribe una cadena de caracteres en formato UTF-8;
los dos primeros bytes especifican el número de
bytes de datos escritos a continuación.
Un flujo de la clase DataInputStream, derivada indirectamente de
InputStream, permite a una aplicación leer de un flujo de entrada
subordinado, datos de cualquier tipo primitivo escritos por un flujo de la
clase DataOutputStream. El siguiente ejemplo muestra el código que
define un filtro que permitirá escribir datos de tipo primitivo en un archivo
llamado datos.dat.
FileInputStream fis = new FileInputStream(“datos.dat”);
DataInputStream dis = new DataInputStream(fis);

Un programa que quiera leer datos del archivo datos.dat, leerá tales datos
del filtro dis, que a su vez está conectado al flujo fis abierto desde ese
archivo. Gráficamente podemos representarlo de la siguiente manera.

Programa dis fis Archivo

Al terminar de leer del flujo, deberán cerrarse el flujo y el filtro, en el orden


inverso en el que fueron abiertos, utilizando el método close().
dis.close();
fis.close();
Todos los métodos proporcionados por esta clase están definidos en la
interfaz DataInput implementada por la misma. Los métodos más utilizados
se resumen en la siguiente tabla:

Método Descripción
readBoolean() Devuelve un valor de tipo boolean.
readByte() Devuelve un valor de tipo byte.
readChar() Devuelve un valor de tipo char.
readShort() Devuelve un valor de tipo short.
readInt() Devuelve un valor de tipo int.
readLong() Devuelve un valor de tipo long.
readFloat() Devuelve un valor de tipo float.
readDouble() Devuelve un valor de tipo double.
readUFT() Devuelve una cadena de caracteres en formato UTF-8;
los dos primeros bytes especifican el número de bytes
de datos que serán leídos a continuación.
El ejemplo muestra los métodos que permiten escribir y leer de un
archivo utilizando estas clases.
public static void crearArchivo(File archivo) throws IOException
{
DataOutputStream dos = null; // salida de datos hacia el archivo
char resp;
try {
// crear un flujo hacia un archivo para escribir datos de tipo primitivo usando un buffer
dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(archivo)));
// leer datos y escribirlos en el archivo
do {
leerDatos(); // Método creado previamente para leer los datos que se graban en el archivo
dos.writeUTF(nombre);
dos.writeUTF(apellidoPat);
dos.writeUTF(apellidoMat);
dos.writeUTF(email);
dos.writeInt(edad);
dos.writeChar(sexo);
System.out.println(" desea escribir otro registro? (s/n) ");
resp = leerCaracter(); // Método creado con PushbackReader para leer un carácter
limpiar(); // Método creado con PushbackReader para limpiar el buffer del teclado
} while (resp == 's');
}
finally {
if (dos != null) dos.close();
}
}
public static void leerArchivo(String nomArchivo) throws IOException
{
DataInputStream dis = null; // lectura de datos del archivo
File archivo = null;
try {
// crear un objeto File que identifique al archivo
archivo = new File(nomArchivo);
// verificar si el archivo existe
if (archivo.exists()) // si existe, abrir un flujo que permita leer datos del archivo
{
dis = new DataInputStream(new BufferedInputStream(new FileInputStream(archivo)));
// leer datos del archivo y asignarlos a las variables
do {
nombre = dis.readUTF();
apellidoPat = dis.readUTF();
apellidoMat = dis.readUTF();
email = dis.readUTF();
edad = dis.readInt();
sexo = dis.readChar();
mostrarDatos (); // Método creado previamente para mostrar los datos leídos del archivo
} while (true);
}
else
System.out.println("El archivo no existe");
}
finally {
if (dis != null) dis.close();
}
}
Clase PrintStream.
Esta clase deriva directamente de FilterOutputStream, por lo que tiene que
estar asociada a un flujo de bytes para salida. Los métodos de esta clase
están sobrecargados para poder escribir desde cadenas hasta cualquiera
de los datos primitivos. Define métodos para que después de escribir un
dato se añada la marca de fin de línea.
Esta clase tiene dos constructores, en el primero, se pasa como argumento
el objeto flujo de bytes al que se asocia. En el segundo, hay un segundo
argumento (opcional) de tipo boolean para que cada vez que se escriba la
marca de fin de línea se vacíe todo el flujo.
public PrintStream(OutputStream destino)
Crea un objeto asociado con cualquier objeto de salida pasado como
argumento.
public PrintStream(OutputStream destino, boolean flag)
Crea un objeto asociado con objeto de salida pasado como argumento y si
el segundo argumento es true se produce un vaciado automático al escribir
el fin de línea.

Los métodos más importantes son:


Método Descripción
flush() Limpia el flujo actual.
print(Object obj) Escribe la representación del objeto en el flujo.
print(String cad) Escribe la cadena en el flujo.
print(char c) Escribe el carácter c en el flujo.
print(byte n) Escribe el byte n en el flujo.
print(short n) Escribe el número n en el flujo.
print(int n) Escribe el número n en el flujo.
print(long n) Escribe el número n en el flujo.
print(float n) Escribe el número n en el flujo.
print(double n) Escribe el número n en el flujo.
println(Object obj) Escribe la representación del objeto en el flujo y la marca de fin de línea.
println(String cad) Escribe la cadena en el flujo y la marca de fin de línea.
println(char c) Escribe el carácter c en el flujo y la marca de fin de línea.
println(byte n) Escribe el byte n en el flujo y la marca de fin de línea.
println(short n) Escribe el número n en el flujo y la marca de fin de línea.
println(int n) Escribe el número n en el flujo y la marca de fin de línea.
println(long n) Escribe el número n en el flujo y la marca de fin de línea.
println(float n) Escribe el número n en el flujo y la marca de fin de línea.
println(double n) Escribe el número n en el flujo y la marca de fin de línea.
Clase File.
La clase File define métodos para conocer propiedades y características del
archivo o directorio, y también métodos para modificar alguna característica
del archivo. Los constructores de File permiten inicializar el objeto con el
nombre de un archivo y la ruta donde se encuentra. También, inicializar el
objeto con otro objeto File como ruta y el nombre del archivo.
public File(String nombreYruta)
Crea un objeto File con el nombre y ruta de acceso del archivo pasado
como argumento.
public File(String ruta, String nombre)
Crea un objeto File con la ruta de acceso y el nombre del archivo pasados
como argumentos separados.
public File(File ruta, String nombre)
Crea un objeto File con un primer argumento que a su vez es un objeto
File con la ruta de acceso y separado el nombre del archivo como segundo
argumento
Es conveniente crear objetos File con el archivo que se va a procesar, para
pasar el objeto al constructor del flujo en vez de pasar directamente el
nombre del archivo. Así se pueden hacer controles previos sobre el archivo.
Los métodos de la clase File se resumen en la siguiente tabla:
Métodos Descripción
String getName() Devuelve una cadena con el nombre del archivo especificado
por el objeto File.
String getParent() Devuelve el directorio padre.
String getPath() Devuelve la ruta relativa del archivo.
String getAbsolutePath() Devuelve la ruta absoluta del archivo.
boolean exists() Devuelve true si existe el archivo (o el directorio).
boolean canWrite() Devuelve true si se puede escribir en el archivo o directorio
especificado por el objeto File (si no es de sólo lectura).
boolean canRead() Devuelve true si se puede leer desde el archivo o directorio
especificado por el objeto File.
boolean isFile() Devuelve true si es un archivo válido.
boolean isDirectory() Devuelve true si de trata un directorio válido.
boolean isHidden() Devuelve true si se trata de un
long length() Devuelve el tamaño del archive. Si el objeto es un directorio
devuelve cero.
long lastModified() Devuelve la hora de la última modificación. El número
devuelto es una representación interna de la hora, minutos y
segundos de la última comparación, solo es útil para
establecer comparaciones con otros valores devueltos por el
mismo método.
Métodos Descripción
String[ ] list() Devuelve un arreglo de objetos String que almacena los
nombres del archivos y directorios con los que se ha
inicializado el objeto File.
boolean mkdir() Crea el directorio especificado por el objeto File.
boolean mkdirs() Crea el directorio especificado por el objeto File
incluyendo los directorios que no existan en la ruta
especificada.
boolean delete() Elimina el archivo o directorio (debe estar vacío)
especificado por el objeto File.
boolean deleteOnExit() Hace lo mismo que delete, pero cuando la máquina virtual
de Java termina.
createTempFile(File arg) Crea el archivo vacío especificado por los argumentos
pasados, en el directorio temporal del sistema.
boolean renameTo(File nuevo) Renombra el archivo especificado por el objeto File que
recibe este mensaje, con el nombre del objeto File pasado
como argumento.
boolean setReadOnly() Marca el archivo o directorio especificado por el objeto
File como de solo lectura.
String toString() Devuelve una cadena con la ruta especificada cuando se
creó el objeto File.
Seriación de objetos.
En un desarrollo orientado a objetos, se debe pensar en objetos, ya que los
datos no son tratados aisladamente, sino que más bien se corresponden
con los atributos de un objeto, por lo cual debemos escribir y leer objetos a
y desde un archivo. Así, la operación de enviar una serie de objetos a un
archivo en disco recibe el nombre de seriación, y la operación de leer o
recuperarlos del archivo para reconstruirlos en memoria recibe el nombre
de deseriación. Para realizar estas operaciones de forma automática, el
paquete java.io proporciona las clases ObjectOutputStream y
ObjectInputStream. Ambas clases dan lugar a flujos que procesan sus
datos; en este caso, se trata de convertir el estado de un objeto (los
atributos, excepto las variables estáticas), incluyendo la clase del objeto y el
prototipo de la misma, en una secuencia de bytes y viceversa. Por esta
razón los flujos ObjectOutputStream y ObjectInputStream deben ser
construidos sobre otros flujos que canalicen esos bytes a y desde el
archivo.
Para poder seriar los objetos de una clase, ésta debe de implementar la
interfaz Serializable. La cual es una interfaz vacía, sin ningún método; su
propósito es simplemente identificar clases cuyos objetos se pueden seriar.
El siguiente ejemplo define una clase cuyos objetos se pueden seriar:

import java.io.*;
public class NombreClase implements Serializable
{
// Cuerpo de la clase
}

Como la interfaz Serializable está vacía, no hay que escribir ningún método
extra en la clase.
a) Escribir objetos en un archivo.
Un flujo de la clase ObjectOutputStream permite enviar datos de tipos
primitivos y objetos hacia un flujo OutputStream o derivado;
concretamente, cuando se trate de almacenarlos en un archivo,
utilizaremos un flujo FileOutputStream. Posteriormente, esos objetos
podrán ser reconstruidos a través de un flujo ObjectInputStream.
Para escribir un objeto en un flujo ObjectOutputStream se utiliza el
método writeObject. Los objetos pueden incluir cadenas (Strings) y
arreglos, y el almacenamiento de los mismos puede combinarse con datos
de tipos primitivos, ya que esta clase implementa la interfaz DataOutput.
Este método lanzará la excepción NotSerializableException si se intenta
escribir un objeto de una clase que no implementa la interfaz Serializable.
b) Leer objetos desde un archivo.
Un flujo de la clase ObjectInputStream permite recuperar datos de tipos
primitivos y objetos desde un flujo InputStream o derivado; concretamente,
cuando se trate de flujos de datos primitivos y objetos almacenados en un
archivo, se utiliza un flujo FileInputStream. La clase ObjectInputStream
implementa la interfaz DataInput para permitir leer también los tipos
primitivos.
Para leer un objeto desde un flujo ObjectInputStream se utiliza el método
readObject. Si se almacenaron objetos y datos de tipos primitivos, deben
ser recuperados en el mismo orden en que se guardaron.
c) Serialización y deserialización de objetos que referencían a otros
objetos.
Cuando en un archivo se escribe un objeto que hace referencia a otros
objetos, entonces todos los objetos accesibles desde el primer objeto deben
ser escritos en el mismo proceso para mantener así la relación existente
entre todos ellos. Este proceso es llevado a cabo automáticamente por el
método writeObject, que escribe el objeto especificado, recorriendo sus
referencias a otros objetos recursivamente, escribiendo así todos ellos.
Del mismo modo, si el objeto recuperado del flujo por el método readObject
hace referencia a otros objetos, readObject recorrerá sus referencias a
otros objetos recursivamente, para recuperarlos todos, manteniendo la
relación que existía entre ellos cuando fueron escritos. Debemos recordar
que para poder serializar un objeto, la clase debe implementar la interfaz
Serializable, al igual que las clases referenciadas por la primera.
El siguiente ejemplo muestra un programa que aplica la serialización y
deserialización de objetos.
import java.io.*;
public class ArchivoOb implements Serializable
{
//…
public static void crearArchivo(File archivo) throws IOException
{
ObjectOutputStream oos = null; // salida de datos hacia el archivo
char resp;
try {
// crea un flujo a un archivo que permita escribir datos de tipo primitivo usando un buffer
oos = new ObjectOutputStream(new FileOutputStream(archivo));
// leer datos y escribirlos en el archivo
leerDatos(); //Método creado previamente para leer los datos que se graban en el archivo
oos.writeObject(new ArchivoOb(nombre,apellidoPat,apellidoMat,email,edad,sexo));
oos.flush();
oos.close();
}
finally {
if (oos != null) oos.close();
}
}
public static void leerArchivo(String nomArchivo) throws IOException
{
ObjectInputStream ois = null; // lectura de datos del archivo
File archivo = null;
try {
// crear un objeto File que identifique al archivo
archivo = new File(nomArchivo);
ArchivoOb datArchivo;
// verificar si el archivo existe
if (archivo.exists())
{
// si existe, abrir un flujo que permita leer datos del archivo
ois = new ObjectInputStream(new FileInputStream(archivo));
// leer datos del archivo y asignarlos a las variables
datArchivo = (ArchivoOb) ois.readObject();
ArchivoOb.mostrarDatos();
ois.close();
}
else
System.out.println("El archivo no existe");
}
catch(EOFException e) {
System.out.println("Fin del archivo");
}
catch(ClassNotFoundException e) {
System.out.println("Error: "+e.getMessage());
}
}
Archivos secuénciales.
La forma en que esta organizado un archivo, define como se guardarán los
registros en el medio de almacenamiento, o también define la forma en que
se estructuran los datos en el archivo. En general se consideran tres
organizaciones fundamentales:
• Organización secuencial.
• Organización directa o aleatoria.
• Organización secuencial indexada.
Un archivo con organización secuencial es una sucesión de registros
almacenados consecutivamente en un medio de almacenamiento externo,
de tal modo que para acceder a un registro cualquiera, forzosamente debe
pasarse por los registros que le anteceden.
En un archivo secuencial los registros se añaden, esto es, un registro de
datos se almacena inmediatamente después del registro anterior. Las
operaciones básicas que se permiten en un archivo secuencial son: grabar
un registro, añadir un registro (al final del archivo) y consultar registros.
Java solo procesa los archivos como secuencias de bytes y no determina la
estructura del archivo. El programador es el que determina el tratamiento
del archivo, si va a ser secuencial o de acceso aleatorio. Primero se debe
especificar el concepto de registro según los datos que se van a almacenar,
para lo cual, Java contempla la estructura de registro. Los campos en que
se descompone cada registro, según como lo determine el programador, se
han de escribir uno a uno. Además, la operación de lectura del archivo
creado debe de hacerse de manera inversa, así, si por ejemplo el primer
campo es de tipo entero, al leer el método de lectura debe ser para un
entero. Una vez definidos los campos de cada registro se escribe la
aplicación en la que se crean los flujos inicializados con el nombre del
archivo y se piden los campos de cada registro para ser escritos por los
métodos el objeto flujo. Cuando se han terminado de escribir todos los
registros se cierra el flujo (close()).
La creación de un archivo secuencial se puede hacer con las clases:
FileOutputStream y DataOutputStream, además de la clase File para
definir el archivo. Un objeto DataOutputStream se inicializa con un previo
objeto de FileOutputStream que a su vez se ha inicializado con el objeto
File. Debe tenerse cuidado ya que los datos que tuviera un archivo externo
con el que se crea el objeto FileOutputStream se pierden, a menos que se
pase al constructor un segundo argumento con el valor true, para que en
ese caso se añadan al final los nuevos registros.
Así, la metodología para escribir datos en un archivo de acceso secuencial
es la siguiente:
• Definimos un flujo hacia el archivo en el que deseamos escribir datos.
• Leemos los datos del dispositivo de entrada o de otro archivo y los
escribimos en nuestro archivo. Este proceso se hace normalmente registro
a registro. Para lo cual utilizamos los métodos proporcionados por la
interfaz del flujo.
• Cerramos el flujo.
Del mismo modo, la metodología para leer datos de un archivo existente:
• Abrimos un flujo desde el archivo del cual deseamos leer los datos.
• Leemos los datos del archivo y los almacenamos en variables de nuestro
programa para trabajar con ellos. Este proceso se hace normalmente
registro a registro. Para lo cual utilizamos los métodos proporcionados por
la interfaz del flujo.
• Cerramos el flujo.
Los archivos de acceso secuencial también pueden actualizarse, añadiendo
nuevos registros (altas), modificando datos de registros existentes
(modificaciones) o borrando registros (bajas).
a) Añadir registros.
El proceso de dar de alta un determinado registro o tantos como se
requiera, puede hacerse al inicializar el flujo de la clase
FileOutputStream, pasando true como segundo argumento al constructor
(el primer argumento es el archivo). De esta forma, el nuevo registro que
se da de alta se añade al final del archivo. Así, para añadir registros en un
archivo cualquiera tenemos el siguiente ejemplo:
File archivo = new File(nombreArchivo);
dos = new DataOutputStream(new BufferedOutputStream(
new FileOutputStream(archivo, true)));
b) Eliminar registros.
Para dar de baja un registro del archivo secuencial se utiliza un archivo
auxiliar, también secuencial. Se lee el archivo original registro por registro y
cuando se observe un registro que se quiere eliminar, se decide si el
registro debe ser escrito en el archivo auxiliar, así, si el registro se va a
eliminar, se omite su escritura en el archivo auxiliar, pero si el registro no se
da de baja, entonces se escribe en el archivo auxiliar. Una vez que se
termina el proceso completo con todo el archivo, se tiene dos archivos, el
original y el auxiliar. El proceso de baja termina eliminando el archivo
original y cambiando el nombre del archivo auxiliar por el del original. Con la
llamada a los métodos de la clase File: delete() y renameTo(), para
eliminar el archivo original una vez procesado y cambiar de nombre el
archivo auxiliar, se termina el proceso de dar de baja.
c) Modificar registros.
Las actualizaciones de registros de un archivo secuencial se pueden hacer
siguiendo los mismos pasos que al eliminar un registro. Los registros del
archivo original se leen y se escriben en el archivo auxiliar hasta llegar al
registro que se va a modificar. Una vez que éste es leído, se cambian los
datos o campos deseados y se escribe en el archivo auxiliar. El archivo
original se continúa procesando hasta leer el último registro; se termina
borrando el archivo original y cambiando el nombre del auxiliar por el
nombre del original.
Archivos de acceso aleatorio.
Un archivo es de acceso aleatorio o directo cuando cualquier registro es
directamente accesible mediante un índice, que da la posición del registro
con respecto al origen del archivo. La principal característica del de los
archivos de acceso aleatorio, es la rapidez de acceso a un determinado
registro; conociendo el índice del registro se puede situar el puntero de
lectura/escritura del archivo, en la posición donde comienza el registro y a
partir de esa posición realizar la operación de lectura o escritura. Sin
embargo, el acceso a un registro cualquiera en el archivo secuencial,
significa leer todos los registros anteriores.
Las operaciones que se realizan con los archivos de acceso directo son las
usuales: creación, consulta, grabar un registro, borrar un registro y modificar
un registro.
Java solo procesa los archivos como secuencias de bytes y no determina la
estructura del archivo, ya que es el programador quien determina la forma
de acceso al archivo. Para el proceso de archivos aleatorios, es importante
establecer el tipo de datos de cada campo del registro lógico y el tamaño de
cada registro. En cuanto al tamaño, se establece tomando en cuanta la
máxima longitud de cada campo; particularmente, para los campos de tipo
String se debe prever el máximo número de caracteres, además, si se
escribe en formato UTP se añaden dos bytes más, en los cuales se guarda
la longitud de la cadena. Los campos de tipo primitivo tienen longitud fija:
char, dos bytes; int, cuatro bytes; double, ocho bytes; etc.
El paquete java.io contiene la clase RandomAccessFile que define los
métodos para facilitar el procesa,iento de archivos de acceso directo.
Además, un flujo de esta clase permite realizar tanto operaciones de lectura
como de escritura (L/E) sobre el archivo vinculado con el mismo. Esta clase
deriva directamente de Object, e implementa las interfaces DataInput y
DataOutput, al igual que las clases DataInputStream y
DataOutputStream, respectivamente. La clase tiene dos constructores con
dos argumentos, el primero es el archivo y el segundo una cadena con el
modo de abrir el flujo.
public RandomAccessFile(String nomArchivo, String modo) throws IOException
El objeto queda ligado al archivo que se pasa como cadena en el primer argumento. El
segundo argumento es el modo de apertura.
public RandomAccessFile(File archivo, String modo) throws IOException
El primer argumento es un objeto File que se creó con la ruta y nombre del archivo, el
segundo argumento es el modo de apertura.
En cuanto al modo de apertura, este puede ser de dos formas:
Modo Significado
“r” Modo de solo lectura. Sólo se permiten realizar operaciones de lectura. No se
puede modificar o escribir registros.
“rw” Modo lectura/escritura. Se pueden realizar operaciones de lectura (entrada) y de
escritura (salida) sobre el archivo.
Ambos constructores lanzan una excepción del tipo IOException si hay algún problema al
crear el flujo. Por ejemplo, si se abre para lectura y el archivo no existe. Por esa razón, es
común comprobar el atributo de existencia del archivo con el método exists() de la clase File
antes de empezar el proceso.
La clase RandomAccessFile implementa a través de las interfaces DataInput (entrada de
datos) y DataOutput (salida de datos) los métodos básicos de Entrada/Salida. Pero también
provee los métodos getFilePointer(), length(), setLength() y el método seek(), que permite
posicionar el puntero del archivo dentro de este.
En los archivos, cuando se hace mención del puntero del archivo se refiere a la posición (en
número de bytes) a partir de la que se va a realizar la siguiente operación de lectura o de
escritura. Así, el puntero del archivo es una especie de índice, el cual, una vez que se ha
llevado a cabo una operación de lectura o de escritura, queda situado justo después del último
byte leído o escrito.
Métodos de la clase DataOutput
Método Descripción
writeBoolean(boolean arg) Escribe un valor de tipo boolean.

writeByte(byte arg) Escribe un valor de tipo byte.


writeBytes(String arg) Escribe un String como una secuencia de bytes.
writeChar(char arg) Escribe un valor de tipo char.
writeChars(String arg) Escribe un String como una secuencia de
caracteres.
writeShort(short arg) Escribe un valor de tipo short.
writeInt(int arg) Escribe un valor de tipo int.
writeLong(long arg) Escribe un valor de tipo long.
writeFloat(float arg) Escribe un valor de tipo float.
writeDouble(double arg) Escribe un valor de tipo double.
writeUFT(String arg) Escribe una cadena de caracteres en formato UTF-8;
los dos primeros bytes especifican el número de
bytes de datos escritos a continuación.
Métodos de la clase DataInput
Método Descripción
readBoolean() Devuelve un valor de tipo boolean.
readByte() Devuelve un valor de tipo byte.
readChar() Devuelve un valor de tipo char.
readShort() Devuelve un valor de tipo short.
readInt() Devuelve un valor de tipo int.
readLong() Devuelve un valor de tipo long.
readFloat() Devuelve un valor de tipo float.
readDouble() Devuelve un valor de tipo double.
readUFT() Devuelve una cadena de caracteres en formato UTF-8; los dos
primeros bytes especifican el número de bytes de datos que
serán leídos a continuación.
El método getFilePointer devuelve la posición actual en bytes del puntero
del archivo. Devuelve un entero de tipo long que representa el número de
bytes desde el inicio del archivo hasta la posición actual. Así, el puntero
marca siempre la posición donde se iniciará la siguiente operación de
lectura o escritura en el archivo.
public long getFilePointer ( ) throws IOException

El método seek (buscar), se usa para establecer la posición actual del


puntero del archivo. El método desplaza el puntero del archivo n bytes (pos
posiciones) tomando como origen el del archivo (byte 0). Es el método más
utilizado debido a que coloca el puntero del archivo en una posición
determinada. No se permiten desplazamientos negativos. El
desplazamiento requerido puede ir más allá del final del archivo; esta acción
no cambia la longitud del archivo; la longitud del archivo solo cambiará si a
continuación se realiza una operación de escritura.
public void seek (long pos) throws IOException

Con el método length se obtiene el tamaño o longitud actual del archivo en


bytes.
public long length ( ) throws IOException
A continuación se presentan algunos ejemplos de métodos
para leer y grabar diversos tipos de datos en un archivo:

1. Grabar y leer un arreglos de bytes.


2. Grabar y leer una cadena de caracteres.
3. Grabar y leer un arreglo bidimensional.
/* Programa que graba un Arreglo de bytes en un archivo y posteriormente lo lee. */

import java.io.*;

class Archivos1 {

// Método para escribir el archivo

public static void escribeArchivo() {


FileOutputStream fos = null; // salida de datos hacia el archivo
byte[] arreglo = new byte[255];
int nbytes;
try {
System.out.println("Escriba el texto que desea almacenar en el archivo: ");
nbytes = System.in.read(arreglo); // leer texto escribirlo en el archivo
fos = new FileOutputStream("datos.txt",true);
fos.write(arreglo, 0, nbytes); }
catch (IOException e) {
System.err.println("Error: "+e.getMessage()); }
finally {
try {
if (fos != null) fos.close(); // cierra el archivo }
catch (IOException e) {
System.err.println("Error: "+e.getMessage());
}
}
}
// Método para leer el archivo
public static void leeArchivo() {
FileInputStream fis = null; // entrada de datos desde el archivo
byte[] arreglo = new byte[255];
int nbytes;
try {
fis = new FileInputStream("datos.txt");
nbytes = fis.read(arreglo, 0, arreglo.length);
String cad = new String(arreglo, 0, nbytes);
System.out.println(cad); }
catch (IOException e) {
System.err.println("Error: "+e.getMessage()); }
finally {
try {
if (fis != null) fis.close(); // cierra el archivo }
catch (IOException e) {
System.err.println("Error: "+e.getMessage()); } } }
} /* fin de la clase */

/* Programa principal */
import java.io.*;
class Archivos2 {
public static void main(String args[]) {
System.out.println("Programa que escribe y lee un arreglo de bytes.");
System.out.println();
Archivos1.escribeArchivo();
Archivos1.leeArchivo();
System.out.println();
} /* fin del main */
} /* fin de la clase */
/* Programa que graba una cadena de caracteres y posteriormente la lee. */

import java.io.*;
import javax.swing.*;

class ArchivosUno {
// Método para escribir el archivo
public void escribeArchivo(String nombreArchivo) {
DataOutputStream dos=null; // salida de datos hacia el archivo
String cadena = " ";
try {
cadena = JOptionPane.showInputDialog(null,"Escriba el texto que desea almacenar en el archivo: ");
dos=new DataOutputStream(new BufferedOutputStream(new FileOutputStream(nombreArchivo+".dat")));
dos.writeUTF(cadena);
}
catch (IOException e) {
System.err.println("Error: "+e.getMessage());
}
finally {
JOptionPane.showMessageDialog(null,"¡Datos guardados con exito en el archivo!");
try {
if (dos != null) dos.close(); // cierra el archivo
}
catch (IOException e) {
System.err.println("Error: "+e.getMessage());
}
}
}
// Método para leer el archivo

public void leeArchivo(String nombreArchivo) {


DataInputStream dis=null; // entrada de datos desde el archivo
File archivo=null;
String cadena =" ";
try {
dis=new DataInputStream (new BufferedInputStream (new FileInputStream(nombreArchivo+".dat")));
cadena = dis.readUTF(); }
catch (IOException e) {
System.err.println("Error: "+e.getMessage());
}
finally {
JOptionPane.showMessageDialog(null,"Datos leidos con exito del archivo:\n\r"+cadena);
try {
if (dis != null) dis.close(); // cierra el archivo
}
catch (IOException e) {
System.err.println("Error: "+e.getMessage());
}
}
}
} /* fin de la clase */
import java.io.*;

public class MatricesArchivo {

/* Método para grabar en un archivo una matriz de orden m x n o n x n


public void grabarArchivoM(File archivo, double matriz[][]) throws IOException {
DataOutputStream dos = null; // salida de datos hacia el archivo
int i, j, m, n;

m = matriz.length;
n = matriz[0].length;

try {
// crear un flujo hacia un archivo que permita escribir datos de tipo primitivo usando un buffer
dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(archivo)));

// escribir los datos en el archivo


dos.writeInt(m);
dos.writeInt(n);

for (i=0; i<matriz.length; i++) {


for (j=0; j<matriz[i].length; j++){
dos.writeDouble(matriz[i][j]);
}
}
}
finally {
if (dos != null) dos.close();
}
}
/* Método para leer de un archivo una matriz de orden m x n o n x n

public double[][] leerArchivoM(String nomArchivo) throws IOException {


DataInputStream dis = null; // lectura de datos del archivo
File archivo = null;
int i = 0, j = 0, m = 0, n = 0;
try {
archivo = new File(nomArchivo); // crear un objeto File que identifique al archivo
if (archivo.exists()) { // verificar si el archivo existe
// si existe, abrir un flujo que permita leer datos del archivo
dis = new DataInputStream(new BufferedInputStream(new FileInputStream(archivo)));
// leer datos del archivo y asignarlos al arreglo
m = dis.readInt();
n = dis.readInt();
matriz = new double [m][n];
i=0;
do {
j=0;
do {
matriz[i][j] = dis.readDouble();
j++;
} while (j<n);
i++;
} while ((i<m) && (true)); }
else
System.out.println("El archivo no existe"); }
finally {
if (dis != null) dis.close(); }
return (matriz); } // Fin del Método
} // Fin de la clase
/* Programa principal, solo muestra las opciones de grabar y leer archivo */

import java.io.*;

class MatricesOp {
public static void main(String args[]) {

// Declaración de variables
File archivo = null;
archivo = new File ("Matrices.dat");
MatricesArchivo archivoM = new MatricesArchivo();

/* Aquí se coloca la declaración de matrices y los métodos para leer y hacer operaciones con las matrices */

// Llamar desde el programa principal al método para grabar una matriz en un archivo
try{
archivoM.grabarArchivoM(archivo, matriz); }
catch (IOException e) {
System.out.println("Error: "+e.getMessage()); }

// Llamar desde el programa principal al método para leer una matriz de un archivo
try{
matriz = archivoM.leerArchivoM("Matrices.dat”); }
catch (IOException e) {
System.out.println("Error: "+e.getMessage()); }

// Aquí podemos imprimir la matriz leída del archivo

} /* fin del main */


} /* fin de la clase */
UNIVERSIDAD AUTONOMA DE SINALOA
FACULTAD DE INFORMÁTICA DE MAZATLAN

PROGRAMACIÓN I
Applets
TITULAR DE LA MATERIA:
DR. JOSÉ NICOLÁS ZARAGOZA GONZÁLEZ
APPLETS.
Los programas en Java se dividen en dos tipos o categorías: aplicaciones y
applets. Las aplicaciones en Java son similares a un programa hecho en
C o C++, pero requieren de la Máquina Virtual de Java para ser ejecutados.
Las aplicaciones se usan para resolver diversos problemas y pueden
agruparse para formar sistemas, como inventarios, nómina, control escolar,
etcétera.
Un applet, es un programa diseñado para ser transmitido por Internet y
ejecutado en un navegador Web compatible con Java. Los applets tienen
algunas limitaciones ya que necesitan de ciertas condiciones de seguridad
para evitar daños en el sistema en el que está funcionando el navegador.
Algunas limitaciones son:
* Los applets no pueden leer o escribir en el sistema de archivos de la
computadora ya que pueden producir daños en los archivos o propagar
virus.
* Los applets no pueden establecer conexiones entre la computadora de un
usuario y otra computadora, excepto el servidor donde estén almacenados
los applets.
* Los applets no pueden ejecutar programas de la computadora donde está
el navegador, ya que pueden originar daños al sistema.
Así, un applet es una pequeña aplicación a la que se accede en un
navegador de Internet, se transmiten a través de la red, se instalan
automáticamente y se ejecutan como parte de un documento Web. Cuando
un applet llega a un cliente tiene acceso limitado a los recursos, por lo que
puede crear una interfaz de usuario multimedia y ejecutar cálculos
complejos sin ningún riesgo de virus o de violación de la integridad de los
datos.
Los applets se diferencian de las aplicaciones en algunas áreas clave ya
que no se estructuran de la misma forma que las aplicaciones. A
continuación presentamos un ejemplo sencillo de un applet.

import java.awt.*;
import java.applet.Applet;
public class Applet001 extends Applet
{
public void paint (Graphics g)
{
g.drawString ("Hola... Este es mi primer Applet en JAVA", 50, 100);
}
}
Este applet comienza con dos sentencias import. La primera importa las
clases del conjunto de herramientas de ventana abstracta (Abstract Window
Toolkit, AWT). Los applets interactúan con el usuario a través del AWT, no a
través de las clases de Entrada/Salida basadas en la consola o teclado. El
AWT permite desarrollar interfaces gráficas, basadas en el sistema de
ventanas. El AWT es bastante amplio y sofisticado y cuenta con múltiples
métodos y clases que permiten crear y manejar ventanas. Sin embargo,
solo se verán algunas de las técnicas necesarias para utilizar eficazmente
el AWT cuando se crean applets o aplicaciones.
La segunda sentencia import importa el paquete applet, el cual contiene la
clase Applet. Cada applet que se cree, debe ser una subclase de Applet.
La siguiente línea del programa declara la clase Applet001. Esta clase se
debe declarar como public, ya que se accederá a la misma desde código
externo al programa.
Dentro de la clase Applet001, se declara el método paint(). Este método
está definido por AWT y debe ser sobrescrito por el applet. Se llama al
método paint() cada vez que el applet debe mostrar su salida. Esto puede
ser por varias razones, por ejemplo, si la ventana en la se está ejecutando
el applet es tapada por otra ventana y después pasa otra vez a primer
término, o bien si se minimiza la ventana del applet y después se restaura.
También se llama al método paint() cuando comienza la ejecución del
applet, este método tiene un parámetro del tipo Graphics. Este parámetro
contiene el contexto gráfico que define el entorno gráfico en el cual se
ejecuta el applet. Este contexto se utiliza cuando se presenta la salida del
applet.
Dentro de paint() se llama al método drawString(), que es un miembro de
la clase Graphics. Este método es similar a System.out.print() que se
utiliza en modo texto, pero imprime una cadena en entorno gráfico a partir
de la posición X, Y especificada. Tiene la siguiente forma general:
void drawString(String mensaje, int x, int y)
Donde mensaje es la cadena que se imprimirá a partir de las coordenadas
x, y. En una ventana de Java, la esquina superior izquierda corresponde a
la posición 0, 0. En el ejemplo, la llamada al método drawString() en el
applet da lugar a que se imprima el mensaje "Hola... Este es mi primer
Applet en JAVA" en la posición 50, 100 de la ventana.
A diferencia de los programas Java, los applets no comienzan ejecutando el
método main() ya que la gran mayoría de los applets no tienen dicho
método. La ejecución de un applet comienza cuando se pasa el nombre de
su clase a un visualizador de applets o a un navegador web.
Después de introducir el código fuente de applet, este se compila de la
misma forma que se han compilado los programas, sin embargo su
ejecución es un proceso distinto. Existen varias formas de ejecución de un
applet:
• Ejecutar el applet dentro de un navegador Web compatible con Java,
como Internet Explorer o Netscape Navigator (recomendable).
• Utilizar un visualizador de applets como appletviewer, que es una
herramienta del equipo de desarrollo Java (JDK). Un visualizador ejecuta el
applet en una ventana. En general, esta es la forma más rápida y sencilla
de probar el applet.
• Algunos entornos de desarrollo, como el jGRASP, cuentan con un
visualizador de applets el cual permite ejecutar applets directamente.
A continuación se describe cada uno de estos métodos.
Para ejecutar un applet en un navegador Web, es necesario escribir un
pequeño archivo de texto HTML que contiene la etiqueta APPLET
apropiada. A continuación se muestra el archivo HTML, el cual llamaremos
Runapp.HTML y que ejecuta el applet Applet001:
<applet code="Applet001" width=300 height=200>
</applet>
Las sentencias width y height especifican las dimensiones de área de la
pantalla utilizada por el applet. Después de crear este archivo, se ejecuta el
navegador y entonces se carga este archivo. Como resultado se ejecutará
Applet001.
Para ejecutar Applet001 con un visualizador de applets, se ejecuta también
el archivo de texto con la etiqueta APPLET y que en este caso llamamos
Runapp.HTML. Entonces, utilizamos la siguiente línea de comando para
ejecutar Applet001:
C:\>j2sdk1.4.0\bin\appletviewer Runapp.html
Otro método para realizar pruebas rápidamente, consiste en incluir un
comentario en la cabecera del archivo fuente de Java que contiene la
etiqueta APPLET. De esta forma, el código está documentado con un
prototipo de las sentencias HTML necesarias, y se puede probar el applet
compilado, iniciando simplemente el visualizador de applets con el archivo
del código fuente Java.
import java.awt.*;
import java.applet.Applet;
/*
<applet code="Applet001" width=300 height=200>
</applet>
*/
public class Applet001 extends Applet
{
public void paint (Graphics g)
{
g.drawString ("Hola... Este es mi primer Applet en JAVA", 50, 100);
}
}
De esta manera, se pueden desarrollar rápidamente applets siguiendo
estos tres pasos:

1. Editar el archivo fuente Java.


2. Compilar el programa.
3. Ejecutar el visualizador de applets, especificando el nombre del
archivo fuente del applet. El visualizador encontrará la etiqueta APPLET
en el comentario y ejecutará el applet.

Finalmente, se pueden ejecutar applets directamente a través del editor


de un entorno de desarrollo, el jGRASP.
Al usar jGRASP, se captura, edita y graba el applet sin necesidad de
modificar la configuración. Se compila para detectar errores y
posteriormente, se ejecuta directamente a través de la opción Build del
menú, seleccionando Run as Applet. O haciendo clic directamente en
el icono correspondiente en el menú de iconos.
La clase Applet.
La clase Applet proporciona lo necesario para la ejecución de un applet,
desde el arranque hasta la finalización. También proporciona métodos que
cargan y visualizan imágenes, métodos que cargan y posibilitan la
reproducción de archivos de audio. Applet extiende además, clases que
proporcionan la base para desarrollar interfaces gráficas basadas en
ventanas de Java. Los fundamentos de la clase Applet son:
• Todos los applets son subclases de la clase Applet. Cualquier applet debe
importar los paquetes java.applet.
• Los applets también tiene que importar java.awt. Como todos los applets
se ejecutan en una ventana, es necesario incluir un soporte para esa
ventana.
• Los applets son ejecutados por un navegador de Internet o por un visor de
applets.
• Los applets no necesitan un método main().
• Las Entradas y Salidas (E/S) del usuario no necesitan las clases de flujo
de E/S Java. En su lugar, se utiliza la interfaz que proporciona el AWT.
• Una vez que se ha compilado un applet, se incluye en un archivo HTML,
utilizando la etiqueta APPLET. El applet se ejecutará en un navegador
compatible con Java cuando este encuentre la etiqueta APPLET.
Métodos definidos por Applet.

Método Descripción
void destroy( ) Método llamado por el navegador justo antes de que
termine el applet. El applet debe sobrescribir este método
si necesita liberar algún recurso antes de finalizar.
AccesibleContext getAccesibleContext( ) Devuelve el contexto de accesibilidad del objeto.
AppletContext getAppletContext( ) Devuelve el contexto asociado al applet.
String getAppletinfo( ) Devuelve una cadena que describe al applet.
AudioClip getAudioClip(URL url) Devuelve un objeto AudioClip que encapsula el archivo
de audio encontrado en la dirección especificada por url.
AudioClip getAudioClip(URL url, String Devuelve un objeto AudioClip que encapsula el archivo
clipName) de audio encontrado en la dirección especificada por url y
que tiene el nombre especificado por clipName.
URL getCodeBase( ) Devuelve el URL asociado con el applet que llama al
método.
URL getDocumentBase( ) Devuelve el URL del documento HTML que invoca al
applet.
Image getImage(URL url) Devuelve un objeto Image que encapsula la imagen
encontrada en la dirección especificada por url.
Image getImage(URL url, String imageName) Devuelve un objeto Image que encapsula la imagen
encontrada en la dirección especificada por url y que tiene
el nombre especificado por imageName.
Método Descripción
Locale getLocale( ) Devuelve un objeto Locale que se utiliza por varias clases
y métodos que pueden trabajar con ese tipo de objetos.

String getParameter(String paramName) Devuelve el parámetro asociado con paramName.


Devuelve null si no se encuentra el parámetro
especificado.
String[ ][ ] getParameterInfo( ) Devuelve una matriz String que describe los parámetros
reconocidos por el applet. Cada entrada de la tabla consta
de tres cadenas que contienen el nombre del parámetro,
una descripción de su tipo y/o rango, y una explicación de
su propósito.
void init( ) Este método se ejecuta cuando un applet comienza a
ejecutarse. Es el primer método que se ejecuta en un
applet.
boolean isActive( ) Devuelve true si ha comenzado el applet. Devuelve false
si se ha parado o detenido el applet.
static final AudioClip new AudioClip(URL url) Devuelve un objeto AudioClip que encapsula el archivo
de audio encontrado en la dirección especificada por url.
Este método es similar a getAudioClip( ) excepto en que
éste es estático y se puede ejecutar sin la necesidad de un
objeto Applet.
void play(URL url) Si encuentra un archive de sonido en la dirección
especificada por url, lo reproduce.
void play(URL url, String clipName) Si encuentra un archivo de sonido en la dirección
especificada por url con el nombre especificado por
clipName, lo reproduce.
Método Descripción

void resize(Dimension dim) Cambia el tamaño del applet en función de las dimensiones
especificadas por dim. Dimension es una clase de java.awt
que contiene dos campos enteros: width y height.
void resize(int width, int height) Cambia el tamaño del applet en función de las dimensiones
especificadas por width y height.
final void setStub(AppletStub stubObj) Hace que stubObj sea el stub (resguardo) del applet. Este
método lo utiliza el intérprete de Java y normalmente no lo
utiliza el applet. Un stub es una pequeña parte de código que
proporciona el enlace entre el applet y el navegador.
void showStatus(String str) Muestra la cadena str en la ventana de estado del navegador o
del visor de applets. Si el navegador no dispone de una ventana
de estado, entonces no se realiza ninguna acción.
void start( ) El navegador llama a este método cuando debe comenzar (o
continuar) la ejecución de un applet. Cuando los applets
comienzan por primera vez, se ejecuta automáticamente
después de init( ).
void stop( ) El navegador llama a este método para parar o detener la
ejecución del applet. Una vez detenido, un applet puede volver
a ejecutarse cuando el navegador llama al método start( ).
Arquitectura de un applet.
Un applet es un programa basado en ventanas. Su arquitectura es
diferente de la de los programas basados en consola, también llamados
aplicaciones independientes, programas en modo plano o modo texto, o
simplemente aplicaciones.
En primer lugar, los applets son conducidos u orientados a eventos. El
applet espera hasta que ocurra un evento. El AWT notifica el evento al
applet llamando a un gestor de eventos para que lo trate. Después, el
applet debe ejecutar la acción que desee el programador y devolver el
control rápidamente al AWT. Esto es muy importante ya que un applet no
debe entrar en un nuevo modo de operación que mantenga el control
durante un periodo largo de tiempo. Por el contrario, el applet debe realizar
acciones específicas en repuesta a eventos y después devolver el control
al AWT. En las situaciones en las que el applet necesite realizar una tarea
repetitiva (por ejemplo, mostrar un mensaje largo en su ventana), se
deberá arrancar un nuevo hilo que ejecuta esta tarea. Auque en este curso
no se ve la programación multihilo, se verá un ejemplo que aplique este
concepto utilizando applets.
En segundo lugar, es el usuario el que inicia una interacción con un applet,
y no al revés. En un programa sin ventanas, cuando el programa necesita
una entrada, aparece el apuntador (prompt) y se llama a algún método de
entrada, como por ejemplo readLine(). Un applet no trabaja así, sino que es
el usuario el que interactúa con el applet como y cuando él quiera. Estas
interacciones se mandan la applet como eventos a los que el applet debe
responder. Por ejemplo, cuando el usuario hace clic dentro de la ventana de
un applet, se genera un evento clic. Si el usuario presiona una tecla cuando
la ventana del applet tiene el foco, se genera un evento keypress. Así, los
applets pueden contener varios controles, como botones o checkbox.
Cuando el usuario interactúa con uno de esos controles, se genera un
evento.
Debido a que la arquitectura de un applet no es tan fácil de entender como
la de un programa basado en consola, el AWT d Java lo hace lo más simple
posible, proporcionando un acceso mucho más claro y sencillo.
Estructura de un applet.
Casi todos los applets más pequeños sobrescriben una serie de métodos
que proporcionan el mecanismo básico mediante el cual el navegador o el
visor de applets se conectan con el applet y controlan su ejecución. Cuatro
de estos métodos, init(), start(), stop() y destroy(), los define Applet.
Otro, paint(), lo define la clase Component. Se proporcionan herramientas
por defecto para todos estos métodos. Los applets no necesitan
sobrescribir los métodos que no utilizan. Sin embargo, sólo los applets muy
sencillos no necesitan sobrescribir todos ellos, estos cinco métodos se
pueden ensamblar.
Es importante entender el orden en el que se llama a los diferentes
métodos en el applet. Cuando comienza un applet, el AWT llama a los
siguientes métodos en el siguiente orden:

init( )
El método init() es el primer método al que se llama. Es aquí cuando se
deben inicializar las variables. A este método sólo se le llama una sola vez
durante la ejecución del applet.
start( )
Al método start() se le llama inmediatamente después del método init().
También es llamado para reanudar un applet después de que este se haya
detenido o parado. Aunque a init() sólo se le llama una vez (cuando
inicialmente se carga un applet), a start() se le llama cada vez que un
documento HTML de un applet se visualiza en la pantalla. Por lo tanto, si un
usuario deja una página Web y vuelve atrás, el applet continúa la ejecución
en start().

paint( )
Al método paint() se le llama cada vez que la salida del applet tiene que
redibujarse. Esto puede ocurrir por varias razones. Por ejemplo, otra
ventana tapa la ventana en la que está corriendo el applet y hay que
visualizarla de nuevo. O cuando se minimiza la ventana del applet y
después se restaura. A paint() también se le llama cuando el applet
comienza a ejecutarse. Cualquiera que sea la causa, siempre que el applet
tenga que volver a dibujar su salida, se llama a paint(). El método paint()
tiene un parámetro del tipo Graphics. En este parámetro estará el contexto
gráfico, que describe el entonro gráfico en el que se está ejecutando el
applet. Este contexto se usa siempre que se requiera una salida al applet.
Cuando finaliza un applet, se llama a los siguientes métodos en este orden:

stop( )
Al método stop() se le llama cuando un navegador deja el documento
HTML que contiene el applet (por ejemplo, cuando se va a otra página).
Cuando se llama a stop(), probablemente el applet continúa ejecutándose.
Se debería usar stop() para suspender tareas que no necesiten ejecutarse
cuando el applet no es visible. Se puede reiniciar estas tareas cuando se
llama a start(), o sea, si el usuario vuelve a la página.

destroy( )
Al método destroy() se le llama cuando el entorno determina que el applet
necesita ser borrado completamente de la memoria. Aquí es cuando hay
que liberar cualquier recurso que pueda estar utilizando el applet. Al método
stop() se le llama siempre antes que a destroy().
Los métodos utilizados para visualizar applets se encuentran definidos en el
AWT, nosotros veremos solamente algunos métodos sencillos que nos
permitan crear nuestros primeros applets.
Métodos sencillos para la visualización de applets.

update( )
Este método está definido en AWT pero el usuario puede sobrescribirlo. La
versión por defecto de update() rellena primero un applet con el color de
fondo que haya por defecto y después llama a paint(). Si se rellena el fondo
con un color diferente con paint(), el usuario verá un flash del fondo cada
vez que se llame a update(), es decir, siempre que se vuelva a pintar la
ventana. Para evitar esto, se sobrescribe el método update() para que
realice lo necesario para una buena visualización. Entonces paint()
simplemente llama a update(). En algunas aplicaciones, el applet
sobrescribe update() y update() de la siguiente forma:
public void update(Graphics g) {
// código para redibujar la ventana.
}
public void paint (Graphics g) {
update(g);
}
drawString( )
Se utiliza para mostrar una cadena de texto en la ventana de un applet.
drawString( ) es un método de la Graphics. Normalmente se llama desde
update o desde paint. Su forma general es la siguiente:
void drawString(String mensaje, int x, int y)

Donde mensaje es la cadena de caracteres que se mostrará en las


coordenadas x, y. Los gráficos de Java se basan en píxeles. Un píxel es un
pequeño punto en la pantalla el cual puede cambiarse a un color específico.
Aunque el número de píxeles varía de un tipo de monitor a otro. Cada píxel
se identifica por un par de números (sus coordenadas), empezando desde
cero:
La posición horizontal, comúnmente llamada x en matemáticas (y en Java),
se incrementa de izquierda a derecha.
La posición vertical, comúnmente conocida como y, se incrementa hacia
abajo.
En una ventana Java, la esquina superior izquierda es el punto 0,0. El
método drawString() no reconoce caracteres de retornos de carro. Por lo
que si se quiere comenzar una nueva línea de texto, hay que hacerlo
manualmente, especificando la coordenada X, Y exacta donde se quiere
que comience la línea.
setBackground( ) y setForeground( )
setBackground( ) se utiliza para establecer el color de fondo de una ventana de un
applet, y para establecer el color del texto se utiliza setForeground( ). Estos
métodos se definen en la clase Component, y sus formas generales son las
siguientes:
void setBackground(Color nuevoColor)
void setForeground(Color nuevoColor)

Donde nuevoColor especifica el nuevo color. La clase Color define las constantes
que se muestran a continuación y que pueden ser utilizadas para especificar
colores.
Color.black Negro Color.magenta Morado
Color.blue Azul Color.orange Naranja
Color.cyan Azul cielo Color.pink Rosa
Color.darkGray Gris oscuro Color.red Rojo
Color.gray Gris Color.white Blanco
Color.green Verde Color.yellow Amarillo
Color.ligthGray Gris claro
Un buen lugar para establecer el color de fondo y el de frente es el método init().
Aunque stos colores pueden cambiarse tantas veces como sea necesario durante la
ejecución del applet. Los colores por defecto son: negro para el texto y gris claro
para el fondo.
getBackground( ) y getForeground( )
Los métodos setBackground() y setForeground(), se utilizan para obtener
los colores que actualmente están establecidos para el fondo y el texto,
respectivamente. Se encuentran definidos en la clase Component de la
siguiente manera:
Color getBackground( )
Color getForeground( )

repaint( )
El método repaint() está definido en AWT y se utiliza para actualizar el
contenido de una ventana cuando su información cambia. Esto hace que el
sistema ejecute una llamada al método update() del applet, y éste método a
su vez, llama por defecto a paint(). Si queremos que otra parte del applet
presente algo en su ventana, lo que se hace es guardar esa salida y llamar
a repaint(), entonces, AWT ejecutará una llamada a paint(), que visualiza la
información guardada. El método repaint() tiene cuatro formas:
La primera es la versión más simple y hace que toda la ventana sea
repintada.
void repaint( )
La siguiente versión especifica la parte o región que será repintada:
void repaint(int left, int top, int width, int height)

Donde las coordenadas de la esquina superior izquierda se especifican por


left y top, y el ancho y el alto de la región por width y height. Las
dimensiones están dadas en pixels. Debe tenerse cuidado ya que
demasiadas llamadas a repaint() en poco tiempo pueden colapsar el AWT,
por esa razón, a update() sólo se le debe llamar de vez en cuando. Una
solución a este problema es utilizar las siguientes formas de repaint():
void repaint(long maxRetraso)
void repaint(long maxRetraso, int left, int top, int width, int height)

Donde maxRetraso especifica el número máximo de milisegundos que


pueden transcurrir antes de llamar a update(). Sin embargo, si el tiempo
que transcurre antes de que se haya llamado a update() es mayor que
maxRetraso, la llamada no se realizará.
showStatus( )
Se utiliza para que un applet escriba un mensaje en la barra de estado del
navegador o del visor de applets en el que se está ejecutando. Para ello
hay que llamar a showStatus(), pasándole una cadena con el mensaje que
se desea mostrar:
void showStatus(String mensaje)

getParameter( )
En HTML, la etiqueta APPLET permite pasar parámetros a un applet. Para
recuperar el valor de un parámetro se utiliza el método getParameter().
Este devuelve el valor del parámetro como un objeto String. Por lo tanto,
para valores numéricos y bolean, se necesitará convertir sus
representaciones de tipo String a sus formatos internos. Por lo que deberán
verificarse los valores de retorno desde getParameter(). Si un parámetro no
está disponible, getParameter() devolverá null. Las conversiones a tipo
numérico también se deben manejar con sentencias try y catch, tratando la
excepción NumberFormatException.
String getParameter(String mensaje)
getDocumentBase( ) y getCodebase( )
Comúnmente, se crearán applets que necesiten explícitamente cargar texto
e imágenes y/o sonido. Java permite cargar datos desde el directorio en el
que se encuentra el archivo HTML que arranca el applet (base del
documento) y desde el directorio desde el cual el archivo clase applet fue
cargado (base de código). Estos directorios se devuelven como objetos
URL mediante getDocumentBase() y getCodebase(). Pueden
concatenarse en una cadena que nombre el archivo que se quiere cargar.
Para cargar otro archivo, se utilizará el método showDocument() definido
por la interfaz AppletContext.
URL getDocumentBase( )
URL getCodebase( )
AppletContext y showDocument()
Java puede mostrar imágenes activas y animación para dar un aspecto
gráfico a la navegación por Internet. Para permitir al applet transferir el
control a otra URL, se debe utilizar el método showDocument(), definido
por la interfaz AppleContext, la cual es una interfaz que da información
desde el entorno de ejecución.
Así, dentro de un applet, y una vez que se ha obtenido el contexto del
applet, se puede visualizar otro documento llamando a showDocument().
Este método no devuelve ningún valor ni lanza ninguna excepción si falla
por lo que hay que utilizarlo con precaución. Hay dos métodos
showDocument(). El método showDocument(URL) visualiza el
documento en la URL especificada. El método showDocument(URL,
where) visualiza el documento especificado en el lugar especificado (where)
dentro de la ventana del navegador. Algunos argumentos válidos para
where son: “_self” (lo muestra en el frame actual), “_parent” (lo muestra en
el frame padre), “_top” (lo muestra en el frame superior), y “_blank” (lo
muestra en una nueva ventana del navegador). También se puede
especificar un nombre, para que el documento se muestre en una nueva
ventana del navegador con ese nombre.
Método Descripción
Applet getApplet(String appletName) Devuelve el applet especificado por
appletName si está dentro del contexto del
applet actual. En caso contrario devuelve null.
Enumeration getApplets( ) Devuelve una enumeración con los applets
que se encuentran dentro del contexto del
actual applet.
AudioClip getAudioClip(URL url) Devuelve un objeto AudioClip que encapsula
el archivo de sonido encontrado en la posición
especificada por url.
Image getImage(URL url) Devuelve un objeto Image que encapsula la
imagen encontrada en la posición especificada
por url.
void showDocument(URL url) Visualiza el documento que se encuentra en el
URL especificado por url. Este método no se
puede utilizar cuando se trabaja con visores de
applets.
void showDocument(URL url, String where) Visualiza el documento que se encuentra en el
URL especificado por url. Este método no se
puede utilizar cuando se trabaja con visores de
applets. La posición del documento en el texto
viene especificada por where.
void showStatus(String str) Muestra la cadena str en la ventana de estado.
Interfaz AudioClip
La interfaz AudioClip define los siguientes métodos:
play( ) (reproduce un archivo de sonido desde el principio),
stop( ) (detiene la reproducción del archivo de sonido), y
loop( ) (reproduce un archivo de sonido en forma continua). Después de
cargar un clip o archivo de audio utilizando getAudioClip( ), estos
métodos se pueden usar para oírlo.
UNIVERSIDAD AUTONOMA DE SINALOA
FACULTAD DE INFORMÁTICA DE MAZATLAN

PROGRAMACIÓN I
Manejo de Eventos
TITULAR DE LA MATERIA:
DR. JOSÉ NICOLÁS ZARAGOZA GONZÁLEZ
EVENTOS.

Los applets son programas basados en eventos. La mayoría de los eventos


a los que un applet va a responder son generados por el mismo usuario.
Hay muchas maneras de pasar estos eventos al applet, desde métodos
específicos hasta métodos reales. Hay muchos tipos de eventos. Los que
normalmente se generan son los que generan el ratón, el teclado y otros
controles como los botones. El paquete java.awt.event es el que contiene
la mayoría de las clases e interfaces de eventos.
La gestión de eventos que hace Java 2 se basa en lo que se llama modelo
de delegación de eventos, que define mecanismos coherentes y estándar
para generar y procesar eventos. Su concepto es muy sencillo: una fuente
genera un evento y lo envía a uno o más oyentes o auditores, que han
estado simplemente esperando hasta que reciben ese evento, y una vez
recibido lo procesan y lo devuelven. La ventaja de todo esto es que la lógica
de aplicación que procesa los eventos está totalmente separada de la lógica
del interfaz de usuario que genera esos eventos. Un elemento de interfaz
de usuario puede delegar el procesamiento de un evento a una parte
separada de código.
Eventos.
En el modelo de delegación, un evento es un objeto que describe un
cambio de estado en una fuente. Se puede generar como una
consecuencia de que una persona interactúe con los elementos en un
interfaz gráfico de usuario. Algunas de las actividades que hacen que se
generen eventos son presionar un botón, introducir un carácter mediante
el teclado, seleccionar una opción de una lista, y hacer clic con el ratón,
entre otros muchos.
Puede ocurrir que no se provoque un evento directamente por la
interacción con un interfaz de usuario. Por ejemplo, se puede generar un
evento cuando un contador pasa de cierto valor o cuando hay un fallo de
software o de hardware, o cuando se acaba una operación. Se es libre de
definir los eventos que uno considere mejores para su aplicación.
Fuentes de eventos.
Una fuente es un objeto que genera un evento. Esto ocurre cuando cambia
de alguna manera el estado interno de ese objeto. Las fuentes pueden
generar más de un tipo de eventos.
Una fuente tiene que ir acompañada de auditores para que estos reciban
notificaciones sobre el tipo específico de evento. Cada tipo de evento tiene
su propio método de registro. La forma general es:
public void addTypeListener(TypeListener el)

donde Type es el nombre del evento y el es una referencia al auditor. Por


ejemplo, el método que registra o acompaña a un auditor de evento de
teclado es addKeyListener( ). El método que registra o acompaña a un
auditor de movimiento del ratón es addMouseMotionListener( ). Cuando
ocurre un evento, se notifica a todos los auditores registrados, que reciben
una copia del objeto evento. Esto es lo que se conoce como multicasting del
evento. En todos los casos, las notificaciones se envían solo a los auditores
que quieren recibirlos.
Algunas fuentes sólo permiten registrar a un auditor. La forma general del
método de registro es:
public void addTypeListener(TypeListener el)
throws java.util.TooManyListenersException

donde Type es el nombre del evento y el es una referencia al auditor.


Cuando se produce el evento, se notifica al auditor que está registrado.
Esto es conocido como unicasting del evento.
Una fuente también puede proporcionar un método que permita a un auditor
eliminar un registro en un tipo específico de evento. La forma general es:
public void removeTypeListener(TypeListener el)

Aquí, Type es el nombre del evento y el es una referencia al auditor. Por


ejemplo, para borrar un auditor de teclado, se llamaría a
removeKeyListener( ).
La fuente que genera eventos es la que proporciona los métodos que
añaden o quitan auditores. Por ejemplo, la clase Component proporciona
métodos para añadir o quitar auditores de eventos del teclado o del ratón.
Auditores de eventos.
Un auditor es un objeto que es avisado cuando ocurre un evento. Tiene dos
requisitos principales. Primero, tiene que ser registrado o ir acompañado
por una o más fuentes para recibir notificaciones sobre los tipos específicos
de eventos. Segundo, tiene que implementar métodos para recibir y
procesar esas notificaciones.
Los métodos que reciben y procesan eventos se definen en un conjunto de
interfaces que están en java.awt.event. Por ejemplo, la interfaz
MouseMotionListener define dos métodos para recibir notificaciones
cuando se arrastra o mueve el ratón. Cualquier objeto puede recibir y
procesar uno de estos eventos, o ambos, si se implementa esa interfaz.
Clases de eventos.
Las clases que representan eventos son el núcleo del mecanismo de gestión de
eventos de Java. A continuación se verán algunas clases de eventos que
proporcionan una forma fácil y potente de encapsular eventos.
Como raíz de la jerarquía de clases de eventos Java está la superclase
EventObject, que está en java.util. Esta es la clase base para todos los eventos y
su constructor es el siguiente:
EventObject(Object src)

Donde src es el objeto que genera ese evento. A su vez, EventObject contiene dos
métodos: getSource( ) y toString( ). El método getSource() devuelve la fuente del
evento. Su forma general es la siguiente:
Object getSource( )

El método toString() devuelve la cadena correspondiente al evento.


La clase AWTEvent, definida dentro del paquete java.awt, es una subclase de
EventObject. Esta es la superclase, directa o indirecta, de todos los eventos
basados en AWT utilizados por el modelo de delegación de eventos. Se puede usar
su método getId() para determinar el tipo del evento. Se define de esta manera:
int getId( )

El paquete java.awt.event define muchos tipos de eventos que se generan


mediante elementos de interfaz de usuario.
Clases de eventos principales en java.awt.event

Clase de evento Descripción


ActionEvent Se genera cuando se presiona un botón, se hace doble clic en un elemento de
una lista, o se selecciona un elemento de menú.
AdjustementEvent Se genera cuando se manipula una barra de desplazamiento.
ComponentEvent Se genera cuando un componente se oculta, se mueve, se cambia de tamaño, o
se hace visible.
ContainerEvent Se genera cuando se añade o se elimina un componente de un contenedor.
FocusEvent Se genera cuando un componente gana o pierde el foco.
InputEvent Superclase abstracta para cualquier clase de evento de entrada de
componente.
ItemEvent Se genera cuando se hace clic en un checkbox o en un elemento de una lista;
también ocurre cuando se hace una selección en una opción (choice) o cuando
se selecciona o se deselecciona un elemento de un menú de opciones.
KeyEvent Se genera cuando se recibe una entrada desde el teclado.
MouseEvent Se genera cuando el ratón se arrastra, se mueve, se hace clic, se presiona, o se
libera; también se genera cuando el ratón entra o sale de un componente.
TextEvent Se genera cuando se cambia el valor de un área de texto o un campo de texto.
WindowEvent Se genera cuando una ventana se activa, se cierra, se desactiva, se minimiza,
se maximiza, se abre, o se sale de ella.
La clase ActionEvent.
Se genera un objeto de la clase ActionEvent cuando se presiona un botón,
se hace doble clic en un elemento de una lista, o se selecciona algo de un
menú. La clase ActionEvent define cuatro constantes enteras que se
pueden utilizar para identificar cualquier modificador asociado con este tipo:
ALT_MASK, CTRL_MASK, META_MASK y SHIFT_MASK. Hay otra
constante entera, ACTION_PERFORMED, que se puede utilizar para
identificar eventos de acción.
ActionEvent tiene estos dos constructores:
ActionEvent(Object src, int type, String cmd)
ActionEvent(Object src, int type, String cmd, int modifiers)

Donde src es una referencia al objeto que ha generado ese evento. El tipo
del evento se especifica con type, y la cadena cmd corresponde a su
comando. El argumento modifiers indica que teclas modificadoras (ALT,
CTRL, META y/o SHIFT) se han presionado cuando se ha generado el
evento.
Se puede obtener el nombre del comando del objeto invocado ActionEvent
utilizando el método getActionCommand( ), como se muestra a
continuación:
String getActionCommand( )
Por ejemplo, cuando se presiona un botón, se genera un evento de acción
que tiene un nombre de comando igual a la etiqueta (label) de ese botón.
El método getModifiers( ) devuelve un valor que indica qué tecla
modificadora (ALT, CTRL, META y/o SHIFT) se han presionado cuando el
evento se ha generado. Su forma es la siguiente:
int getModifiers( )
La clase FocusEvent.
Se genera un objeto evento de la clase FocusEvent cuando un
componente está o deja de estar activo. Estos eventos se identifican
mediante las constantes enteras: FOCUS_GAINED y FOCUS_LOST.
FocusEvent es una subclase de ComponentEvent y tiene estos
constructores:
FocusEvent(Component src, int type)
FocusEvent(Component src, int type, boolean temporaryFlag)

Donde src es una referencia al componente que ha generado ese evento. El


tipo del evento es especificado por type. El argumento temporaryFlag es
puesto a true si el evento foco es temporal. En cualquier otro caso, se pone
a false. (Un evento foco temporal reproduce como resultado de otra
operación de interfaz de usuario. Por ejemplo, si lo que está activo –tiene el
foco- es un campo de texto. Si el usuario mueve el ratón para modificar una
barra de desplazamiento, entonces el campo de texto pierde temporalmente
el foco).
El método isTemporary( ) indica si este cambio de foco es temporal. Su
forma es la siguiente:
boolean isTemporary( )
El método devuelve true si el cambio es temporal. Si no, devuelve false.
La clase InputEvent.
La clase abstracta InputEvent es una subclase de ComponentEvent y es
la superclase para los eventos de entrada de componentes. Sus clases
derivadas son KeyEvent y MouseEvent. La clase InputEvent define las
siguientes ocho constantes enteras, que se pueden utilizar para obtener
información sobre cualquier modificador asociado con el evento:
ALT_MASK BUTTON2_MASK META_MASK
ALT_GRAPH_MASK BUTTON3_MASK SHIFT_MASK
BUTTON1_MASK CTRL_MASK
Los métodos isAltDown( ), isAltGraphDown( ), isControlDown( ),
isMetaDown( ), isShiftDown( ) comprueban si esos modificadores se ha
presionado al mismo tiempo que se ha generado el evento. Las formas de
estos métodos son las siguientes:
boolean isAltDown( )
boolean isAltGraphDown( )
boolean isControlDown( )
boolean isMetaDown( )
boolean isShiftDown( )
El método getModifiers( ) devuelve un valor que contiene todas las
etiquetas de los modificadores para ese evento:
int getModifiers( )
La clase ItemEvent.
Se genera un objeto de la clase ItemEvent cuado se hace clic en un check
box o en un elemento de una lista, o cuando se selecciona o se
deselecciona un elemento de un menú checkable. Hay dos tipos de eventos
de elemento los cuales se identifican por las siguientes constantes enteras:
DESELECTED El usuario deselecciona un elemento.
SELECTED El usuario selecciona un elemento.
Además, ItemEvent define una constante entera,
ITEM_STATE_CHANGED, que significa un cambio de estado. ItemEvent
tiene el siguiente constructor:
ItemEvent(ItemSelectable src, int type, Object entry, int state)

Donde src es una referencia al componente que ha generado ese evento.


Un ejemplo podría ser una lista o un elemento de elección. El tipo de
elemento es especificado por type. Lo que específicamente genera el
evento de elemento se pasa con entry. El estado actual del elemento es
state.
El método getItem( ) se puede utilizar para obtener una referencia al
elemento que ha generado un evento. Su forma es la siguiente:
Object getItem( )
El método getItemSelectable( ) se puede utilizar para obtener una
referencia al objeto ItemSelectable que ha generado un evento. Su forma
general es la siguiente:
ItemSelectable getItemSelectable( )

Las listas (List) y las listas desplegables (choice) son ejemplos de


elementos de interfaz de usuario que implementan el interfaz
ItemSelectable.
El método getStateChange( ) devuelve el cambio de estado (por ejemplo,
SELECTED o DESELECTED) para el evento. Su forma general es la
siguiente:
int getStateChange( )
La clase KeyEvent.
Se genera un evento de la clase KeyEvent cuando se pulas una tecla. Hay
tres clases de eventos de teclado los cuales están definidos por las
siguientes constantes enteras: KEY_PRESSED, KEY_RELEASED y
KEY_TYPED. Los primeros dos eventos se generan cuando se presiona o
se libera cualquier tecla. El último evento sólo se da cuando se genera un
carácter, ya que no siempre se generan caracteres al presionar teclas. Por
ejemplo, si se presiona la tecla SHIFT sola, no se genera ningún carácter.
KeyEvent define muchas constantes enteras. Por ejemplo: VK_0 a VK_9 y
VK_A a VK_Z definen los ASCII equivalentes a números y letras. Algunos
otros son los siguientes:
VK_ENTER VK_ESCAPE VK_CANCEL VK_UP
VK_DOWN VK_LEFT VK_RIGHT VK_PAGE_DOWN
VK_PAGE_UP VK_SHIFT VK_ALT VK_CONTROL
Las constantes VK especifican códigos de teclas virtuales y son
independientes de cualquier modificador, como control, shift o alt. KeyEvent
es una subclase de InputEvent y tiene estos dos constructores:
KeyEvent(Component src, int type, long when, int modifiers, int code)
KeyEvent(Component src, int type, long when, int modifiers, int code,
char ch)
Donde src es una referencia al componente que genera ese evento. El tipo
del evento es especificado por type. El momento en el que se ha
presionado la tecla se pasa con when. Los argumentos modifiers indican
qué modificador se ha presionado cuando ha ocurrido ese evento de
teclado. El código de tecla virtual, como VK_UP, VK_A, y así
sucesivamente, se pasa con code. El carácter equivalente (si existe alguno)
se pasa con ch. Si no existe ningún carácter válido, entonces ch contiene a
CHAR_UNDEFINED. Para los eventos KEY_TYPED, code contendrá a
VK_UNDEFINED.
La clase KeyEvent define varios métodos pero los que más se usan son
getKeyChar( ), que devuelve el carácter que se ha tecleado, y
getKeyCode( ), que devuelve el código de la tecla. Sus formas generales
son las siguientes:
char getKeyChar( )
int getKeyCode( )

Si no hay disponible carácter válido alguno, entonces getKeyChar( )


devuelve CHAR_UNDEFINED. Cuando se produce un evento
KEY_TYPED, getKeyCode( ) devuelve VK_UNDEFINED.
La clase MouseEvent.
Hay siete tipos de eventos de ratón. La clase MouseEvent define las
siguientes constantes enteras, que se pueden utilizar para identificarlos:
MOUSE_CLICKED El usuario hace clic con el ratón.
MOUSE_DRAGGED El usuario arrastra el ratón.
MOUSE_ENTERED El ratón se introduce en un componente.
MOUSE_EXITED El ratón sale de un componente.
MOUSE_MOVED Se mueve el ratón.
MOUSE_PRESSED Se presiona un botón de ratón.
MOUSE_RELEASED Se libera el ratón.
MouseEvent es una subclase de InputEvent y tiene este constructor:
MouseEvent(Component src, int type, long when, int modifiers,
int x, int y, int clicks, boolean triggersPopup)

Donde src es una referencia al componente que ha generado el evento. El tipo del
evento es especificado por type. El momento en el que ha ocurrido el evento ratón
se pasa con when. El argumento modifiers indica qué modificador se ha presionado
cuando ha ocurrido un evento ratón. Las coordenadas del ratón se pasan con x, y.
El número de clicks se pasa con clicks. La etiqueta triggersPopup indica si ese
evento hace que aparezca un menú en esa plataforma.
Los métodos que más se usan en esta clase son getX( ) y getY( ). Estos métodos
devuelven las coordenadas X, Y del ratón cuando ha ocurrido el evento. Sus formas
son las siguientes:
int getX( )
int getY( )

También se puede usar el método getPoint( ) para obtener las coordenadas del
ratón:
Point getPoint( )

Este devuelve un objeto Point que contiene las coordenadas X, Y en sus miembros
enteros: x, y.
El método translatePoint( ) traduce la posición del evento. Su forma es la siguiente:
void translatePoint(int x, int y)

Aquí, los argumentos x, y se añaden a las coordenadas del evento.


El método getClickCount( ) da el número de clicks que se han hecho con el ratón
para ese evento. Su forma es la siguiente:
int getClickCount( )

El método isPopupTrigger( ) prueba si el evento ha hecho aparecer un menú en la


plataforma. Su forma es la siguiente:
boolean isPopupTrigger( )
La clase TextEvent.
Con esta clase se describen eventos de texto. Se generan mediante
campos de texto y áreas de texto cuando el usuario o el programa
introducen caracteres. TextEvent define la constante entera
TEXT_VALUE_CHANGED. El único constructor para esta clase es:
TextEvent(Object src, int type)

Donde src es una referencia al objeto que ha generado el evento. El tipo de


evento es especificado por type.
El objeto TextEvent no incluye los caracteres que ya están en el
componente de texto que ha generado el evento, sino que es el programa el
que tiene que utilizar otros métodos asociados con el componente de texto
para recuperar la información.
La clase WindowEvent.
Hay siete tipos de eventos de ventana. La clase WindowEvent define
constantes enteras que se pueden utilizar para identificarlos. Las
constantes y sus significados son los siguientes:
WINDOW_ACTIVATED Se ha activado la ventana.
WINDOW_CLOSED Se ha cerrado la ventana.
WINDOW_CLOSING El usuario ha pedido que se cierre la ventana.
WINDOW_DEACTIVATED La ventana ha dejado de estar activa.
WINDOW_DEICONIFIED Se ha mostrado la ventana tras pulsar su icono.
WINDOW_ICONIFIED Se ha minimizado la ventana a un icono.
WINDOW_OPENED Se ha abierto la ventana.
WindowEvent es una subclase de ComponentEvent y tiene el siguiente
constructor:
WindowEvent(Window src, int type)
Donde src es una referencia al objeto que ha generado el evento. El tipo
del evento es type.
El método más utilizado en esta clase es getWindow( ), que devuelve el
objeto Window que ha generado el evento. Su forma general es la
siguiente:
Window getWindow( )
Fuentes de eventos.
En la siguiente tabla aparecen algunos de los componentes de interfaz del
usuario que pueden generar los eventos descritos anteriormente. Pero
además de esos elementos de interfaz gráfico de usuario, hay más
componentes, como un applet, que pueden generar eventos. Por ejemplo,
se pueden recibir eventos de ratón y de teclado desde un applet.
Origen de evento Descripción
Button Genera eventos de acción (ActionEvent) cuando se presiona el botón
Checkbox Genera eventos de elemento (ItemEvent) cuando se selecciona o se
deselecciona un check box.
Choice Genera eventos de elemento cuando se cambia una opción (choice).
List Genera eventos de acción cuando se hace doble clic sobre un elemento: genera
eventos de elemento cuando se selecciona o se deselecciona un elemento.
Menú Item Genera eventos de acción cuando se selecciona un elemento de menú: genera
eventos de elemento cuando se selecciona o se deselecciona un elemento de
un menú de opciones.
Scrollbar Genera eventos de ajuste (AdjustementEvent) cuando se manipula la barra de
desplazamiento.
Text components Genera eventos de texto (TextEvent) cuando el usuario introduce un carácter.
Window Genera eventos de ventana (WindowEvent) cuando una ventana se activa, se
cierra, se desactiva, se minimiza, se maximiza, se abre o se sale de ella.
Interfaces auditores de eventos.
Como se indicó anteriormente, el modelo de delegación de eventos tiene
dos partes: fuentes y auditores u oyentes. Los auditores se crean
implementando al menos una de las interfaces definidas en el paquete
java.awt.event. Cuando se produce un evento, la fuente de evento invoca
el método apropiado definido por el auditor y proporciona un objeto evento
como su argumento. A continuación se muestra cada una de las interfaces y
los métodos específicos de cada una de ellas.
1. La interfaz ActionListener.
Esta interfaz define el método actionPerformed( ) que se invoca cuando se
da un evento de acción. Su forma general es la siguiente:
void actionPerformed(ActionEvent ae)

2. La interfaz AdjustmentListener.
Esta interfaz define el método adjustmentValueChanged( ) que se invoca
cuando se produce un evento de ajuste. Su forma general es la siguiente:
void adjustmentValueChanged(AdjustmentEvent ae)
3. La interfaz ComponentListener.
Esta interfaz define cuatro métodos que se invocan cuando a un
componente se le cambia el tamaño, se mueve, se muestra o se oculta. Sus
formas generales son las siguientes:
void componentResized(ComponentEvent ce)
void componentMoved(ComponentEvent ce)
void componentShown(ComponentEvent ce)
void componentHidden(ComponentEvent ce)

4. La interfaz ContainerListener.
Esta interfaz tiene dos métodos. Cuando se añade un componente a un
contenedor, se invoca a componentAdded( ). Cuando se borra un
componente de un contenedor, se invoca a componentRemoved( ). Sus
formas generales son las siguientes:
void componentAdded(ContainerEvent ce)
void componentRemoved(ContainerEvent ce)
5. La interfaz FocusListener.
Esta interfaz define dos métodos. Cuando un componente obtiene el foco
del teclado, se invoca focusGained( ). Cuando un componente pierde el
foco del teclado, se llama a focusLost( ). Sus formas generales son las
siguientes:
void focusGained(FocusEvent fe)
void focusLost(FocusEvent fe)

6. La interfaz ItemListener.
Esta interfaz define el método itemStateChanged( ) que se invoca cuando
cambia el estado de un elemento. Su forma general es la siguiente:
void itemStateChanged(ItemEvent ie)
7. La interfaz KeyListener.
Esta interfaz define tres métodos. Los métodos keyPressed( ) y
keyReleased( ) se invocan cuando se presiona y se libera una tecla,
respectivamente. El método keyTyped( ) se invoca cuando se introduce un
carácter.
Por ejemplo, si un usuario presiona y libera la tecla A, se generan tres
eventos en este orden: tecla presionada, carácter introducido, tecla
liberada. Si un usuario presiona y libera la tecla INICIO, se generan dos
eventos en este orden: tecla presionada, tecla liberada.
Las formas generales de estos eventos son las siguientes:
void keyPressed(KeyEvent ke)
void keyReleased(KeyEvent ke)
void keyTyped(KeyEvent ke)
8. La interfaz MouseListener.
Esta interfaz define cinco métodos. Si se presiona y se libera el ratón en el
mismo punto, se invoca a mouseClicked( ). Cuando el ratón se introduce
en un componente, se llama al método mouseEntered(). Cuando el ratón
sale del componente, se llama a mouseExited(). Los métodos
mousePressed( ) y mouseReleased( ) se invocan cuando se presiona y
se libera el ratón, respectivamente.
Las formas generales de estos métodos son las siguientes:
void mouseClicked(MouseEvent me)
void mouseEntered(MouseEvent me)
void mouseExited(MouseEvent me)
void mousePressed(MouseEvent me)
void mouseReleased(MouseEvent me)

9. La interfaz MouseMotionListener.
Esta interfaz define dos métodos. Al método mouseDragged( ) se le llama
tantas veces como se arrastre el ratón. Al método mouseMoved( ) se le
llama tantas veces como se mueva el ratón. Sus formas generales son:
void mouseDragged(MouseEvent me)
void mouseMoved(MouseEvent me)
10. La interfaz TextListener.
Esta interfaz define el método textChanged( ) que se invoca cuando hay
un cambio en un área de texto o en un campo de texto. Su forma general
es la siguiente:
void textChanged(TextEvent te)

11. La interfaz WindowListener.


Esta interfaz define siete métodos. Los métodos windowActivated( ) y
windowDeactivated( ) se invocan cuando se activa o desactiva una
ventana, respectivamente. Si una ventana se minimiza a un icono, se llama
al método windowIconified( ). Cuando una ventana es mostrada pulsando
en su icono, s ellama al método windowDeiconified( ). Cuando se abre o
se cierra una ventana, se llama a los métodos windowOpened( ) o
windowClosed( ), respectivamente. Al método windowClosing( ) se le
llama cuando se está cerrando una ventana. Las formas generales de
estos métodos son:
windowActivated(WindowEvent we)
windowClosed(WindowEvent we)
windowClosing(WindowEvent we)
windowDeactivated(WindowEvent we)
windowDeiconified(WindowEvent we)
windowIconified(WindowEvent we)
windowOpened(WindowEvent we)
Utilización del método de delegación de eventos.
Una vez que se conoce como trabaja el método de delegación de eventos
y se tiene una idea general de sus componentes, se puede pasar a
trabajar con él. Así, la programación de applets utilizando el método de
delegación de eventos es bastante fácil. Solo hay que seguir estos dos
pasos:
1. Implementar la interfaz apropiada en el auditor, de tal manera que
reciba el tipo de evento deseado.
2. Implementar el código para registrar y eliminar el registro (si fuese
necesario) del auditor como destinatario de las notificaciones de eventos.
Debido a que una fuente puede generar muchos tipos de eventos. Cada
evento se tiene que declarar de forma separada. Asimismo, se puede
registrar un objeto auditor para que reciba varios tipos de eventos, pero se
deben implementar todas las interfaces que hagan falta para recibir esos
eventos.
Para ver como trabaja el método de delegación de eventos, se muestran
dos ejemplos que gestionan los dos generadores de eventos que más se
utilizan: el ratón y el teclado.
La gestión de eventos del ratón.
Para gestionar eventos del ratón, se deben implementar las interfaces
MouseListener y MouseMotionListener. El siguiente applet muestra este
proceso. Se visualizan las actuales coordenadas del ratón en la ventana de estado
del applet. Cada vez que se presione un botón, se verá la palabra “Abajo” en la
posición que apunta el ratón. Y cuando se libere el botón, aparecerá la palabra
“Arriba”. Si se hace clic en un botón, se verá el mensaje “Click en el ratón” en la
esquina superior izquierda. Cuando el ratón entre o salga de la ventana del applet,
se verá un mensaje en la esquina superior izquierda del panel del applet. Cuando
se arrastre el ratón, se mostrará un “*”, que se ira dejando como pista de por donde
se ha ido arrastrando el ratón. Las dos variables mouseX y mouseY, guardan la
mposición del ratón cuando se da un evento presionar, liberar o arrastrar el ratón.
Cada método gestiona y su evento y luego devuelve el control.
Dentro de init(), el applet se declara a sí mismo como auditor para eventos de
ratón. Esto se hace utilizando addMouseListener() y addMouseMotionListener().
synchronized void addMouseListener(MouseListener ml)
synchronized void addMouseMotionListener((MouseMotionListener mml)

Donde ml es una referencia al objeto que recibe los eventos del ratón, y mml es
una referencia al objeto que recibe los eventos de movimiento del ratón.
La gestión de eventos del teclado.
Para gestionar eventos de teclado se utiliza la misma arquitectura que se
acaba de ver para los eventos de ratón. La diferencia es que se
implementará la interfaz Key Listener. El applet incluye la gestión de
algunas teclas especiales (virtuales), como los cursores o las teclas de
función, utilizando el manejador keyPressed( ), ya que no están
disponibles a través de keyTyped( ). Para identificar las teclas, hay que
utilizar sus códigos de tecla virtuales. Un aspecto que hay que conocer
antes de que el programa pueda procesar eventos del teclado, es que tiene
que pedir el foco de entrada. Para hacer esto, hay que llamar a
requestFocus( ), que está definido por Component. Si no se hace esto,
entonces el programa no recibirá ningún evento del teclado.
UNIVERSIDAD AUTONOMA DE SINALOA
FACULTAD DE INFORMÁTICA DE MAZATLAN

PROGRAMACIÓN I
Herramientas gráficas AWT
TITULAR DE LA MATERIA:
DR. JOSÉ NICOLÁS ZARAGOZA GONZÁLEZ
HERRAMIENTAS GRÁFICAS AWT.

El AWT (Abstract Window Toolkit) contiene numerosos métodos y clases


que permiten crear y gestionar ventanas. En esta unidad solo se verán unos
cuantos métodos y técnicas necesarias para utilizar eficazmente el AWT
cuando se crean applets o aplicaciones.
Aunque el propósito principal del AWT es dar el soporte necesario a las
ventanas de los applets, también se puede utilizar para crear ventanas
independientes que se ejecuten en un entorno gráfico de internaza de
usuario, como Windows. La mayoría de los ejemplos son applets, por lo que
para ejecutarlos es necesario utilizar un visor de applets o un navegador
compatible con Java. También se muestran unos ejemplos sencillos de
programas de aplicación con ventanas.

Las clases AWT.


El paquete java.awt contiene todas las clases de AWT. Algunas de estas
clases se presentan a continuación:
Clase Descripción
AWTEvent Encapsula eventos del AWT.
AWTEventMulticaster Envía eventos a varios auditores.
BorderLayout Es un gestor de organización. Utiliza cinco componentes: North
(Norte), South (Sur), East (Este), West (Oeste) y Center (Centro).
Button Crea un botón de control (push button).
Canvas Crea una ventana en blanco sin una semántica asociada.
CardLayout Es el gestor de organización con tarjetas. Simula tarjetas
indexadas; solo se enseña la que está en la parte superior.
Checkbox Crea un control checkbox.
CheckboxGroup Crea un grupo de controles checkbox.
CheckboxMenuItem Crea un elemento de menú de tipo on/off.
Choice Crea una lista pop-up (emergente).
Color Gestiona los colores en un entorno portátil independiente de la
plataforma.
Component Es una superclase abstracta de varios componentes del AWT.
Container Es una subclase de Component que puede contener otros
componentes.
Cursor Encapsula un cursor “bitmapeado”.
Dialog Crea una ventana de diálogo.
Clase Descripción
Dimension Especifica las dimensiones de un objeto. El ancho se almacena en
width y el alto en height.
Event Encapsula eventos.
EventQueue Pone eventos en cola.
FileDialog Crea una ventana desde la que se puede seleccionar un archivo.
FlowLayout Es un gestor de organización que sitúa los componentes de izquierda
a derecha y de arriba hacia abajo.
Font Encapsula un tipo de letra.
FontMetrics Encapsula información relacionada con un tipo de letra. Esta
información ayuda a mostrar texto en una ventana.
Frame Crea una ventana estándar que tiene una barra de título, esquinas
que permiten cambiar el tamaño de la ventana y un menú.
Graphics Encapsula el contexto gráfico. Este contexto lo utilizan varios
métodos para mostrar la salida en una ventana.
GraphicsDevice Describe un dispositivo gráfico como una pantalla o una impresora.
GraphicsEnviroment Describe la colección de objetos Font y GraphicsDevice disponibles.
GridBagConstraints Define varias restricciones relacionadas con la clase
GridBagLayout.
Clase Descripción
GridBagLayout Es un gestor de organización en cuadrícula. Muestra los componentes
con las limitaciones especificadas por GridBagConstraint.
GridLayout Es un gestor de organización en cuadrícula. Muestra los componentes
en una cuadrícula de dos dimensiones.
Image Encapsula imágenes gráficas.
Insets Encapsula los bordes de un contenedor.
Label Crea una etiqueta que muestra una cadena de caracteres.
List Crea una lista donde el usuario puede elegir un elemento. Es similar a
la lista estándar de Windows.
MediaTracker Gestiona objetos multimedia.
Menu Crea un menú desplegable.
MenuBar Crea una barra de menú.
MenuComponent Clase abstracta implementada por varias clases del menú.
MenuItem Crea un elemento de un menú.
MenuShortcut Encapsula un atajo vía teclado para un elemento de menú.
Panel Es una subclase concreta de Container.
Point Encapsula las coordenadas cartesianas almacenadas en x, y.
Polygon Encapsula un polígono.
Clase Descripción
PopupMenu Encapsula un menú pop-up.
PrintJob Clase abstracta que representa una tarea de impresión.
Rectangle Encapsula un rectángulo.
Robot Soporta aplicaciones basadas en chequeos automáticos de AWT.
Scrollbar Crea un control de barra de desplazamiento.
ScrollPane Contenedor que proporciona barras de desplazamiento horizontales y/o
verticales para otro componente.
SystemColor Contiene los colores de los widgets GUI como ventanas, barras de
desplazamiento, texto, etc. Un widget es un elemento gráfico con el que
el usuario puede interactuar.
TextArea Crea un control para un área de texto con varias líneas.
TextComponent Es una superclase TextArea y TextField.
TextField Crea el control para un área de texto con una línea.
Toolkit Clase abstracta implementada por el AWT.
Window Crea una ventana sin marco, sin menú y sin título.
Fundamentos básicos de las ventanas.
El AWT define ventanas de acuerdo con una jerarquía de clases que da
funcionalidad y carácter específico a cada nivel. Los dos tipos de ventanas
más utilizados son las que se derivan de Panel, que son las empleadas por
los applets, y las que se derivan de Frame (marco), que permiten crear una
ventana estándar. La mayor parte de la funcionalidad de estas ventanas las
heredan de sus superclases. En la parte superior de la jerarquía del AWT
se encuentra la clase Component. Esta clase define más de cien métodos
públicos que son responsables de la gestión de eventos como: la entrada
por teclado o ratón, cambio de tamaño y posición de la ventana, y del
repintado de una ventana. La siguiente figura muestra la jerarquía de
clases de Panel y Frame.
Component

Container
MenuContainer
Interface
Window Panel

Frame
Trabajar con ventanas Frame.
Después del applet, el tipo de ventana más común es el derivado de la
clase Frame. Se utilizan para crear ventanas hijas dentro de los applets y
ventanas de nivel superior o hijas para las aplicaciones con un estilo
estándar. Los dos constructores de la clase Frame son:
Frame( )
Frame(String título)

El primero crea una ventana estándar que no tiene título. El segundo crea
una ventana con el título indicado en la cadena título. Las dimensiones de
la ventana se establecen una vez que se ha creado la ventana. No se
pueden establecer sus dimensiones en el constructor. A continuación se
verán algunos métodos que se utilizan al trabajar con ventanas Frame.
1. Establecer las dimensiones de una ventana.
El método setSize( ) se utiliza para establecer las dimensiones de una
ventana:
void setSize(int newWidth, int newHeight)
void setSize(Dimension newSize)

El Nuevo tamaño de la ventana se especifica con newWidth y newHeight, o


con los campos width y height del objeto Dimension pasado con newSize.
Las dimensiones son en pixels.
El método getSize( ) se utiliza para obtener el tamaño actual de una
ventana:
Dimension getSize( )

Este método devuelve el tamaño actual de la ventana contenida en los


campos width y height de un objeto Dimension.
2. Ocultar y mostrar una ventana.
Después de crear una ventana de tipo Frame, no será visible hasta que no
se llame al método setVisible( ), que tiene el siguiente formato:
void setVisible(boolean visibleFlag)

El componente es visible si el argumento visibleFlag es true. En caso


contrario permanecerá oculto.

3. Poner título a una ventana.


Se puede cambiar el título a una ventana de tipo Frame con el método
setTitle( ), que tiene la siguiente forma:
void setTitle(String newTitle)

Donde newTitle es el nuevo título de la ventana.

4. Cerrar una ventana Frame.


Cuando se utilice una ventana de tipo Frame, el programa debe eliminarla
de la pantalla cuando se cierre esa ventana. Esto lo hace llamando al
método setVisible(false). Si se quiere detener el evento de cerrar ventana,
se debe implementar el método windowClosing( ) de la interfaz
WindowListener. En el método windowClosing( ) se debe borrar la
ventana de la pantalla.
Crear una ventana Frame en un applet.
Normalmente las ventanas Frame se crean desde un applet. Primero se
crea una subclase de Frame. Después se sobrescribe los métodos de la
ventana estándar, como init(), start(), stop() y paint(). Por último, se
implementa el método windowClosing() de la interfaz WindowListener,
llamando a setVisible(false) cuando se cierra la ventana.
Una vez que se ha definido una subclase Frame, se puede crear un objeto
de esa clase. Esto hace que se cree una ventana Frame, aunque
inicialmente no sea visible. Se puede hacer visible llamando a setVisible().
Cuando se crea la ventana, se le asigna un alto y un ancho por defecto.
Ahora se puede establecer el tamaño de la ventana de forma explícita
llamando al método setSize().
Creación de un programa con ventanas.
Generalmente se utiliza el AWT de Java para crear applets, pero también se
pueden crear aplicaciones independientes basadas en el AWT. Para
hacerlo, simplemente hay que crear una instancia de la ventana o ventanas
que se vayan a necesitar dentro de main(). El siguiente programa crea una
ventana Frame que responde a los clicks del ratón y cuando se pulsa una
tecla:

Una vez creada la ventana Frame tiene vida propia. Aunque main() termina
con la llamada a unaAplicacionVentana.setVisible(true). El programa
sigue ejecutándose hasta que se cierra la ventana. Básicamente, cuando se
crea una aplicación con ventanas, se utilizará main() para lanzar su
ventana de nivel superior. Después, el programa funcionará igual que una
aplicación basada en Interfaz Gráfica del Usuario (Graphic User Interface o
GUI), y no como los anteriores programas basados en consola.
/* MiAplicacionVentana.java */
import java.awt.*;
import java.awt.event.*;
// Crea una ventana marco o frame.
public class MiAplicacionVentana extends Frame
{
String keyMensaje = " ";
String mouseMensaje = " ";
int ratonX = 30, ratonY = 30;
public MiAplicacionVentana() {
addKeyListener(new MiKeyAdapter(this));
addMouseListener(new MiMouseAdapter(this));
addWindowListener(new MiVentanaAuditora());
}
public void paint(Graphics g)
{
g.drawString(keyMensaje, 10, 40);
g.drawString(mouseMensaje, ratonX, ratonY);
}
// Crea la ventana.
public static void main(String args[ ])
{
MiAplicacionVentana unaAplicacionVentana = new MiAplicacionVentana();
unaAplicacionVentana.setSize(new Dimension(300, 200));
unaAplicacionVentana.setTitle("Apicacion basada en el AWT");
unaAplicacionVentana.setVisible(true);
}
} // Fin de la clase.
/* MiKeyAdapter.java */
import java.awt.*;
import java.awt.event.*;
public class MiKeyAdapter extends KeyAdapter
{
MiAplicacionVentana appVentana;

public MiKeyAdapter(MiAplicacionVentana appVentana) {


this.appVentana = appVentana;
}
public void keyTyped(KeyEvent ke)
{
appVentana.keyMensaje += ke.getKeyChar();
appVentana.repaint();
}
} // Fin de la clase
/* MiMouseAdapter.java */
import java.awt.*;
import java.awt.event.*;
public class MiMouseAdapter extends MouseAdapter
{
MiAplicacionVentana appVentana;

public MiMouseAdapter(MiAplicacionVentana appVentana) {


this.appVentana = appVentana;
}
public void mousePressed(MouseEvent me)
{
appVentana.ratonX = me.getX();
appVentana.ratonY = me.getY();
appVentana.mouseMensaje = "Posicion del raton "+appVentana.ratonX+",
"+appVentana.ratonY;
appVentana.repaint();
}
} // Fin de la clase

/* MiVentanaAuditora.java */
import java.awt.*;
import java.awt.event.*;
public class MiVentanaAuditora extends WindowAdapter
{
public void windowClosing(WindowEvent we)
{
System.exit(0);
}
} // Fin de la clase
Gráficos.
En el sentido más amplio, una ventana es un contenedor de información, la
cual puede presentar textos de alta calidad y gráficos. Gran parte de la
potencia del AWT viene de estos elementos, y el AWT tiene una amplia
variedad de métodos gráficos. Todos los gráficos se dibujan en una
ventana, que puede ser la ventana principal de un applet, una ventana hija
de un applet, o una ventana de una aplicación independiente. El origen (0,0)
de cada ventana está en la esquina superior izquierda. Las coordenadas
están dadas en píxeles. Todas las salidas sobre una ventana se hacen a
través de un contexto gráfico el cual está encapsulado en la clase Graphics
y se obtiene de dos posibles maneras:
•Se pasa a un applet cuando se llama a alguno de sus métodos, como
paint( ) o update( ).
•Es devuelto por el método getGraphics( ) de Component.
Los gráficos pueden aparecer en la ventana principal de un applet o en
cualquier otra ventana. En la clase Graphics se definen un conjunto de
métodos para dibujar. Se puede dibujar una figura o una forma rellena, o
sólo su borde. Los objetos se dibujan y se rellenan con el color que esté en
ese momento seleccionado, el color por defecto es el negro. Cuando se
intenta dibujar un objeto gráfico de dimensiones mayores que las de la
ventana, la salida se corta automáticamente.
Entre otras figuras, Java permite dibujar:
•Líneas;
•Rectángulos;
•Óvalos (y por consecuencia también círculos);
•Arcos.
También pueden dibujarse:
•Rectángulos con realce (tridimensionales);
•Rectángulos con esquinas redondeadas;
•Polígonos.
Además, se puede especificar un color para rellenar las figuras.
Un objeto se dibuja en el color actual, que puede cambiarse mediante el
método setColor(). Los colores disponibles son:
black Negro magenta Morado
blue Azul orange Naranja
cyan Azul cielo pink Rosa
darkGray Gris oscuro red Rojo
gray Gris white Blanco
green Verde yellow Amarillo
ligthGray Gris claro

Si queremos cambiar el color actual a rojo, debe invocarse:


setColor( red);
Las coordenadas de los objetos se expresan como coordenadas de píxel x,
y. x se mide a o largo de la pantalla, empezando desde la izquierda. y se
mide hacia debajo de la pantalla, tomando como origen la parte superior.
Muchos de los objetos gráficos se dibujan como si estuvieran dentro de un
rectángulo invisible (contenedor o container) cuyas coordenadas de píxel
superior izquierdo son x, y. La altura y la anchura del rectángulo, que se
mide en píxeles, son los otros dos parámetros.
A continuación se presentan un grupo de métodos que proporciona las
capacidades necesarias para mostrar cadenas y objetos gráficos en la
pantalla.
java.awt.Graphics (import java.awt.Graphics; o import java.awt.*;)

Método Descripción
public abstract void clearRect (int x, Borra el rectángulo especificado, llenándolo con el color de fondo.
int y, int ancho, int alto)
public void draw3DRect (int x, int y, Dibuja un rectángulo resaltado en 3D. Si el valor de relieve es
int ancho, int alto, boolean relieve) verdadero (true), el rectángulo aparece con relieve.
public void drawArc (int x, int y, int Dibuja un arco circular o elíptico. El arco se dibuja empezando
ancho, int alto, int anguloInicio, int desde anguloInicio hasta anguloInicio+anguloArco. Los ángulos
anguloArco) se miden en grados. Un ángulo de 0 grados representa la posición
de las 3:00 en el reloj. Un valor de anguloArco positivo indica un
sentido contrario a las manecillas del reloj.
public abstract boolean drawImage Dibuja la imagen dentro del rectángulo especificado, escalándola
(Image imagen, int x, int y, int ancho, en caso de ser necesario. Debe especificarse un objeto como el
int alto, ImageObserver observador) último parámetro. Este objeto es notificado en caso de que la
imagen no se cargue completamente. Por lo general, este
parámetro es simplemente this.
public void drawLine (int x1, int y1, Dibuja una línea desde las coordenadas x1, y1 hasta x2, y2.
int x2, int y2)
public void drawOval (int x, int y, int Dibuja una elipse o un círculo (si el ancho y el alto son iguales).
ancho, int alto)
public void drawPolygon (int puntosX[ Dibuja un polígono cerrado, utilizando los pares de coordenadas
], int puntosY[ ], int puntosn) en los dos arreglos. Se dibuja una línea desde el primer hasta el
último punto.
public void drawRect (int x, int y, int Dibuja un rectángulo, utilizando el color actual.
ancho, int alto)
java.awt.Graphics (import java.awt.Graphics; o import java.awt.*;)

Método Descripción
public void drawRoundRect (int x, int Dibuja un rectángulo con esquinas redondeadas en el color actual.
y, int ancho, int alto, int anchoArco, int anchoArco es el diámetro horizontal del arco en las cuatro
altoArco) esquinas y altoArco es el diámetro vertical.
public void drawString (String cad, Dibuja la cadena especificada en cad. La línea base del primer
int x, int y) carácter se encuentra en la coordenada x, y. Los caracteres están
en el tipo de letra y color actuales.
public void fillArc (int x, int y, int Dibuja una figura en forma de pastel, utilizando de relleno el color
ancho, int alto, int anguloInicio, int actual.
anguloArco)
public void fillOval (int x, int y, int Dibuja una elipse o círculo relleno.
ancho, int alto)
public void fillPolygon (int puntosX[ ], Rellena un polígono con el color actual.
int puntosY[ ], int puntosn)
public void fillRect (int x, int y, int Rellena un rectángulo con el color actual.
ancho, int alto)
public void fillRoundRect (int x, int y, Rellena un rectángulo redondeado con el color actual.
int ancho, int alto, int anchoArco, int
altoArco)
public void setColor (Color c) Establece el color actual. Los colores disponibles son los
indicados en la tabla anterior.
java.awt.Button (import java.awt.Button; o import java.awt.*;)

Método Descripción
public Button (String etiqueta) Crea un botón con la etiqueta indicada.
public String getLabel( ) Devuelve la etiqueta en este botón.

java.awt.Canvas (import java.awt.Canvas; o import java.awt.*;)

Método Descripción
public Canvas( ) Crea un lienzo para dibujar.
public void paint (Graphics g) Vuelve a dibujar el lienzo. Normalmente el programador redefine
este método.

java.awt.Checkbox (import java.awt.Checkbox; o import java.awt.*;)

Método Descripción
public Checkbox (String cad) Crea una casilla de verificación con la etiqueta cad.
public Checkbox (String cad, Crea una casilla de verificación con la etiqueta cad, dentro del grupo
Checkboxgroup g, boolean estado) de casillas de verificación de nombre g y con el estado inicial.
public boolean getState ( ) Devuelve el estado de la casilla de verificación.

java.awt.CheckboxGroup (import java.awt.CheckboxGroup; o import java.awt.*;)


Método Descripción
public CheckboxGroup ( ) Crea un nuevo grupo de casillas de verificación, al que se pueden
agregar casillas.
java.awt.Choice (import java.awt.Choice; o import java.awt.*;)

Método Descripción
public Choice ( ) Crea un nuevo grupo de cuadros de opción al que se le pueden
agregar más de este tipo de cuadros.
public void addItem (String Agrega un elemento a este cuadro de opción.
elemento)
public String getSelectedItem( ) Devuelve el elemento seleccionado.

java.awt.Component (import java.awt.Component; o import java.awt.*;)

Método Descripción
public Color getBackground( ) Devuelve el color de fondo.
public Graphics getGraphics( ) Devuelve el contexto de gráficos que, por lo general se llama g.
public void paint (Graphics g) El programador lo redefine para dibujar la ventana, g es el contexto
de gráficos.
public void repaint ( ) El programador lo invoca cuando la pantalla necesita volver a
dibujarse. Ocasiona que se invoque a paint().
public void setSize (int ancho, int Cambia el tamaño del componente al tamaño especificado en la
alto) pantalla.
public void setVisible (boolean Hace que el componente sea visible (o no) en la pantalla.
visible)
java.awt.Container (import java.awt.Container; o import java.awt.*;)
Método Descripción
public Component add Agrega el componente al final del contenedor.
(Component comp)
public void remove Elimina el componente del contenedor.
(Component comp)
public void setSize (int Cambia el tamaño del componente al tamaño especificado.
ancho, int alto)
public void setLayout Administrador de esquemas. Las opciones son: FlowLayout(), GridLayout(),
(LayoutManager m) BorderLayout().

java.awt.FileDialog (import java.awt.FileDialog; o import java.awt.*;)

Método Descripción
public FileDialog Crea una ventana de diálogo de archivos. El padre es el marco que crea la
(Frame padre, String ventana. El título es el título de la ventana. El modo puede ser FileDialog.LOAD
titulo, int modo) o FileDialog.SAVE.
public String getFile( ) Devuelve el nombre del archivo que ha sido seleccionado, o un valor nulo si no
se ha seleccionado ninguno.

java.awt.Frame (import java.awt.Frame; o import java.awt.*;)

Método Descripción
public FileDialog ( ) Crea un marco.
public void setTitle Establece el título del marco en la cadena cad.
(String cad)
java.awt.Label (import java.awt.Label; o import java.awt.*;)

Método Descripción
public Label (String etiqueta) Crea una nueva etiqueta.

java.awt.List (import java.awt.List; o import java.awt.*;)

Método Descripción
public List (int r, boolean varios) Crea una nueva lista con r renglones visibles. Si varios es
verdadero (true), entonces pueden seleccionarse varios
elementos. Si varios es falso (false), entonces sólo puede
seleccionarse un elemento.
public void add (String elemento) Agrega el elemento a la lista.
public void add (String elemento, int Agrega el elemento en el índice especificado.
índice)
public String getSelectedItem ( ) Devuelve una cadena, que es el nombre del elemento
seleccionado, o null si no hay elemento seleccionado (la lista sólo
permite que se seleccione un elemento).
public String[ ] getSelectedItem ( ) Devuelve una cadena, que es el nombre del elemento
seleccionado, o null si no hay elemento seleccionado (la lista
permite que se seleccionen varios elementos).
public void remove (int índice) Elimina el elemento que se encuentre en el índice especificado.
public void remove (String Elimina la primera ocurrencia del elemento.
elemento)
java.awt.Menu (import java.awt.Menu; o import java.awt.*;)

Método Descripción
public MenuItem add (MenuItem mi) Agrega un elemento a un menu.
public void addSeparator ( ) Agrega un separador a un menú.
public Menu (String cadena) Crea un menú con el nombre especificado por la cadena.

java.awt.MenuBar (import java.awt.MenuBar; o import java.awt.*;)

Método Descripción
public Menu add (Menu m) Agrega un menú a una barra de menús.
public MenuBar ( ) Crea una barra de menus.

java.awt.MenuItem (import java.awt.MenuItem; o import java.awt.*;)

Método Descripción
public MenuItem ( ) Crea un elemento de menú con la cadena especificada como
etiqueta.

java.awt.ScrollBar (import java.awt.ScrollBar; o import java.awt.*;)

Método Descripción
public ScrollBar (int orientación, int Crea una nueva barra de desplazamiento.
valor, int visible, int mínimo, int
máximo)
public int getValue ( ) Devuelve el valor entero.
java.awt.TextArea (import java.awt.TextArea; o import java.awt.*;)

Método Descripción
public TextArea (int renglones, int Crea una nueva área de texto con un tamaño definido por el
columnas) número de renglones y por el número de columnas.
public TextArea (String texto, int Crea una nueva área de texto, iniciándola con la cadena.
renglones, int columnas, int vista) vista especifica las barras de desplazamiento a mostrar,
mediante uno de los siguientes valores:
SCROLLBARS_BOTH
SCROLLBARS_HORIZONTAL_ONLY
SCROLLBARS_VERTICAL_ONLY
SCROLLBARS_NONE
public void append (String cad) Agrega la cadena cad al final del texto actual.
public void insert (String cad, int aquí) Inserta la cadena cad en el índice aquí.

java.awt.TextComponent (import java.awt.TextComponent; o import java.awt.*;)


Método Descripción
public String getSelectedText ( ) Devuelve el texto seleccionado por el usuario.
public int getSelectionStart ( ) Devuelve el índice del primer carácter seleccionado por el
usuario.
public int getSelectionEnd ( ) Devuelve el índice del último carácter seleccionado por el
usuario.
public String getText ( ) Devuelve el texto completo.
public void setText (String cad) Asigna el texto complete a la cadena cad.
public void setEditable (boolean b) Si b es verdadero (true), el componente se vuelve editable.
java.awt.TextField (import java.awt.TextField; o import java.awt.*;)

Método Descripción
public TextField (int cols) Crea un nuevo campo de texto, con una anchura de cols
caracteres.
Texto.
El AWT permite trabajar con diversos tipos de letra, los cuales han surgido
de los tipos tradicionales de imprenta y se han convertido en una parte
importante de las visualizaciones de los documentos generados por
computadora. El AWT proporciona gran flexibilidad para las operaciones de
manipulación de tipos de letra y permite la selección dinámica de dichos
tipos de letra.
En Java 2, los tipos de letra tienen un nombre de familia, un nombre lógico
y un nombre. El nombre de familia es el nombre general del tipo de letra,
por ejemplo: Courier. El nombre lógico especifica una categoría del tipo de
letra, como SansSerif. El nombre o nombre face especifica el tipo de letra,
como Courier Italic. La clase Font encapsula los tipos de letra. En la
siguiente tabla se muestran algunos de los métodos definidos por la clase
Font.
Método Descripción
static Font decode(String cad) Devuelve un tipo de letra dando su nombre.
boolean equals(Object FontObj) Devuelve true si el objeto que llama ala método contiene el mismo tipo
de letra que el especificado por FontObj. En caso contrario devuelve
false.
String getFamily( ) Devuelve el nombre de la familia de tipo de letra a la que pertenece el
tipo de letra que ha realizado la llamada.
static Font getFont(String Devuelve el tipo de letra asociado a la propiedad especificada por
property) property. Devuelve null si no existe property.
static Font getFont(String Devuelve el tipo de letra asociado a la propiedad especificada por
property, Font defautlFont) property. Devuelve null si no existe property. Devuelve el tipo de letra
especificado por defaultFont si no existe property.
String getFontName( ) Devuelve el nombre del tipo de letra que ha llamado al método.
String getName( ) Devuelve el nombre lógico del tipo de letra que ha llamado al método.
int getSize( ) Devuelve el tamaño, en puntos, del tipo de letra que llama al método.
int getStyle( ) Devuelve el valor del estilo del tipo de letra que llama al método.
int hashCode( ) Devuelve el código hash asociado al objeto que llama al método.
boolean isBold( ) Devuelve true si el tipo de letra incluye el estilo BOLD. En caso
contrario devuelve false.
boolean isItalic( ) Devuelve true si el tipo de letra incluye el estilo ITALIC. En caso
contrario devuelve false.
boolean isPlaint( ) Devuelve true si el tipo de letra incluye el estilo PLAIN. En caso
contrario devuelve false.
String toString( ) Devuelve la cadena equivalente al tipo de letra que llama al método.
La clase Font define las siguientes variables:

Variable Significado
String name Nombre del tipo de letra.
float pointSize Tamaño, en puntos, del tipo de letra.
int size Tamaño, en puntos, del tipo de letra.
int style Estilo del tipo de letra.

Cuando se desea saber los tipos de letra que están disponibles en la


computadora se utiliza el método getAvailableFontFamilyNames( )
definido por la clase GraphicsEnviroment.
String[ ] getAvailableFontFamilyNames( )

Este método devuelve un arreglo de cadenas con los nombres de las


familias de tipos de letras disponibles.
El método getAllFonts( ) está definido por la clase GraphicsEnviroment:
Font[ ] getAllFonts( )

Este método devuelve un arreglo de objetos Font que contiene todos los
tipos de letra disponibles.
Para seleccionar u nuevo tipo de letra, primero hay que construir un objeto
Font que describa ese tipo de letra. Una de las formas del constructor
Font tiene el siguiente formato:
Font(String fontName, int fontStyle, int pointSize)

Aquí, fontName especifica el nombre del tipo de letra deseado. Se puede


especificar el nombre utilizando ya sea el nombre lógico o el nombre face.
Todos los entornos Java admiten los siguientes tipos de letra: Dialog,
DialogInput Sans Serif, Serif, Monospaced y Symbol. Dialog es el tipo de
letra que utilizan las cajas de diálogo del sistema. También es el tipo de
letra que hay por defecto. Se puede utilizar cualquier otro tipo de letra que
haya en la computadora, pero hay que tener cuidado con eso puesto que
puede que no estén disponibles en todos los entornos.
El estilo del tipo de letra se especifica en fontStyle. Puede estar formado
por una o más de estas tres constantes: Font.PLAIN, Font.BOLD y
Font.ITALIC. Para combinar estilos se puede hacer un OR. Por ejemplo,
Font.BOLD | Font.ITALIC especifica un estilo en negrita y cursiva.
El tamaño del tipo de letra, en puntos, se especifica con pointSize.
Para utilizar un tipo de letra propio, se utiliza el método setFont( ), que está
definido por Component y tiene la siguiente forma general:
void setFont(Font fontObj)

donde fontObj es el objeto que contiene el tipo de letra deseado.


Cuando se quiera obtener información sobre el tipo de letra seleccionado.
Primero hay que obtener el tipo de letra en curso llamando al método
getFont( ). Este método está definido por la clase Graphics, como se
muestra a continuación:
Font getFont( )

Una vez que se tiene el tipo de letra que se está utilizando, se puede
obtener información de él utilizando varios métodos definidos por la clase
Font.
El siguiente ejemplo muestra una aplicación de la clase Font y el manejo de
las cinco fuentes básicas:
import java.awt.*;
import java.awt.event.*;
// Crea una ventana marco o frame.
public class Texto extends Frame
{
Font f;
String msg;
public Texto() {
this.addWindowListener(this);
}
public void miFuente (int x)
{
switch (x) {
case 1 : f = new Font ("Dialog", Font.PLAIN, 12);
setFont (f);
msg = "Dialog"; break;
case 2 : f = new Font ("DialogInput", Font.PLAIN, 12);
setFont (f);
msg = "DialogInput"; break;
case 3 : f = new Font ("SansSerif", Font.PLAIN, 12);
setFont (f);
msg = "SanSerif"; break;
case 4 : f = new Font ("Serif", Font.PLAIN, 12);
setFont (f);
msg = "Serif"; break;
case 5 : f = new Font ("Monospaced", Font.PLAIN, 12);
setFont (f);
msg = "Monospaced";
}
}
public void paint(Graphics g)
{
g.drawString ("Hola... Esta es una aplicación con texto", 10, 200);
miFuente(1);
g.drawString (msg, 20, 50);
miFuente(2);
g.drawString (msg, 20, 75);
miFuente(3);
g.drawString (msg, 20, 100);
miFuente(4);
g.drawString (msg, 20, 125);
miFuente(5);
g.drawString (msg, 20, 150);
}
public static void main(String args[ ])
{
Texto unaAplicacionVentana = new Texto();
unaAplicacionVentana.setSize(new Dimension(300, 300));
unaAplicacionVentana.setTitle("Apicacion basada en el AWT");
unaAplicacionVentana.setVisible(true);
}
} // Fin de la clase.
APLICACIONES CON ENTORNO GRÁFICO.

Las aplicaciones en entorno gráfico son el tipo de programas más utilizados


en la actualidad. Utilizando cuadros de texto (text field), botones (buttons),
barras de desplazamiento (scroll bars) y cajas de diálogo (check box), estas
aplicaciones utilizan lo que se conoce como GUI (Graphic User Interface o
Interfaz Gráfica de Usuario). Para aplicar GUI se utiliza Java Swing, sin
embargo, con lo visto hasta el momento podemos hacer aplicaciones
sencillas que funcionen con GUI. Para desarrollar estas aplicaciones,
debemos manejar algunos conceptos de la programación orientada a
eventos. En primer lugar debemos definir el tipo de herramienta a utilizar:
•cuadro de texto (text field),
•botones (buttons),
•barras de desplazamiento (scroll bars),
•cajas de diálogo (check box),
•listas, y/o
•barras de menú y menús.
Cuadros de texto.
La clase TextField implementa un área de entrada de texto de una sola
línea que se llama control de edición. Los campos de texto (text fields)
permiten al usuario introducir cadenas y editar texto utilizando los cursores,
las teclas de cortar y pegar, y las selecciones que se hacen con el ratón. La
clase TextField es una subclase de TextComponent. TextField
proporciona los siguientes constructores:
TextField( )
TextField(int numChars)
TextField(String cad)
TextField(String cad, int numChars)

La primera versión crea un campo de texto por defecto. El segundo formato


crea un campo de texto que tiene una anchura de numChars caracteres. La
tercera versión inicializa el campo de texto con la cadena dada por cad. El
cuarto formato inicializa un campo de texto con la cadena cad y además
especifica su anchura.
Botones.
Es el control más utilizado. Un botón es un componente que contiene una
etiqueta y que genera un evento cuando es pulsado. Los botones son
objetos de la clase Button. Button proporciona dos constructores:
Button( )
Button(String cad)

El primer constructor crea un botón vacío (sin etiqueta). El segundo crea un


botón que contiene cad como etiqueta.
Cada vez que se pulsa un botón, se genera un evento de acción que se
envía a cualquier auditor que previamente haya registrado un interés por
recibir información de eventos de acción que genere ese componente. Cada
auditor implementa la interfaz ActionListener. Esta interfaz define el
método actionPerformed( ), al que se llama cuando ocurre un evento.
Como argumento a ese método se pasa un objeto ActionEvent. Contiene
una referencia la botón que ha generado el evento y una referencia a la
cadena que es la etiqueta del botón. Normalmente se puede utilizar
cualquier valor para identificar un botón.
En total, se requieren seis pasos para configurar un botón:
•Indicar que la clase implementa a ActionListener.
•Declarar una variable de botón, dándole un nombre.
•Crear un nuevo botón, dándole una etiqueta.
•Agregar el botón a la ventana.
•Informar al botón que este objeto responderá a los eventos del botón,
utilizando addActionListener.
•Proporcionar un método llamado actionPerformed que sea llamado
cuando ocurra un evento de clic de botón.
Barras de desplazamiento.
Las barras de desplazamiento se utilizan para seleccionar valores continuos entre
un mínimo y un máximo especificados. Las barras de desplazamiento pueden ser
horizontales o verticales. Una barra de desplazamiento tiene varios elementos. Cada
extremo tiene una flecha en la que se puede hacer clic para mover una unidad en la
dirección de la flecha el valor actual de la barra de desplazamiento. El valor actual
de la barra de desplazamiento, en relación a sus valores mínimo y máximo, lo indica
un cuadrado (o caja de desplazamiento), que el usuario puede arrastrar hasta una
nueva posición. El usuario puede hacer clic en una zona de la barra de
desplazamiento en la que no está el cuadrado, para que éste salte en esa dirección
logrando incrementos mayores que 1. Esta acción se puede convertir en una forma
de avance de página o retroceso de página. La clase Scrollbar encapsula a las
barras de desplazamiento y define los siguientes constructores:
Scrollbar( )
Scrollbar(int estilo)
Scrollbar(int estilo, int valorInicial, int tamaño, int min, int max)

El primer formato crea una barra de desplazamiento vertical. El segundo y tercer


formatos permiten determinar la orientación de la barra de desplazamiento. Si estilo
es Scrollbar.VERTICAL, se crea una barra de desplazamiento vertical. Si estilo es
Scrollbar.HORIZONTAL, la barra de desplazamiento es horizontal. En el tercer
formato, el valor inicial de la barra de desplazamiento se pasa con valorInicial. El
número de unidades que representa la altura del cuadrado es tamaño. Los valores,
mínimo y máximo de la barra de desplazamiento se especifican con min y max.
Cajas de diálogo.
Las cajas de diálogo o checkbox son objetos de la clase Checkbox. Un checkbox es
un control que se utiliza para activar o desactivar una opción. Está formado por un
pequeño cuadro que puede contener o no, una marca de comprobación. Hay una
etiqueta asociada a cada checkbox que describe qué opción representa. Para
cambiar el estado de un checkbox sólo hay que pulsar sobre él. Los checkbox se
pueden utilizar individualmente o como parte de un grupo. Checkbox proporciona
los siguientes constructores:
Checkbox( )
Checkbox(String cad)
Checkbox(String cad, boolean on)
Checkbox(String cad, boolean on, CheckboxGroup cbGroup)
Checkbox(String cad, CheckboxGrouop cbGroup, boolean on)

El primer formato crea un checkbox cuya etiqueta está inicialmente vacía y el estado
del checkbox es no seleccionado. El segundo formato crea un checkbox cuya
etiqueta está especificada en cad y el estado del checkbox está también como no
seleccionado. El tercer formato permite establecer el formato inicial del checkbox. Si
on es true, el checkbox está inicialmente seleccionado; si no, esta no seleccionado.
Los formatos cuarto y quinto crean un checkbox cuya etiqueta viene especificada
por cad y cuyo grupo está especificado por cbGroup. Si este checkbox no pertenece
a ningún grupo, cbGroup tiene que ser null. El valor de on determina el estado
inicial del checkbox.
Listas.
La clase List proporciona una lista de selección compacta, con
desplazamiento, que permite realizar selecciones múltiples. Se puede
construir un objeto List que muestre cualquier número de opciones en una
ventana. También se puede configurar de manera que se puedan realizar
selecciones múltiples. List tiene estos constructores:
List( )
List(int numRenglones)
List(int numRenglones, boolean selecciónMúltiple)

La primera versión crea un control List que permite que haya solo un
elemento seleccionado en cada instante. En el segundo formato, el valor de
numRenglones especifica el número de entradas en la lista que estarán
visibles (las demás se pueden ver cuando sea necesario desplazándose por
la ventana). En el tercer formato, si selecciónMúltiple es verdadero, el
usuario puede seleccionar dos o más elementos a al vez. Si es falso, sólo
se puede seleccionar un elemento.
Barras de menú y menús.
Una ventana de nivel superior puede tener asociada una barra de menú,
que muestra una lista de opciones de menú de nivel superior. Cada opción
está asociada a un menú desplegable. Este concepto se implementa en
Java con las clases: MenuBar, Menu y MenuItem. En general, una barra
de menú tiene uno o más objetos Menu. Cada objeto Menu tiene una lista
de objetos MenuItem. Cada objeto MenuItem representa algo que el
usuario puede seleccionar. Debido a que Menu es una subclase de
MenuItem, se puede crear una jerarquía de submenús anidados. También
se pueden incluir elementos de menú que puedan verificar (o seleccionar),
que son opciones de menú de la clase CheckboxMenuItem y aparece una
marca al lado de ellos cuando se seleccionan.
Para crear una barra de menú, primero hay que crear una instancia de
MenuBar. Esta clase solo define el constructor por defecto. Después, se
crean instancias de Menu que definan las selecciones que se muestran en
la barra.
Los constructores de Menu son los siguientes:
Menu( )
Menu(String nombreOpción)
Menu(String nombreOpción, boolean removible)

Donde nombreOpción especifica el nombre de la selección de menú. Si


removible es verdadero, el menú pop-up puede flotar libremente. En caso
contrario, permanecerá siempre junto a la barra de menú (estos menús
dependen de la implementación). El primer constructor crea un menú vacío.
Los elementos individuales del menú son de la clase MenuItem. Esta clase
define los siguientes constructores:
MenuItem( )
MenuItem(String nombreItem)
MenuItem(String nombreItem, MenuShortcut teclaAcel)

Aquí, nombreItem es el nombre que se muestra en el menú, y teclaAcel es


la tecla aceleradora para ese elemento.
Organización de los componentes de las ventanas
Una vez que hemos definido una ventana y los componentes que vamos a
incluir en la misma, debemos organizarlo utilizando los denominados
Layout. De esta manera podemos definir la posición y el alineamiento de
los botones, los cuadros de texto y demás componentes. Las principales
clases para el manejo de Layouts son:
FlowLayout() Coloca los componentes en fila, uno junto a otro, acomodándolos de
acuerdo al ancho de la ventana.
BoxLayout() Acomoda los componentes en fila de forma vertical u horizontal.
GridLayout() Coloca los componentes en forma de una matriz, adaptándolos al
tamaño de la ventana y quedando todos del mismo tamaño.
BorderLayout() Este Layout divide la ventana en 5 partes: centro, arriba, abajo,
derecha e izquierda. El tamaño de cada parte depende de los
componentes que van dentro.
La parte de arriba y abajo se pueden estirar de izquierda a derecha
hasta ocupar toda la ventana.
Las partes izquierda y derecha se estiran de arriba a abajo hasta
ocupar todo el espacio disponible entre las zonas de arriba y abajo.
La parte del centro se estira en ambas direcciones hasta tocar a las
otras zonas.
Los anchos de cada zona son los necesarios para que quepan los
componentes que se colocan dentro.
El esquema general de BorderLayout es el siguiente:

Arriba (NORTH)

Izquierda Derecha

(WEST) Centro (EAST)

(CENTER)

Abajo (SOUTH)

Ejemplos:
setLayout (new FlowLayout (FlowLayout.CENTER ) ;
setLayout (new GridLayout (Renglones, Columnas, SeparaciónX, SeparaciónY ));
setLayout (new BorderLayout ( ));

Con BorderLayout(), también podemos definir la posición donde


queremos colocar los botones o cuadros de texto con el método
setBounds(CoordX, CoordY, Largo, Alto).

Ejemplo de aplicación de BorderLayout:


import java.awt.*;
import java.applet.Applet;

public class EjemploBorderLayout extends Applet {

public void init () {


setLayout (new BorderLayout ( ));
add(new Button("North"), BorderLayout.NORTH);
add(new Button("South"), BorderLayout.SOUTH);
add(new Button("East"), BorderLayout.EAST);
add(new Button("West"), BorderLayout.WEST);
add(new Button("Center"), BorderLayout.CENTER);
}

public void paint (Graphics g) {


showStatus("Ejemplo de BorderLayout");
}
}
Cuadros de diálogo para leer de datos y mostrar mensajes
Java Swing cuenta con interfaces gráficas para la captura de datos y para
mostrar mensajes. Para poderlos utilizar requerimos importar el paquete:
import javax.swing.*;
La clase JOptionPane cuenta con diversos métodos que permiten abrir
cuadros de diálogo para capturar datos y enviar mensajes o mostrar
resultados, estos métodos son showInputDialog y showMessageDialog.
La forma en que se pueden aplicar estos métodos es:

showInputDialog
JOptionPane.showInputDialog(null, “Mensaje”);
JOptionPane.showInputDialog(null,“Mensaje”,null,JOptionPane.QUESTION_MESSAGE);
JOptionPane.showInputDialog(null,“Mensaje”,null,JOptionPane.INFORMATION_MESSAGE);

showMessageDialog
JOptionPane.showMessageDialog(null, “Mensaje”);
JOptionPane.showMessageDialog(null,“Mensaje”,null,JOptionPane.INFORMATION_MESSAGE);
JOptionPane.showMessageDialog(null,“Mensaje”,null,JOptionPane.WARNING_MESSAGE);
JOptionPane.showMessageDialog(null,“Mensaje”,null,JOptionPane.ERROR_MESSAGE);
Ejemplo de aplicación de los métodos de JOptionPane:
import java.io.*;
import javax.swing.*;

public class Suma5


{
public static void main(String args[ ])
{
int a=0, b=0, c=0;
String num = " ";
JOptionPane.showMessageDialog(null,"Programa que suma dos numeros enteros", null,
JOptionPane.INFORMATION_MESSAGE);

num = JOptionPane.showInputDialog(null, "Dame el primer numero: ");


a = Integer.parseInt(num);
num = JOptionPane.showInputDialog(null, "Dame el segundo numero: ");
b = Integer.parseInt(num);

c = a + b;

JOptionPane.showMessageDialog(null, "La suma es: "+c);

} /* fin del main */


} /* fin de la clase */
Añada los siguientes métodos a la clase LeerDato:
import javax.swing.*;
public class LeerDato {

// . . . Otros métodos . . .

/* Método para convertir la cadena leída en entero (int) */


public static int numInt(String mensaje) {
try {
return Integer.parseInt(JOptionPane.showInputDialog(null,mensaje));
}
catch(NumberFormatException e) {
return 0;
}
}
/* Método para convertir la cadena leída en número real (double) */
public static double numDouble(String mensaje) {
try {
return Double.parseDouble(JOptionPane.showInputDialog(null,mensaje));
}
catch(NumberFormatException e) {
return 0;
}
}
} /* Fin de la clase * /
Aplicaciones usando AWT.

A continuación se muestra el esquema general para construir una


aplicación basada en AWT. En este caso suponemos que la clase modelo
se encuentra definida en su propio archivo. Aunque la GUI esta en el
constructor, también puede definirse en un método independiente y
llamarlo explícitamente:
import java.awt.*;
import java.awt.event.*;
public class AplicaciónAWT extends Frame implements ActionListener, WindowListener
{
// variables de instancia
private Button unBoton;
private Scrollbar barraDesplazamiento;
private Modelo unaInstanciaModelo;
// Programa principal.
public static void main(String args[ ])
{
AplicaciónAWT miAplicacionAWT = new AplicaciónAWT ();
miAplicacionAWT.setSize(new Dimension(300, 300));
// Instrucciones
miAplicacionAWT.setVisible(true);
}
public AplicaciónAWT( ) { // constructor
setLayout(new FlowLayout( ));
unBoton = new Button(“Mensaje”);
add(unBoton);
unInstanciaModelo = new Modelo();
this.addWindowListener(this); // para WindowClosing
}
public void paint(Graphics g)
{
g.drawString(”Mensaje”) ;
}
public void actionPerformed(ActionEvent event)
{
if (event.getSource() == unBoton)
// responder al botón, por ejemplo:
unInstanciaModelo.hacerAlgo();
}
public void windowClosing(WindowEvent we)
{ System.exit(0); }
public void windowIconified(WindowEvent we)
{ }
public void windowOpened(WindowEvent we)
{ }
public void windowClosed(WindowEvent we)
{ }
public void windowDeiconified(WindowEvent we)
{ }
public void windowActivated(WindowEvent we)
{ }
public void windowDeactivated(WindowEvent we)
{ }
} // Fin de la clase.
import java.awt.*;
El siguiente programa import java.awt.event.*;
import java.applet.*;
permite seleccionar import java.text.*;
una de las cuatro import java.util.*;
public class OperacionesG extends Frame implements
operaciones básicas ActionListener, WindowListener
{
(suma, resta, private TextField dato1, dato2;
multiplicación o private double a = 0.0, b = 0.0, c = 0.0;
private Button boton1, boton2, boton3, boton4;
división), trabajando private String msg = " ", op = " ";
en entorno gráfico en public OperacionesG () {
setLayout(new BorderLayout());
base al esqueleto dato1 = new TextField(15);
anterior. Utilizando add(dato1); dato1.setBounds(20, 90, 80, 20);
dato1.addActionListener(this);
cuadros de texto para dato2 = new TextField(15);
capturar los datos y add(dato2); dato2.setBounds(120, 90, 80, 20);
dato2.addActionListener(this);
botones para boton1 = new Button("Suma");
seleccionar la add(boton1); boton1.setBounds(30, 120, 60, 30);
boton1.addActionListener(this);
operación deseada (el boton2 = new Button("Resta");
ejemplo no considera add(boton2); boton2.setBounds(130, 120, 60, 30);
boton2.addActionListener(this);
excepciones, ni la boton3 = new Button("Multiplica");
add(boton3); boton3.setBounds(30, 160, 60, 30);
posible división entre boton3.addActionListener(this);
cero). boton4 = new Button("Divide");
add(boton4); boton4.setBounds(130, 160, 60, 30);
boton4.addActionListener(this);
setLayout(new BorderLayout());
this.addWindowListener(this); }
// Programa principal.
public static void main(String args[ ])
{
OperacionesG unaAplicacionVentana = new OperacionesG();
unaAplicacionVentana.setSize(new Dimension(300, 300));
unaAplicacionVentana.setTitle("Aplicacion basada en el AWT");
unaAplicacionVentana.setVisible(true);
}
public void paint(Graphics g)
{
g.drawString("Cuatro operaciones básicas“,30,50); g.drawString("Primer Num",20,80);
g.drawString("Segundo Num",120,80); g.drawString("La "+msg+" de "+a+op+b+" = "+c,30,240);
Date hoy = new Date();
String patron = "EEEE dd-MMM-yyyy, HH:mm:ss";
SimpleDateFormat formato = new SimpleDateFormat(patron);
String salida = formato.format(hoy);
g.drawString(salida,30,280);
}
public void actionPerformed(ActionEvent event)
{
a = Double.parseDouble(dato1.getText());
repaint();
b = Double.parseDouble(dato2.getText());
repaint();
if (event.getSource() == boton1) { c = a + b; msg = "suma"; op = " + "; }
else
if (event.getSource() == boton2) { c = a - b; msg = "resta"; op = " - "; }
else
if (event.getSource() == boton3) { c = a * b; msg = "multiplicación"; op = " * "; }
else
if (event.getSource() == boton4) { c = a / b; msg = "división"; op = " / "; }
repaint();
}
public void windowClosing(WindowEvent we)
{
System.exit(0);
}
public void windowIconified(WindowEvent we)
{ }
public void windowOpened(WindowEvent we)
{ }
public void windowClosed(WindowEvent we)
{ }
public void windowDeiconified(WindowEvent we)
{ }
public void windowActivated(WindowEvent we)
{ }
public void windowDeactivated(WindowEvent we)
{ }
} // Fin de la clase.
A continuación se muestra un ejemplo de la aplicación del programa:
El siguiente programa crea una ventana con una malla de botones
(ButtonGrid) aplicando JAVA Swing:

import javax.swing.JFrame; //importa la libreria JFrame


import javax.swing.JButton; //importa la libreria JButton
import java.awt.GridLayout; //importa la libreria GridLayout

public class ButtonGrid {


JFrame frame = new JFrame(); //crea el frame o ventana
JButton[][] grid; //nombra el arreglo o malla de botones
public ButtonGrid(int width, int length) { //constructor
frame.setLayout(new GridLayout(width,length)); //aplicación de setLayout
grid=new JButton[width][length]; //define el tamaño de la malla
for(int y=0; y<length; y++){
for(int x=0; x<width; x++){
grid[x][y]=new JButton("("+x+","+y+")"); //crea nuevos botones
frame.add(grid[x][y]); //añade un boton a la malla o grid
}
}
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack(); //define el tamaño apropiado par las ventanas
frame.setVisible(true); //hace la ventana visible
}

public static void main(String[] args) {


new ButtonGrid(3,3); //Crea una nueva malla de botones
}
}
El siguiente código, es un programa que abre una ventana o frame, con un
nombre o título, con la fecha en la barra de estado, con un botón en la
parte superior y barras de desplazamiento horizontal y vertical:
import java.text.*; Date hoy = new Date();
import java.util.*; String patron = "EEEE dd-MMM-yyyy, HH:mm:ss";
import java.awt.*; SimpleDateFormat formato = new SimpleDateFormat(patron);
import java.awt.event.*; String salida = formato.format(hoy);
import javax.swing.*; Label mensaje=new Label("Esto aparece en la barra de estado:
"+salida);
public class EjemploVentanaTres extends JFrame{ ventana.add(mensaje, BorderLayout.SOUTH);
static JFrame ventana= new JFrame(); ventana.setExtendedState(NORMAL);

public static void main(String args[]) { // se agrega un verificador para que cierre la ventana con la x de arriba
JScrollPane barra; ventana.addWindowListener(new WindowAdapter() {
JButton boton1; public void windowClosing(WindowEvent e) {System.exit(0);}
ventana.setTitle("Ejemplo de una Ventana o Frame"); });
ventana.setBackground(java.awt.Color.white); } // termina main
ventana.setExtendedState(ICONIFIED); } // termina clase
ventana.setSize(600,400);
ventana.setVisible(true);
ventana.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ventana.setLayout(new BorderLayout());
JTextArea texto1 = new JTextArea(400,200);
texto1.setEditable(false);
texto1.append("\n\n\n\n\n\n\n\n\t\tEste texto se escribe en la
ventana\n\n\n");
ventana.add(texto1);
barra = new JScrollPane(texto1);
ventana.getContentPane().add(barra, BorderLayout.CENTER);
boton1 = new JButton("Este boton aparece arriba y permite cerrar
la ventana");
ventana.add(boton1, BorderLayout.NORTH);
boton1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ventana.dispose();} });
Explicación del código (1)

import java.text.*; // Este paquete tiene parte de las clases para formato de fecha y hora
import java.util.*; // Este paquete contien también clases para formato de fecha y hora
import java.awt.*; // Paquete con clases para el manejo de entorno gráfico
import java.awt.event.*; // Paquete con clases para el manejo y gestión de eventos
import javax.swing.*; //Java Swing contiene clases que permiten manejar entorno gráfico y eventos

public class EjemploVentanaTres extends JFrame{


static JFrame ventana= new JFrame();
/* Esta clase se deriva de la clase JFrame que se encuentra en javax.swing, posteriormente se crea el objeto
ventana para aplicar los métodos de JFrame, la variable ventana se define como estática para poderla aplicar
dentro de main(), ya que main() es un método estático */

public static void main(String args[]) {


JScrollPane barra; // Define una variable para crear el panel con las barras de desplazamiento
JButton boton1; // Define una variable para cerar un botón
ventana.setTitle("Ejemplo de una Ventana o Frame"); // Pone título a la ventana
ventana.setBackground(java.awt.Color.white); // Define el color de fondo de la ventana
ventana.setExtendedState(ICONIFIED); /* Inicializa la ventana minimizada (opción ICONIFIED), esto con
el fin de que al maximizarla posteriormente, se muestren en la ventana el botón y el área de texto con un
mensaje y el panel de barras de desplazamiento */
ventana.setSize(600,400); // Define el tamaño d ela ventana en pixeles
ventana.setVisible(true); // Inicializa la ventana para que esté visible desde el principio
ventana.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); /* Perfite definir la forma en que la
ventana se comportará al darle clic en el botón de cerrar, esto es, cierra la ventana */
ventana.setLayout(new BorderLayout()); /* Define el formato o Layout que se aplicará para
colocar los objetos en la ventana */
Explicación del código (2)

JTextArea texto1 = new JTextArea(400,200); /* JTextArea es una clase que permite definir y
manejar áreas de texto, en esta aplicación crea un área de texto de 400 x 200 pixeles, en ésta área de texto no
se puede escribir o editar texto desde el teclado, sin embargo si puede imprimirse texto desde el programa.
También permite colocar un panel con barras de desplazamiento */
texto1.setEditable(false); // Elimina la posibilidad de escribir texto desde el teclado en el área de texto
texto1.append("\n\n\n\n\n\n\n\n\t\tEste texto se escribe en la ventana\n\n\n"); /* Se le añade texto al área
de texto para imprimirlo posteriormente */
ventana.add(texto1); // Se inserta el área de texto en la ventana
barra = new JScrollPane(texto1); /* Se crea el objeto barra para aplicar las barras de
desplazamiento (horizontal y vertical) ,dentro de la ventana */
ventana.getContentPane().add(barra, BorderLayout.CENTER); /* Se añaden las barras de
desplazamiento a la ventana, se define una malla (Layout) en la ventana para colocarlas y se colocan en la
parte central de la ventana para lo cual se usa la opción BorderLayout.CENTER */
boton1 = new JButton("Este boton aparece arriba y permite cerrar la ventana"); // Crea el objeto boton1
ventana.add(boton1, BorderLayout.NORTH); /* Coloca el objeto boton1 en la parte superior de la
ventana, el botón se mostrará a todo lo ancho de la ventana de acuerdo al tamaño que ésta tenga. Para
colocar el botón en la parte superior se usa la opción BorderLayout.CENTER */
boton1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ventana.dispose();} }); /* Se anida la clase ActionListener dentro del método main(), esto se hace
para aplicar el método actionPerformed en el cual se definen las acciones que se deben llevar a cabo, cuando
se genera un evento sobre un determinado objeto, en este caso en particular se define la acción de cerrar la
ventana actual, al momento de hacer clic en el botón definido (boton1). Las clases anidadas son permitidas por
el lenguaje Java . Recordemos que el campo de acción de una clase anidada se limita a la clase que la
contiene. Esto es, si la clase B se define dentro de la clase A, entonces B es conocida dentro de A, pero no
fuera de A. Una clase anidada tiene acceso a los miembros, incluyendo miembros privados, de la clase en la
que está anidada. Sin embargo, la clase que la contiene no tiene acceso a los miembros de la clase anidada */
Explicación del código (3)

Date hoy = new Date(); // Define un objeto llamando a la clase Date para mostrar la fecha
String patron = "EEEE dd-MMM-yyyy, HH:mm:ss"; // Define el patrón para mostrar la fecha
SimpleDateFormat formato = new SimpleDateFormat(patron); // Define el formato a partir del patrón
String salida = formato.format(hoy); /* A través del objeto formato, guarda la fecha actual en una
variable de tipo cadena para imprimirla en la ventana */
Label mensaje=new Label("Esto aparece en la barra de estado: "+salida); /* Crea una etiqueta para
imprimir un mensaje y la fecha y hora en el formato especificado /*
ventana.add(mensaje, BorderLayout.SOUTH); /* Añade el mensaje en la parte inferior de la
ventana. Para colocar el mensaje en la parte inferior se usa la opción BorderLayout.SOUTH */
ventana.setExtendedState(NORMAL); /* Expande la ventana para mostrarla en el tamaño en el cual fue
definida, al crear la ventana se definió como ICONIFIED, por lo cual se mantuvo minimizada hasta que esta
parte del código la maximiza a su tamaño normal y permite mostrar el botón, el panel con las barras de
desplazamiento, el área de texto y la etiqueta con los mensajes */

// se agrega un verificador para que cierre la ventana con la |x| de la esquina superior derecha
ventana.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {System.exit(0);} });
} // termina main
} // termina clase
Finalmente el siguiente programa crea un menú de opciones para una
aplicación de operaciones con matrices, las opciones del menú principal y
de los submenús son:

Datos
Leer
Sumar
Multiplicar
Transponer
Salir

Archivo
Grabar
Lectura
Capturar
Mostrar

Ayuda
Indice
import java.awt.*; archivo.add(capturar); LOSE);
import java.awt.event.*; archivo.add(mostrar); Date hoy = new Date();
import java.util.*; ayuda.add(indice); String patron = "EEEE dd-MMM-yyyy, HH:mm:ss";
import java.text.*; barraMenu.add(datos); SimpleDateFormat formato = new
import javax.swing.*; barraMenu.add(archivo); SimpleDateFormat(patron);
barraMenu.setHelpMenu(ayuda); String salida = formato.format(hoy);
public class EjemploVentana2 extends JFrame { setMenuBar(barraMenu); Label mensaje=new Label("Selecciona una opción.
pack(); "+salida);
MenuItem leer = new MenuItem("Leer", new show(); ventana.setLayout(new BorderLayout());
MenuShortcut('L')); repaint(); ventana.add(mensaje, BorderLayout.SOUTH);
MenuItem sumar = new MenuItem("Sumar", new addWindowListener(new AplicacionVentana2 ()); } } // termina main
MenuShortcut('O')); void acciones() { } // Fin de la clase.
MenuItem restar = new MenuItem("Restar", new leer.addActionListener(new AplicacionVentana2());
MenuShortcut('C')); sumar.addActionListener(new AplicacionVentana2 // Archivo de librería con actionPerformed
MenuItem multiplicar = new MenuItem("Multiplicar", ()); import java.awt.*;
new MenuShortcut('B')); restar.addActionListener(new AplicacionVentana2 import java.awt.event.*;
MenuItem transponer = new MenuItem("Transponer", ()); import javax.swing.*;
new MenuShortcut('T')); multiplicar.addActionListener(new public class AplicacionVentana2 implements
MenuItem salir = new MenuItem("Salir", new AplicacionVentana2 ()); ActionListener, WindowListener {
MenuShortcut('S')); transponer.addActionListener(new
MenuItem grabar = new MenuItem("Grabar"); AplicacionVentana2 ()); public void actionPerformed (ActionEvent e) {
MenuItem lectura = new MenuItem("Lectura"); salir.addActionListener(new AplicacionVentana2 ()); if (e.getActionCommand().compareTo("Salir")==0)
MenuItem capturar = new MenuItem("Capturar"); grabar.addActionListener(new AplicacionVentana2 System.exit(0);
MenuItem mostrar = new MenuItem("Mostrar"); ()); if (e.getActionCommand().compareTo("Indice")==0)
MenuItem indice = new MenuItem("Indice"); lectura.addActionListener(new AplicacionVentana2 {
Menu datos = new Menu("Datos"); ()); JOptionPane.showMessageDialog(null,"Programa
Menu archivo = new Menu("Archivo"); capturar.addActionListener(new AplicacionVentana2 hecho por: Aquí ponga su
Menu ayuda = new Menu("Ayuda"); ()); Nombre.",null,JOptionPane.INFORMATION_MESSAG
MenuBar barraMenu = new MenuBar(); mostrar.addActionListener(new AplicacionVentana2 E); }
()); }
public EjemploVentana2 () { ayuda.addActionListener(new AplicacionVentana2
acciones(); ()); } public void windowClosing(WindowEvent we) {
datos.add(leer); System.exit(0); }
datos.add(sumar); public static void main(String args[]) { public void windowIconified(WindowEvent we) { }
datos.add(restar); EjemploVentana2 ventana = new EjemploVentana2 (); public void windowOpened(WindowEvent we) { }
datos.add(multiplicar); ventana.setTitle("Ejemplo de un Frame o Ventana"); public void windowClosed(WindowEvent we) { }
datos.add(transponer); ventana.setBackground(java.awt.Color.white); public void windowDeiconified(WindowEvent we) {
datos.addSeparator(); ventana.setExtendedState(NORMAL); }
datos.add(salir); ventana.setSize(600,400); public void windowActivated(WindowEvent we) { }
archivo.add(grabar); ventana.setVisible(true); public void windowDeactivated(WindowEvent we) {
archivo.add(lectura); }
archivo.addSeparator(); ventana.setDefaultCloseOperation(JFrame.EXIT_ON_C } // Fin de la clase

También podría gustarte