Download FUNDAMENTOS DE JAVA

Document related concepts
no text concepts found
Transcript
FUNDAMENTOS DE JAVA
FUNDAMENTOS DE JAVA
Un archivo fuente de Java, llamado oficialmente una unidad de compilación, es un archivo
de texto que contiene una o más definiciones de clase. El compilador de Java espera que estos
archivos se encuentre con una extensión.java. Cuando se compila el fuente, cada clase individual se
coloca en un archivo de salida propio con el nombre de la clase y con extensión.class. Dado que no
hay funciones ni variables globales en Java, lo único que puede haber en un archivo fuente de Java
es una o más definiciones de clase. Veremos a continuación un mini programa ejemplo, la forma de
compilarlo y ejecutarlo y lo analizaremos línea por línea. Posteriormente definiremos todos los
componentes que puede tener un programa en Java.
Primer programa
El programa que analizaremos es el siguiente:
public class HolaMundo {
public static void main (String args[]) {
System.out.println("Hola mundo!!!");
}
}
Este programa debe almacenarse en un archivo llamado HolaMundo.java ya que Java
requiere que todo el código resida dentro de una clase con nombre, debemos asegurarnos también
que se usen las mayúsculas y minúsculas de la misma manera tanto en el nombre de la clase en el
código fuente como en el nombre del archivo. Para compilar este código fuente se usa el programa
javac, tal como se muestra a continuación:
C:\jdk1.1.6>javac HolaMundo.java
El compilador genera un archivo objeto en bytecode, el cual como ya habíamos mencionado
es independiente del procesador usado. El nombre de este archivo es HolaMundo.class. Para
ejecutar este programa requerimos del intérprete del bytecode denominada java. Damos entonces el
siguiente comando:
D:\jdk1.1.6>java HolaMundo
Hola mundo!!!
Como puede ver, para ejecutar el programa no es necesario indicar la extensión del archivo
ya que se asume .class.
Analicemos ahora línea por línea este miniprograma:
Class HolaMundo {
Autor: M.C.C. Roberto Solís Robles
Página 1 de 50
FUNDAMENTOS DE JAVA
La primera línea utiliza la palabra reservada class para declarar que se va a definir una
nueva clase. HolaMundo es un identificador válido que se utiliza para dar nombre a la clase. La
definición completa de la clase está entre la llave de apertura "{" y la correspondiente llave de
cierre "}", lo cual es similar al uso que se tiene en C++.
public static void main (String args[]) {
La segunda línea del programa utiliza varias palabras reservadas que se definen a
continuación:
ƒ
public. Este es un especificador de acceso el cual indica que cualquier clase puede ver
el método main (principal). Existen otros especificadores los cuales veremos más
adelante en el curso.
ƒ
static. Esta palabra indica que el método o variable se aplican a toda la clase y no a una
sola instancia (objeto). Esto permite que se llame al método sin tener que referirse a una
instancia concreta de la clase. En el caso de main, es necesario que se declare static dado
que el intérprete la llama antes de que se cree cualquier instancia. Cabe hacer mención
que la palabra static hace que las variables sean estáticas (su espacio se aparta al
momento de compilar y no al estarse ejecutando).
ƒ
void. Esta palabra indica que el método no devuelve ningún valor.
ƒ
main. Este es el nombre del método. Java hace diferencia entre mayúsculas y
minúsculas, por lo cual es distinto el método main que el método Main. Las
implementaciones actuales de los intérpretes de Java buscan un método con este nombre
cuando se interpreta una clase para ejecutarla al inicio. Hay que hacer notar que aunque
el compilador de Java puede compilar clases sin método main, el intérprete no puede
ejecutar este tipo de clases, por lo cual se desplegaría un mensaje de error. Otra cosa
importante es que a un método se le pueden pasar parámetros, los cuales se indican
dentro de paréntesis como una lista de elementos que constan del tipo y del identificador
separados por coma (si no se requieren parámetros se ponen los paréntesis vacíos). En
este ejemplo solo existe un parámetro de tipo String denominado args, el cual es un
arreglo de instancias de la clase String (la cual almacena una cadena de caracteres), aquí
se almacenarían todas las cadenas que se pasan en la línea de comando al ejecutar el
programa (el primer índice es cero como en C).
System.out.println("Hola mundo!!!");
La tercera línea ejecuta el método println que está en out, la cual es una instancia de la clase
de OutputStream (flujo de salida) que se inicializa de manera estática en la clase System (sistema).
Este método imprime la cadena en la salida estándar y añade al final un carácter de nueva línea.
Las llaves de las siguientes líneas simplemente cierran el método main y la definición de la
clase respectivamente.
Autor: M.C.C. Roberto Solís Robles
Página 2 de 50
FUNDAMENTOS DE JAVA
Ahora empezaremos a ver los aspectos generales de la sintáxis en Java. Un programa en
Java es un conjunto de espacios en blanco, comentarios, palabras reservadas, identificadores,
literales, operadores y separadores.
Espacios en blanco
Java es libre de contexto, es decir, tiene una forma libre y se puede escribir de la manera en
que uno quiera. No es necesario indentar nada para que funcione correctamente. Por ejemplo, la
clase del programa anterior se pudo haber escrito en una sola línea como se muestra a continuación:
public class HolaMundo {public static void main (String args[]) { System.out.println("Hola
mundo!!!"); } }
O también se pudo haber escrito con cada palabra en una línea. Lo que importa es que por lo
menos exista un espacio en blanco, tabulador o nueva línea entre cada elemento que no esté ya
delimitado por un operador o separador.
Comentarios
Son textos que no influyen en la compilación del programa pero que son muy útiles para
explicar el funcionamiento del mismo por ejemplo.
Los comentarios tienen 3 posibles aspectos: de una sola línea, de múltiples líneas y
comentarios de documentación. Los comentarios de una sola línea comienzan con // y terminan al
final de la línea. Este estilo de comentario es útil para explicaciones breves.
Para comentarios más largos, puede crear comentarios de múltiples líneas comenzando con
un /* y terminando con un */. Cualquier cosa comprendida entre estos caracteres se considera como
comentario y el compilador lo ignora.
Una herramienta llamada javadoc (la cual genera archivos HTML) utiliza una forma
especial de comentario. Esta herramienta utiliza componentes del compilador de Java para generar
automáticamente documentación para la interfaz pública de una clase. El formato usado por
javadoc es que antes de las declaraciones de clase, métodos y variables públicas, se utilice un
comentario /** para indicar un comentario de documentación. Este comentario termina con un */
igual que en el anterior tipo de comentario. Javadoc reconoce varias variables especiales que van
precedidas por el signo @ dentro de estos comentarios.
Palabras Reservadas
Estas son identificadores especiales que Java ha reservado para controlar la definición de un
programa. Se utilizan para identificar los tipos, modificadores y mecanismos de control
incorporados. Existen 59 palabras reservadas (para la versión 1.0), las cuales en conjunto con los
operadores y separadores forman la definición del lenguaje Java. Las palabras reservadas son:
Autor: M.C.C. Roberto Solís Robles
Página 3 de 50
FUNDAMENTOS DE JAVA
abstract
case
const
else
float
if
int
null
protected
static
throw
var
boolean
cast
continue
extends
for
implements
interface
operator
public
super
throws
void
break
catch
default
false
future
import
long
outer
rest
switch
transient
volatile
byte
char
do
final
generic
inner
native
package
return
synchronized
true
while
byvalue
class
double
finally
goto
instanceof
new
private
short
this
try
Identificadores
Se utilizan para dar nombre a las clases, métodos y variables.Un identificador puede ser
cualquier secuencia de letras, dígitos, subrayados y el símbolo $. No debe comenzar con dígito.
Recuerde que hay diferencia entre mayúsculas y minúsculas.
Los desarrolladores de Java han seguido el convenio de nombrar todos los métodos y
variables de instancia públicos con una letra minúscula primero y marcada cada palabra que venga
a continuación con una letra mayúscula, como por ejemplo siguienteElemento y sumaTotal. Para
las variables locales y privadas, todos los identificadores están en minúsculas mezclados con
subrayados, por ejemplo importe_neto y valor_aux. Para variables final, las cuales representan
constantes, se utilizan solo mayúsculas, por ejemplo MAXIMO o MENSAJE.
Literales
Un valor constante en Java se crea utilizando una representación literal de él. Los enteros,
números en coma flotante (reales), booleanos, caracteres y cadenas se pueden poner en cualquier
lugar del código fuente de Java.
ƒ
Enteros
Son el tipo más utilizad en los programas típicos. Cualquier secuencia de dígitos es un
literal entero. Los enteros pueden expresarse en 3 bases: base 10, base 8 y base 16. Los enteros
decimales son por ejemplo: 78, 563 o 8712. Los enteros octales se caracterizan por iniciar con un 0,
así pues tendríamos a 056 y 0321 como ejemplos de octales. Por último tenemos los enteros
hexadecimales los cuales inician con 0x (o OX) seguidos de una secuencia de dígitos
hexadecimales, teniendo como ejemplos a 0x5f, 0XFE0 y 0xabac0. Los literales enteros crean un
valor int, que en Java es un valor de 32 bits. Si se quiere crear un valor mayor o menor de lo que se
puede representar con 32 bits, se necesita crear un valor long (de 64 bits) agregando al final del
literal una L o una l (L minúscula), por ejemplo, 0xf6432212acL.
Autor: M.C.C. Roberto Solís Robles
Página 4 de 50
FUNDAMENTOS DE JAVA
ƒ
Coma flotante
Son un valor decimal con una parte fraccional. Se pueden expresar en notación científica o
estándar. Por ejemplo, 3.1416 o 5.43 son literales en notación estándar (es decir, constan de una
parte entera y una fraccional separadas por un punto). La notación científica implica un número en
coma flotante en notación estándar con una notación adicional que implica una multiplicación por
diez elevado al exponente especificado. El exponente se indica mediante una E o e seguida de un
número decimal que puede ser positivo o negativo. Por ejemplo, 5.42e9 o 45.321e-2. Los números
en coma flotante son de tipo double por default (64 bits de almacenamiento) pero se puede forzar a
que se consideren float poniéndoles al final una F o f (solo requieren 32 bits pero tienen menor
capacidad y exactitud).
ƒ
Booleanos
Estos solo pueden tener uno de dos valores: true (verdadero) y false (falso). Sólo se pueden
asignar estos valores a variables declaradas como boolean o ser utilizadas en expresiones con
operadores booleanos.
ƒ
Caracter
Los caracteres en Java son índices en el conjunto de caracteres Unicode. Son valores de 16
bits que se pueden convertir a enteros y manipularse con los operadores de enteros, como la suma y
la resta. Un caracter literal se representa dentro de un par de comillas simples o apóstrofos (' ').
Todos los caracteres ASCII visibles se pueden introducir directamente dentro de las comillas, como
'a' o '$'. Para los caracteres que no se pueden introducir directamente, hay varias secuencias de
escape, que permiten introducir el carácter deseado, como '\'' para poder introducir el propio
apóstrofo y la '\n' para el carácter de nueva línea. También hay un mecanismo para introducir el
valor de un caracter en octal o hexadecimal. Para notación octal se utiliza la barra invertida seguida
del número de 3 dígitos. Para hexadecimal se introduce \u seguido de exactamente 4 dígitos
hexadecimales.
ƒ
Cadena
Son un texto arbitrario entre comillas (" "). Las cadenas de Java deben comenzar y terminar
en la misma línea. No hay ninguna secuencia de escape de continuación de línea como en otros
lenguajes tales como C.
Tipos de Datos
El tipo de datos determina la cantidad de memoria a ocupar, el rango de valores que se
pueden guardar así como las operaciones que se pueden realizar. En Java existen tipos de objetos
(los cuales surgen de la definición de clases), tipos simples y arreglos. Los tipo simples representan
Autor: M.C.C. Roberto Solís Robles
Página 5 de 50
FUNDAMENTOS DE JAVA
expresiones atómicas, de un solo valor, como números enteros, de coma flotante, caracteres y
valores booleanos. Ahora veremos estos tipos y los compuestos, tales como las clases, los
dejaremos para después. Estos tipos simples se pueden agrupar en 4 categorías:
1. Enteros
2. Coma flotante
3. Caracteres
4. Booleanos
Java es un lenguaje fuertemente tipeado de la misma manera en que lo es Pascal. Cada
expresión tiene un tipo así como cada variable tiene un tipo y cada tipo esta definido estrictamente.
En todas las asignaciones de expresiones a variables y en las llamadas a métodos se comprueba la
compatibilidad del tipo. No hay ninguna conversión automática entre tipos. Si no coinciden los
tipos el compilador genera errores que se deben de corregir para poder terminar de compilar la
clase.
ƒ
Enteros
Todos los tipos numéricos de Java tienen signo por lo cual no existe el modificador
unsigned como se da en C. Los tipos enteros se dan en la siguiente tabla:
Nombre
Cantidad de bits
Rango
63
63
long
64
-2 a 2 - 1
int
32
-231 a 231 - 1
short
16
-32768 a 32767
byte
8
-128 a 127
ƒ
Flotantes
Se utilizan para obtener resultados con fracciones decimales. Los tipos flotantes o reales son
los siguientes:
Nombre
Cantidad de bits
Rango
-308
double
64
1.7x10
a 1.7x10+308
-38
float
32
3.4x10 a 3.4x10+38
ƒ
Conversiones de tipos
En algunos tipos es posible almacenar un valor sin una conversión de tipos, a esto se le
llama conversión de tipos automática. En Java sólo es posible la conversión automática cuando el
compilador conoce que la variable destino tiene la precisión suficiente para contener el valor
origen. Esto sucede cuando se almacena una constante literal, o en algunas relaciones entre
subtipos, como almacenar un valor byte en una variable int.. A esto se le llama promoción, dado
que el tipo más pequeño se promociona o crece al tipo compatible más grande. Hay que notar que
esta promoción automática también se da en las expresiones (al tipo int), lo cual puede generar
errores en asignaciones. Se puede convertir entre estos tipos numéricos de manera explícita
anteponiendo entre paréntesis el tipo al que se quiere convertir a la expresión o variable deseada.
Autor: M.C.C. Roberto Solís Robles
Página 6 de 50
FUNDAMENTOS DE JAVA
ƒ
Caracteres
Dado que Java utiliza Unicode para representar los caracteres de una cadena, el tipo char es
de 16 bits sin signo y se utiliza para almacenar las decenas de miles de caracteres del conjunto de
caracteres Unicode completamente internacional (latín, griego, arábigo, cirílico, hebreo, etc.).
ƒ
Booleanos
Java usa el tipo boolean para representar los valores lógicos, los cuales pueden ser como ya
se menciono true o false.
Variables
La variable es la únidad básica de almacenamiento en un programa en Java. Una variable se
define mediante la combinación de un identificador, un tipo y un ámbito. Dependiendo de donde se
definan las variables, pueden ser locales o de instancia accesibles por todos los métodos de la clase.
Para declarar una variable se usa la siguiente sintaxis:
tipo identificador [= valor] [, identificador [=valor] ...] ;
Por ejemplo, se tienen las siguientes declaraciones:
int x = 20, y=30, n;
float pi=3.1416;
char caracter;
Enunciados (Sentencias)
Un enunciado es lo más sencillo que se puede hacer en Java, cada uno forma una sola
operación. Todos los enunciados deben terminar con punto y coma. Los enunciados pueden ser
simples tal como la asignación y compuestos (de bloque), los cuales están formados por varios
enunciados encerrados entre llaves.
ƒ
Asignación
La asignación se usa para dar un valor a una variable, lo cual se logra mediante el operador
de asignación =. La sintaxis general de una asignación es la siguiente:
variable = expresion;
Por ejemplo, se tienen las siguientes asignaciones donde se le da un valor de 15 a num y el
valor de 802.3 a producto:
num = 15;
producto = 802.3;
Autor: M.C.C. Roberto Solís Robles
Página 7 de 50
FUNDAMENTOS DE JAVA
Expresiones y Operadores
Una expresión es un conjunto de datos unidos por operadores.
Un operador toma uno o mas argumentos (operandos) y realiza una determinada acción con
ellos dando un resultado.
ƒ
Operadores Aritméticos
Se usan para operaciones matemáticas. Los operandos deben ser un tipo numérico. No se
pueden utilizar estos operadores con tipo boolean, pero se pueden utilizar con tipos char, dado que
este tipo es un subconjunto de int en Java.
Operador
Significado
Operador
Significado
+
Suma
+=
Suma y asignación
Resta
-=
Resta y asignación
*
Multiplicación
*=
Multiplicación y asignación
/
División
/=
División y asignación
%
Módulo
%=
Módulo y asignación
++
Incremento
-Decremento
ƒ
Operadores a nivel de bit
Los tipos numéricos enteros long, int, short y byte tienen un conjunto adicional de
operadores que pueden modificar e inspeccionar los bits que componen sus valores. Estos
operadores son los siguientes:
Operador
Significado
Operador
Significado
~
NOT a nivel de bit
&
AND a nivel bit
&=
AND y asignación
|
OR a nivel bit
|=
OR y asignación
^
XOR a nivel bit
^=
XOR y asignación
>>
Desplazamiento a la derecha
>>=
Desplazamiento a la derecha y
asignación
>>>
Desplazamiento a la derecha >>>=
Desplazamiento a la derecha
rellenando con ceros
rellenando con ceros y asignación
<<
Desplazamiento a la izquierda
<<=
Desplazamiento a la izquierda y
asignación
ƒ
Operadores Relacionales
Para comparar 2 valores, Java tiene el siguiente conjunto de operadores relacionales que
describen igualdad y ordenamiento.
Operador
Significado
==
Igual a
Autor: M.C.C. Roberto Solís Robles
Página 8 de 50
FUNDAMENTOS DE JAVA
!=
>
<
>=
<=
Diferente de
Mayor que
Menor que
Mayor o igual que
Menor o igual que
En Java, cualquier tipo se puede comparar utilizando == y != pero los restantes solo se
pueden usar con datos numéricos.
Cada uno de estos operadores devuelve como resultado un tipo boolean.
ƒ
Operadores lógicos booleanos
Estos operadores actúan únicamente sobre operandos boolean.
Operador
Significado
Operador
Significado
&
AND lógico
&=
AND y asignación
|
OR lógico
|=
OR y asignación
^
XOR lógico
^=
XOR y asignación
||
OR en cortocircuito
==
Igual a
&&
AND en cortocircuito
!=
Distinto de
!
NOT lógico
?:
If - then - else ternario
Es típico usar el ANDy OR en cortocircuito en todos los casos en que se utiliza lógica
booleana dejando las versiones de un único carácter exclusivamente para operaciones a nivel de bit.
ƒ
Precedencia de operadores
En una expresión las operaciones se dan en un determinado orden, el cual se obtiene a partir
de la precedencia que Java le da a cada uno de los operadores. La siguiente tabla muestra la
precedencia de la más alta a la más baja.
La más alta
()
[]
.
++
-~
!
*
/
%
+
>>
>>>
<<
>
>=
<
<=
==
!=
&
^
|
&&
||
Autor: M.C.C. Roberto Solís Robles
Página 9 de 50
FUNDAMENTOS DE JAVA
?:
=
La más baja
Op=
Los paréntesis al igual que en otros lenguajes se utilizan para indicar que se desea se haga
primero en una expresión.
MANEJO DE OBJETOS
Creación de nuevos objetos
Para poder utilizar objetos o instancias de una clase determinada lo primero que hay que
hacer es crearlo, es decir, obtener memoria para almacenar todos sus atributos y métodos. Para
hacer esto, se hace uso del operador new, al cual se le para el nombre de la clase de la cual se
quiere crear una instancia seguido de paréntesis. Por ejemplo, para crear una instancia de la clase
String se hace lo siguiente:
String cadena = new String();
Los paréntesis pueden estar vacíos, en cuyo caso se crea el objeto más simple, o bien, puede
contener parámetros que determinan los valores iniciales de las variables de instancia u otras
cualidades de ese objeto. El número y tipo de estos argumentos están definidos por la clase misma a
través de un método especial denominado constructor (el cual inicializa el objeto y sus variables),
que veremos más adelante.
El operador new lo que hace pues es crear la instancia de la clase (objeto), asignarle
memoria y ejecutar su método constructor.
Recordemos que Java se encarga de la administración de memoria, por lo cual si un objeto
creado deja de utilizarse automáticamente es eliminado.
El elemento básico de la POO en Java es una clase. Una clase define la forma y
comportamiento de un objeto. Cualquier concepto que desee representar en un programa en Java
está encapsulado en una clase. Para crear una clase sólo se necesita un archivo fuente que contenga
la palabra class seguida de un identificador válido y un par de llaves para el cuerpo de la misma.
Una clase es un modelo o patrón para un objeto. Una clase define la estructura de un objeto
y su interfaz funcional, conocida como métodos. Cuando se ejecuta un programa en Java, el sistema
utiliza definiciones de clase para crear instancias de las clases, que son los objetos reales. Los
términos instancia y objeto se utilizan de manera indistinta. La forma general de una definición de
clase
Autor: M.C.C. Roberto Solís Robles
Página 10 de 50
FUNDAMENTOS DE JAVA
Acceso y configuración de las variables de instancia y de clase
Antes que nada, hay que aclarar la diferencia entre variables locales, variables de instancia y
variables de clase. Una variable local es aquella que tiene un alcance limitado, es decir, solo
permanece activa durante la ejecución de las sentencias que se encuentran entre las llaves en la que
se declaró (dentro de un método o estructura de control), por ejemplo, en el siguiente fragmento se
puede ver una variable local num, que solo durante la ejecución de la sentencia if:
if (suma>0)
{ int num;
num=20;
}
Una variable de instancia es aquella que existe por cada objeto (instancia de clase) creada y
que es diferente de la de los otros objetos de la misma clase, se declara fuera de cualquier método
de la clase. Por ejemplo, en la siguiente clase se encuentra la variable de instancia x, la cual existe 3
veces, una en el objeto O1, otra en el objeto O2 y otra en el objeto O3:
class Prueba {
int x;
static int n;
};
Prueba O1=new Prueba(), O2=new Prueba(), O3=new Prueba();
Una variable de clase es algo similar a la de instancia con la diferencia de que solo existe
una por la clase independientemente de cuantos objetos o instancias se crearon de la misma. En el
ejemplo anterior a pesar de que se crearon 3 objetos, solo existe en memoria una variable n. Se
puede notar que para indicar que es variable de clase a la declaración se le antepone el modificar
static.
Una vez establecida la diferencia, veamos como se puede accesar una variable de instancia
de o de clase. Para ello se utiliza el operador punto (.), el cual tendrá 2 operandos, del lado
izquierdo estará el nombre de un objeto o clase y del lado derecho el nombre de la variable a
accesar, así pues, para hacer referencia a la variable x del objeto O1 se usa la siguiente notación:
O1.x
Para hacer referencia a una variable de instancia es necesario primero crear una instancia de
la clase (objeto), mientras que para hacer referencia a una variable de clase no se requiere tener
ningún objeto creado de la misma. Así, si los objetos O1, O2 y O3 no hubieran sido creados, se
podría de todos modos tener acceso a la variable de clase n mediante la siguiente notación:
Prueba.n
Autor: M.C.C. Roberto Solís Robles
Página 11 de 50
FUNDAMENTOS DE JAVA
Llamado a los métodos
Para llamar a un método de un objeto o clase, se usa una notación similar a la utilizada para
accesar a las variables. Usando el operador punto se pone el nombre del objeto o clase y el nombre
del método seguido de los parámetros a pasarle entre paréntesis (los cuales son obligatorios aun y
cuando no existan parámetros). Por ejemplo, si la clase Prueba tiene un método denominado suma
y requiere de 2 parámetros enteros, para llamarlo se haría lo siguiente:
Prueba O;
...
O.suma(10, 6);
Si al momento de declarar el método se le antepuso la palabra static se logra lo mismo que
con las variables, es decir, se puede llamar al mismo sin necesidad de tener un objeto creado para la
clase (método de clase) y para llamarlo se pondría del lado izquierdo el nombre de la clase:
Prueba.suma(10, 3);
Referencias a objetos
Al trabajar con objetos, algo importante que sucede sin nosotros darnos cuenta es el uso de
referencias (direcciones de memoria) a dichos objetos. Cuando se asignan objetos a las variables, o
los pasa como parámetros a los métodos, se trasladan las referencias a los mismos y no los objetos
mismos o una copia de ellos.
El siguiente ejemplo permite verlo con mayor claridad.
import java.awt.Point;
class PruebaReferencias {
public static void main (String args[]) {
Point pt1, pt2;
pt1=new Point(100,100);
pt2=pt1;
pt1.x = 200:
pt1.y = 200;
System.out.println("Punto 1: "+pt1.x+", "+pt1.y);
System.out.println("Punto 2: "+pt2.x+", "+pt2.y);
}
}
Si corre este programa verificará que tanto pt1 como pt2 tienen los mismos datos, esto se
debe a que cuando se asigna a pt2 el valor de pt1 en realidad lo que se hace es que ambos esten
referenciando al mismo objeto (la misma dirección de memoria). Por lo tanto, si se cambia pt1
también se está cambiando pt2.
Autor: M.C.C. Roberto Solís Robles
Página 12 de 50
FUNDAMENTOS DE JAVA
Este manejo de las referencias hace también que las comparaciones entre objetos tengan
resultados que dependen de si se trata de exactamente el mismo objeto.
Para ejemplificar esto, analice el siguiente programa:
class PruebaIgualdad{
public static void main (String args[]) {
String str1, str2;
str1 = "Especialidad en Computacion.";
str2 = str1;
System.out.println("String1: " + str1);
System.out.println("String2: " + str2);
System.out.println("Mismo objeto? " + (str1 == str2));
str2 = new String(str1);
System.out.println("String1: " + str1);
System.out.println("String2: " + str2);
System.out.println("Mismo objeto? " + (str1 == str2));
System.out.println("Mismo valor? " + str1.equals(str2));
}
Al correr este programa se puede ver que en la primera igualdad nos da un valor verdadero
pues tanto str1 como str2 estan referenciando al mismo objeto mientras que en la segunda ya la
referencia es a objetos distintos por lo cual obtenemos un valor verdadero aún y cuando los valores
que contiene son los mismos.
Determinación de la clase de objeto
Para determinar la clase de un objeto se puede hacer lo siguiente:
String nombre = obj.getClass().getName();
El método getClass() está definido en la clase Object, y como tal esta disponible para todos
los objetos. El resultado de ese método es un objeto Class, el cual posee un método llamado
getName() que regresa una cadena representando el nombre de la clase.
Otra prueba que podría serle útil es el operador instanceof, el cual tiene 2 operandos: un
objeto a la izquierda y el nombre de una clase a la derecha. La expresión regresa true o false con
base en si el objeto es una instancia de la clase nombrada o se trata de cualesquiera de las subclases
de esa clase.Por ejemplo:
O2 instanceof Prueba
Autor: M.C.C. Roberto Solís Robles
---> Regresa true
Página 13 de 50
FUNDAMENTOS DE JAVA
Biblioteca de clases
La biblioteca de clases de Java ofrece el conjunto de clases disponibles garantizadas en
cualaquier ambiente Java (por ejemplo Netscape o Internet Explorer). Estas clases se encuentran en
el paquete java (por ejemplo la que usamos en el programa para probar las referencias).
El JDK viene con la documentación para toda la biblioteca de clases de Java e incluye
descripciones de las variables de instancia, métodos y constructores de cada clase.
Los paquetes que forman parte de la biblioteca de clases de Java son:
ƒ
java.lang: Clases que se aplican al lenguaje mismo, entre las cuales se incluye la
clase Object, la clase String y la clase System. También contiene las clases
especiales para los tipos primitivos (Integer, Character, Float, etc).
ƒ
java.util: Clases de utilería como Date y también clases de colección de datos
como Vector.
ƒ
java.io: Clases de entrada y salida para escribir y leer desde flujos y para
manejar archivos.
ƒ
java. net: Clases para soporte de red.
ƒ
java.awt: Clases para implantar una interfaz gráfica de usuario y procesar
imágenes.
ƒ
java.applet: Clases para implantar applets de Java.
ARREGLOS, CONDICIONALES Y CICLOS
Arreglos
Los arreglos en Java son diferentes con respecto a los otros lenguajes pues son objetos que
pueden pasarse y tratarse de la misma manera que otros objetos.
ƒ
Declaración
Un arreglo es un grupo de variables del mismo tipo a la que nos referimos con el mismo
nombre. Para declarar un arreglo se usa la siguiente declaración:
tipo nombre[];
Autor: M.C.C. Roberto Solís Robles
Página 14 de 50
FUNDAMENTOS DE JAVA
Para los arreglos hay un valor especial llamado null, que representa un arreglo sin ningún
valor. Para dar un valor al arreglo se usa el operador new, el cual asigna el espacio del mismo. Para
utilizarlo se debe proporcionar un tipo y un número entero positivo de elementos a asignar. Por
ejemplo, para asignar diez flotantes a un arreglo tipo float se hace lo siguiente:
float a[];
a = new float [12];
Otra posibilidad de asignar espacio al arreglo es al momento de declararlo dar sus valores
iniciales, por ejemplo:
String colores[] = { "Rojo" , "Verde", "Azul", "Amarillo"};
Aquí se crea un arreglo de 4 elementos String.
ƒ
Acceso
Para acceder a un elemento del arreglo se pone el nombre del arreglo y entre corchetes la
posición deseada (la primera es la cero al igual que en C). Hay que hacer notar que Java no permite
acceder a una localidad que no existe, por ejemplo si se declaro un arreglo de tamaño 10 y se quiere
acceder a la posición 15, esto generaría un error, el cual sería de compilación o ejecución según sea
la causa.
Para evitar que en tiempo de ejecución se generen estos tipos de errores se puede obtener la
longitud del arreglo (número de elementos) accesando la variable length del arreglo (recuerde que
un arreglo es un objeto). Por ejemplo, si se tiene la siguiente declaración:
String A[];
En el programa se puede saber en cualquier momento el tamaño del mismo haciendo
referencia a:
A.length
ƒ
Cambio de los elementos
Para asignar un valor a una casilla del arreglo en particular, se usa la sentencia de
asignación después de la expresión de acceso al arreglo:
A[0]="beto";
A[29]="UAZ";
A[15]=Dato[10];
Hay que tener en cuenta que como un arreglo de objetos en Java consiste de referencias a
dichos objetos de tal forma que cuando se asigna un valor a una posición del mismo, se crea una
referencia al objeto por lo que en la última asignación lo que sucede es que se asigna la referencia,
no se copia el valor de Dato[10] a A[15]; dicho de otra manera, si cambia A[15] cambia Dato[10] o
viceversa.
Autor: M.C.C. Roberto Solís Robles
Página 15 de 50
FUNDAMENTOS DE JAVA
ƒ
Arreglos multidimensionales
Para declarar arreglos multidimensionales se hace algo similar, por ejemplo para declarar un
arreglo bidimensional de 10 x 4 (10 renglones y 4 columnas en caso de verlo como si fuera una
tabla) se hace lo siguiente:
float m[][]=new float[10][4];
Condicionales if
El if permite tomar una decisión para determinar si ejecuta una parte del código o ejecuta
otra en base a una simple prueba. La sintaxis es la siguiente:
if (expresion_logica)
sentencia1;
[ else
sentencia2; ]
Si la expresion lógica entre paréntesis es verdadera se ejecuta la sentencia inmediatamente
después de los paréntesis (sentencia1) , en caso contrario se ejecuta la sentencia del else
(sentencia2), en caso de que se encuentre, pues la claúsula else es opcional.
Condicional switch
Esta condicional permite seleccionar de entre varias alternativas en base al valor de una
expresión. La sintaxis es la siguiente:
switch (expresion) {
case valor1 : sentencias;
case valor2: sentencias;
....
[ default: sentencias; ]
}
Lo que hace el switch es evaluar la expresión y el resultado compararlo con cada uno de los
valores puestos con la palabra reservada case, si resulta igual a alguno de ellos comienza a ejecutar
las sentencias que están a continuación del valor. La claúsula default es opcional y si se pone las
sentencias que tiene se ejecutan solo si la expresión tiene un valor distinto a los valores puestos en
el switch. Hay que hacer mención que al igual que en el C, si no se pone la palabra reservada break
al final de las sentencias que se quieren ejecutar por cada valor, la ejecución continuará hasta
encontrar un break o finalizar el case. break lo que hace es terminar la ejecución del case y
continuar con las sentencias que estén después del mismo.
Autor: M.C.C. Roberto Solís Robles
Página 16 de 50
FUNDAMENTOS DE JAVA
También hay que aclarar que la expresión y valores sólo pueden ser enteros (a
excepción del tipo long) o carácter.
Ciclo for
Permite la repetición de una sentencia o de un conjunto (bloque) de las mismas mientras una
condición se cumple. Su sintaxis es la siguiente:
for (inicializacion; condición; incremento)
sentencia;
Analicemos cada una de las 3 partes entre paréntesis:
ƒ
Inicialización. Es una expresión que inicializa el principio del ciclo. Las
variables que se declaran en esta parte son locales al ciclo.
ƒ
Condición. Es la prueba (expresión lógica) que ocurre al final de cada vuelta del
ciclo. Si la condición dada se cumple (la expresión es verdadera) el ciclo sigue,
de otra manera termina la ejecución del ciclo.
ƒ
Incremento. Es una expresión o llamada a función o método. Por lo general,
esta parte se utiliza para cambiar el valor del índice del ciclo a fin de acercar el
estado del ciclo a su terminación.
La sentencia se ejecuta cada vez que se entra al ciclo. Esta puede estar vacía si solo
se requiere ejecutar la parte entre paréntesis.
Ciclo while
Se utiliza para repetir una sentencia o conjunto de las mismas mientras una determinada
condición se cumpla. La sintaxis es la siguiente:
while (condición)
sentencia;
La condición es una expresión booleana. Si esta es verdadera, el ciclo continúa, de otra
manera termina la ejecución del ciclo. Esto hace que si la condición es falsa desde el principio la
sentencia del ciclo no se ejecute nunca.
Ciclo do .. while
Este ciclo es similar al anterior, solo que primero se ejecutan las sentencias y posteriormente
la condición de tal forma que las sentencias se ejecutan por lo menos una vez. La sintaxis es la
siguiente:
Autor: M.C.C. Roberto Solís Robles
Página 17 de 50
FUNDAMENTOS DE JAVA
do {
sentencias;
} while (condicion);
La ejecución termina una vez que la condición es falsa.
Como salir de los ciclos
Para salir de los ciclos se pueden usar las sentencias break y continue.
La sentencia break hace que el ciclo termine su ejecución (si es que esta dentro de uno). Por
otro lado, la sentencia continue hace que el ciclo continue, pero en la siguiente vuelta, es decir, si la
sentencia continue esta a la mitad de las sentencias del ciclo, las que restan para terminar esa vuelta
del ciclo se omiten y se vuelve a la primera que contenga el mismo (otra vuelta). En el caso del for
se ejecuta primero la parte de incremento.
CREACION DE CLASES Y APLICACIONES EN JAVA
Definición de clases
Para definir una clase se usa la sintaxis:
class nombre {
....
}
Si la clase es una subclase de otra, se utiliza la palabra extends para indicar cual es su
superclase:
class nombre extend nombresuperclase {
....
}
Definición de variables de instancia
La definición de una variable de instancia es como la de cualquier variable pero se realiza
fuera de la definición de cualquier método. Generalmente se definen todas las variables de esta
categoría después de la primera línea de la definición de clase. Ejemplo:
class nueva {
int n;
char c;
// Estas son variables de instancia
Autor: M.C.C. Roberto Solís Robles
Página 18 de 50
FUNDAMENTOS DE JAVA
....
}
Estas variables se denominan de instancia porque como ya lo mencionamos existe una por
cada instancia de la clase (objeto) que se cree, y son accesibles por cualquier método de la clase.
Constantes
Las variables de instancia o de clase pueden ser constantes, es decir, que una vez asignado
su valor, no pueda ser modificado durante la ejecución del programa. Para indicar que una variable
va a ser constante se le antepone a su declaración la palabra reservada final. Ejemplos:
final float PI = 3.1416;
final int NUM = 134;
Definición de variables de clase
Como ya habíamos mencionado, una variable de clase es aquella que existe
independientemente de que se hayan creado o no objeto de la clase y que es compartida entre todos,
es decir, si un objeto la cambia, los otros objetos de esa clase se dan cuenta de ese cambio. Para
definir una variable de clase se hace lo mismo que para las variables de instancia pero se le
antepone a la declaración la palabra static. Ejemplos:
class nueva {
int n;
char c; // Estas son variables de instancia
static int x; // Esta es una variable de clase
....
}
Creación de métodos
La definición de un método dentro de una clase consta de 5 partes:
1. Un modificador que indica el tipo de acceso al método
2. El nombre del método
3. El tipo de objeto o tipo simple que regresa
4. Una lista de parámetros
5. El cuerpo del método
En Java se maneja un término denominado identificación del método, el cual consiste del
nombre del método, el tipo de objeto o simple regresado y la lista de parámetros.
Autor: M.C.C. Roberto Solís Robles
Página 19 de 50
FUNDAMENTOS DE JAVA
En otros lenguajes, el nombre del método es suficiente para distinguirlo de otros métodos
del programa. En Java, puede tener diferentes métodos con el mismo nombre, pero con un tipo de
retorno o lista de parámetros distinta. A esto se le llama sobrecarga de métodos (polimorfismo).
La sintaxis de la definición de un método es pues:
modificador tipo nombre (tipo par1, tipo par2, tipo par3, ... ) {
...
}
El modificador indica si el método puede accesarse solo desde la clase o desde otras clases
(por default es public, accesible por todos); estos los veremos más adelante. El tipo indica que es lo
que va a regresar el método al terminar su ejecución (int, short, etc.). Si regresa un arreglo, este se
indica poniendo el nombre del tipo del arreglo seguido de corchetes vacíos:
int[] ordenado (int n) {
...
}
Si no se desea regresar ningún valor el tipo se especifica como void.
La lista de parámetros va entre paréntesis después del nombre del método, estos van
separados por coma y se indica tanto el tipo como el nombre de cada uno separados por espacio.
El cuerpo del método lo conforman todas las sentencias necesarias para que el método
realice su trabajo y estas van entre las llaves que aparecen después de la lista de parámetros.
La palabra reservada this
Esta palabra se utiliza cuando en la definición de un método se quiera referir al objeto actual
para poder utilizar sus variables de instancia o bien, para poder pasar el objeto actual como
parámetro a otro método. A continuación se muestran ejemplos de esto:
T = this.x;
// Se asigna la variable de instancia x del objeto actual
this.limpia(); // Se llama al método limpia del objeto actual
return this;
// Para retornar el objeto actual
En muchos casos se puede sin embargo omitir el uso de la palabra this. Para referirse a las
variables de instancia o métodos de la clase actual se puede usar sólo el nombre pues this esta
ímplicito en estas referencias:
T = x;
limpia();
// Se asigna la variable de instancia x del objeto actual
// Se llama al método limpia del objeto actual
Hay que hacer notar que si por ejemplo existe una variable local x desde donde se hace el
primer acceso de ejemplo, es necesario el uso de la palabra this para poder acceder a la variable de
instancia, de otra manera, se accesa la variable local.
Autor: M.C.C. Roberto Solís Robles
Página 20 de 50
FUNDAMENTOS DE JAVA
También hay que aclarar que la palabra this se usa para las variables de instancia mas no
para las variables de clase.
Métodos de clase
Así como existen variables de instancia y de clase, existen métodos de instancia y de clase y
la diferencia entre estos 2 tipos es análoga. Los métodos de clase están disponible para cualquier
instancia de la clase así como en otras clases. En consecuencia, algunos métodos se usan en
cualquier lugar, sin importar si una instancia de la clase existe o no.
Por ejemplo, las biblotecas de clase de Java incluyen una clase llamada Math, la cual define
un conjunto completo de operaciones matemáticas que puede usarse en cualquier programa:
float raiz=Math.sqrt(26.7);
Para definir métodos de clase se emplea la palabra reservada static antes de definir el tipo
de resultado que va a regresar el método:
static char upcase (char c) { ... }
Si los métodos van a ofrecer una utilidad general que no afecten de manera directa a una
instancia de la clase, lo mejor es definirlos como métodos de clase. De otra manera, los métodos
son de instancia, que de hecho son la mayoría.
Creación de aplicaciones
Una aplicación Java consiste de una o mas clases. HotJava (un navegador de Web) es un
ejemplo de una aplicación Java. Lo único que se necesita para ejecutar una aplicación Java es una
clase que funcione como punto "de arranque" para el resto del programa Java. Si el programa es
pequeño, solo se necesita esa clase.
La clase de arranque requiere de un método main(). Cuando se ejecuta la clase, el método
main() es lo primero que se llama.
La identificación para el método main() siempre tendrá la siguiente apariencia:
public static void main (String args []) { ... }
Las partes de esta identificación ya habían sido revisadas con anterioridad.
Lo único que resta decir es que args es un arreglo de cadenas de caracters las cuales
contiene los parámetros de la línea de comando; es decir, si al ejecutar el programa se le pusieron
parámetros estos quedan en cada una de las posiciones de args. Por ejemplo, si hace lo siguiente:
C:\jdk1.1.6>java Programa Juan sin miedo
En la clase Programa el método main puede accesar a los parámetros (Juan sin miedo) a
través del arreglo args quedando de la siguiente manera:
args[0]="Juan"
args[1]="sin"
args[2]="miedo"
Autor: M.C.C. Roberto Solís Robles
Página 21 de 50
FUNDAMENTOS DE JAVA
Polimorfismo
El lenguaje Java permite que se tengan varios métodos con el mismo nombre pero con
distintos parámetros, a esto se le denomina polimorfismo (o sobrecarga de métodos). Este
polimorfismo permite a las instancias de clase tener una interfaz más sencilla para otros objetos (no
hay necesidad de métodos por completo diferentes que realizan en esencia lo mismo) y comportarse
en forma distinta en base a la entrada dada al método.
Cuando se llama a un método Java hace coincidir el nombre, número y tipo de parámetros
para seleccionar la definición del método a ejecutar.
Para crear un método sobrecargado (polimorfico) todo lo que se necesita es crear varias
definiciones distintas de método en su clase, todas con el mismo nombre, pero con diferente lista de
parámetros (ya sea en número o en tipo). Hay que hacer notar que el tipo que devuelve el método
no se toma en cuenta para diferenciar los métodos sobrecargados.
Métodos constructores
Un método constructor es una clase especial que determina como se inicializa un objeto
cuando se crea.
A diferencia de los métodos ordinarios, no puede llamar a un método constructor en forma
directa; en su lugar, Java los llama de manera automática; de este modo, cuando se usa new para
crear una nueva instancia de una clase, Java realiza tres acciones:
1. Asignar memoria para el objeto
2. Inicializa las variables de instancia del objeto, ya sea con sus valores iniciales o por el
valor predeterminado (0 para números, null para objetos, false para booleanos ,'\0' para
los caracteres).
3. Llama al método constructor de la case (puede ser uno de varios)
Si la clase no cuenta con algún método constructor especial definido, aún así se obtiene un
objeto pero se requerirá de inicializar las variables explícitamente o llamando a algún método que
el objeto necesita para ello.
Al definir los métodos constructores en una clase, se pueden configurar valores iniciales de
las variables de instancia, llamar métodos basados en esas variables o llamar métodos de otros
objetos, o bien calcular propiedades iniciales de su objeto. También es factible que se tengan
métodos constructores sobrecargados.
Los constructores son muy parecidos a los métodos ordinarios, con 2 diferencias básicas:
1. Siempre tienen el mismo nombre de la clase
2. No tienen un tipo de retorno
Algunos constructores podrían ser un conjunto más amplio de otro constructor definido en
su clase; es decir, puede tener el mismo comportamiento y un poco más. En lugar de duplicar su
Autor: M.C.C. Roberto Solís Robles
Página 22 de 50
FUNDAMENTOS DE JAVA
comportamiento idéntico en múltiples métodos constructores de su clase, tiene sentido estar
habilitado para sólo llamar al primer constructor desde dentro del cuerpo del segundo. Java ofrece
una sintaxis especial para hacer esto. Así, para llamar a un constructor definido en la clase actual,
se emplea la forma:
this(par1, par2, par3, ...)
Métodos sobrepuestos
Cuando se llama a un método en un objeto, Java busca su definición en la clase de ese
objeto y si no la encuentra, pasa la llamada hacia una jerarquía mayor hasta encontrar una
definición del mismo. La herencia permite definir y utilizar métodos de forma repetida en las
subclases sin tener que duplicar el código. Sin embargo, habrá ocasiones en que desee que un
objeto responda a los mismos métodos, pero que tenga diferente comportamiento cuando llame a
un método. En este caso, se puede sobreponer. Esto implica definir un método en una subclase que
tiene la misma identificación de otro en una superclase. Entonces, cuando se llama al método, el de
la subclase se busca y se ejecuta, en lugar del que está en la superclase.
Para sobreponer un método, todo lo que tiene que hacer es crear uno en su subclase que
tenga la misma identificación (nombre, número y tipo de parámetros) de otro definido en una de
sus superclases. Puesto que Java ejecuta la primera definición del método que encuentra que
coincida con la identificación, esto en forma eficiente "oculta" la definición del original.
En ocasiones, se requerirá de llamar al método original, para ello, dentro de la definición del
método, se utiliza la palabra reservada super para pasar la llamada al método hacia una jerarquía
superior. Por ejemplo, si en una subclase se sobrepuso el método Imprime y se quiere llamar al
original desde el método sobrepuesto, la llamada sería:
super.Imprime()
Si lo que se sobrepone es un constructor (que en términos técnicos no se puede pues debe
llamarse como la clase), entonces para llamar al constructor de la superclase se usa la sintaxis:
super(par1, par2, ...)
Métodos de finalización
Los métodos de finalización son lo contrario de los métodos constructores; mientras que un
método constructor se utiliza para inicializar a un objeto, estos métodos de finalización se llaman
justo antes de que sea recolectado como basura y se reclame su memoria.
El método de finalizar es sólo finalize(). La clase Object define un método de finalización,
el cual no realiza nada. Para crear uno para una clase determinada, se sobrepone y se usa la
identificación:
void finalize() {
...
}
Autor: M.C.C. Roberto Solís Robles
Página 23 de 50
FUNDAMENTOS DE JAVA
Dentro del cuerpo se incluye cualquier limpieza que desee realizar para ese objeto. Estos
métodos se utilizan casi siempre para optimizar la eliminación de un objeto, por ejemplo, al
eliminar las referencias a otros objetos, al liberar recursos externos que han adquirido o para otros
comportamientos que puedan facilitar la eliminación del objeto.
Autor: M.C.C. Roberto Solís Robles
Página 24 de 50
FUNDAMENTOS DE JAVA
Manejo de Cadenas
Una cadena es una secuencia de caracteres. Las cadenas son una parte fundamental de la
mayoría de los programas; incluso los programas gráficos necesitan manipular habitualmente
cadenas de texto para los nombres de archivo y otros objetos con nombre. Debido a este gran uso
de las cadenas, Java tiene varias características incorporadas que facilitan la manipulación de
cadenas. Java tiene una clase incorporada en el paquete java.lang que encapsula la estructura de
datos de una cadena. Esta clase se denomina String.
Constructores
Como con todas las otras clases, se pueden crear instancias de String con el operador new.
Para crear un String vacío, se puede llamar al constructor por defecto sin parámetros:
String cad = new String();
Para crear un String inicializado con caracteres, hay que pasarle una matriz de char al
constructor, como se muestra a continuación:
char c[]={'a','c','a','b','a'};
String cad = new String(c);
También existe un constructor alterno en el cual se puede especificar el índice de comienzo
y el número de caracteres a utilizar. Por ejemplo en el siguiente código:
char c[]={'a','c','a','b','a'};
String cad = new String(c,2,3);
en cad queda "aba".
Creación de cadenas
Dado que los Strings son valores constantes, Java permite que entre cadenas se especifique
la cadena entre comillas, tal como se había mencionado antes y se puede inicializar como sigue:
String cad = "acaba";
Uno de los métodos mas usados de la clase String es length(), el cual devuelve la longitud
en caracteres de la cadena (No confundir con la variable de instancia length de los arreglos).
Hay que notar que como Java crea un objeto String cada vez que se tiene una constante
literal de cadena entonces se puede llamar al método length directamente como en el siguiente
ejemplo:
"UAZ".length();
Autor: M.C.C. Roberto Solís Robles
Página 25 de 50
FUNDAMENTOS DE JAVA
Concatenación de cadenas
Para concatenar 2 o más cadenas se utiliza el operador + de la siguiente manera:
"Hola" + " UAZ "+"Inge"
esto da como resultado un String igual a "Hola UAZ Inge".
NOTA: En realidad cuando se usa el operador + con los Strings se está llamando al método
append, el cual se encarga de agregar al String lo indicado después del +.
Conversión de cadenas
Debido a que el método append tiene una versión para cada tipo simple que existe entonces
se puede hacer por ejemplo lo siguiente:
"Cadenita " + 78 + 3.782
Lo que da como resultado "Cadenita 783.782".
Para lograr esto el método append llama a un método de clase de String denominado
valueOf para construir la representación típica de una cadena. Para tipos simples, valueOf crea
simplemente una representación de cada int o float. Para objetos, valueOf llama al método toString
con ese objeto. Cada clase implementa toString, con una implementación por defecto que se
encuentra en la clase Object. Es bueno sobreponer el método toString y presentar una versión
propia de cadena para las clases.
Extracción de caracteres
Para extraer un carácter de una cadena, se puede referir al caracter indexado mediante el
método charAt pasandole como parámetro el índice deseado. No se debe llamar a este método con
un índice menor de cero o mayor de la longitud de la cadena. Si se necesita extraer más de un
carácter a la vez, puede utilizar el método getChars, al cual hay que pasarle el índice desde el cual
se quieren tomar los caracteres y el del último caracter deseado (+1).
También existe una función útil llamada toCharArray que devuelve una matriz de char que
contiene la cadena completa o bien, se puede usar el método getBytes el cual coloca los caracteres
en una matriz de bytes, descartando el byte más significativo.
Comparación de cadenas
Para ver si 2 cadenas son iguales se utiliza el método equals de String. Este devuelve true si
el parámetro está compuesto por los mismos caracteres que el objeto que llama al método.
String s1="Hola", s2="Hola";
s1.equals(s2); // Esto devuelve true
Autor: M.C.C. Roberto Solís Robles
Página 26 de 50
FUNDAMENTOS DE JAVA
Una forma alternativa es el método equalsIgnoreCase, el cual ignora si los caracteres son
mayúsculas o minúsculas, es decir, las considera iguales.
El método regionMatches se utiliza para comparar una región específica que es parte de una
cadena con otra región de otra cadena. Hay una opción para que las mayúsculas y minúsculas se
consideren iguales. A continuación se muestran los prototipos de ambas:
boolean regionMatches(int desp, String otra, int odesp, int longitud);
boolean regionMatches(boolean ignorar, int desp, String otra, int odesp, int longitud);
El parámetro ignorar se pone en true si se desea ignorar si las letras son mayúsculas o
minúsculas, el parametro offset indica desde que posición en la cadena que llama al método se va a
tomar, el parámetro otra es la cadena con la que se va a comparar, el parámetro odesp indica desde
que caracter se va a tomar en la otra cadena y por último, el parámetro longitud indica de cuantos
caracteres es la región a comparar.
Otro método es startsWith, el cual comprueba si la cadena que manda llamar al método
comienza con la cadena que se pasa como parámetro.
Hay que notar que equals y el operador == hacen cosas muy distintas pues mientras el
primero compara el contenido caracter a caracter, el segundo determina si ambas hacer referencia al
mismo objeto.
Para hacer comparaciones que no sean de igualdad se usa el método compareTo el cual
compara la cadena que llama al método con la cadena pasada como parámetro y devuelve 0 si son
iguales, un número entero negativo si es menor la primera y un número entero positivo si la primera
es mayor.
Búsqueda
La clase String proporciona los métodos indexOf y lastIndexOf, los cuales reciben como
parámetro un caracter o una cadena y devuelven el índice de la primera y última aparición,
respectivamente, de lo que se paso como parámetro dentro de la cadena que llama al método. Si no
tienen éxito, devuelven -1.
O bien, si se le pueden dar 2 parámetros a ambos métodos, en cuyo caso el significado del
primer método es el índice de la primera aparición del caracter o cadena desde el índice dado como
segundo parámetro; y en el caso del segundo método de la última aparición antes del índice dado.
Algunos otros métodos son:
substring
Este obtiene una copia de una subcadena de la cadena que llama al método, se le puede
pasar un solo parámetro en cuyo caso indica el índice de inicio de la subcadena o 2 números que
indicarían el índice de inicio de la subcadena y el índice final.
concat
Autor: M.C.C. Roberto Solís Robles
Página 27 de 50
FUNDAMENTOS DE JAVA
Este método concatena a la cadena que lo manda llamar la cadena pasada como parámetro.
replace
Recibe 2 parámetros de tipo caracter y sustituye en la cadena que lo manda llamar las
apariciones del primero por el segundo.
toLowerCase
Convierte a minúscula la cadena que lo manda llamar.
toUpperCase
Convierte a minúscula la cadena que lo manda llamar.
trim
Devuelve una copia de la cadena que lo manda llamar sin espacios en blanco iniciales o
finales.
Clase StringBuffer
Esta es una clase gemela de la clase String que proporciona una gran parte de la
funcionalidad de la utilización habitual de las cadenas. String representa secuencias de caracteres
de longitud fija e inmutables. StringBuffer representa secuencias de caracteres que se pueden
ampliar y modificar. Con StringBuffer se pueden insertar caracteres y subcadenas. StringBuffer
crecerá automáticamente para hacer sitio a dichas adiciones.
ƒ
Constructores
Se puede construir un StringBuffer sin parámetros, lo que reserva espacio para 16
caracteres, o se le puede pasar un entero que indica explícitamente el tamaño del buffer.
Finalmente, se le puede pasar un valor de String inicial, que establecerá su contenido y reservará
espacio para 16 caracteres más. Se puede obtener su longitud actual mediante el método length() y
el espacio asignado total a través del método capacity().
ƒ
ensureCapacity
Se utiliza para establecer el tamaño del buffer después de haber construido el objeto
StringBuffer.
ƒ
setLength
Se usa para establecer la longitud exacta del valor String de un buffer, este rellena con ceros
si se establece la longitud a un valor mayor que la longitud actual y trunca el String si se da un
valor menor que el actual.
Autor: M.C.C. Roberto Solís Robles
Página 28 de 50
FUNDAMENTOS DE JAVA
ƒ
charAt y setCharAt
charAt se usa para extraer un caracter de un StringBuffer y setCharAt establece un carácter
en un la posición indicada.
void setCharAt(int posicion, char caracter)
ƒ
getChars
Se usa para copiar una subcadena de un StringBuffer en un arreglo.Se debe tener cuidado en
asegurar que el arreglo tenga lo longitud suficiente para almacenar la subcadena a extraer.
void getChars(int PosInicial, int PosFinal, char Destino[], int posIniDest)
ƒ
append
Este método se llama comúnmente a través del operador +. Tiene versiones sobrecargadas
para todos los tipos. Se llama a String.valueOf para cada parámetro y el resultado se añade al
StringBuffer. Cada versión de append devuelve el propio buffer, lo cual permite que se encadenen
llamadas a append como se muestra a continuación:
StringBuffer cad = new StringBuffer(20);
String s;
s = cad.append("Fac.").append("UAZ ").append(99);
Este ejemplo deja en s la cadena "Fac.UAZ 99"
ƒ
insert
Es igual al método append en que tiene versiones para todos los tipos posibles y se
diferencia en que coloca los caracteres devueltos por String.valueOf en el buffer a partir de un
índice especificado por el primer parámetro.
void insert(int Posicion, String cadena)
Utilidades
La biblioteca de clases de Java contiene un conjunto de clases utilizadas en todos los otros
paquetes principales de Java. Estas clases están almacenadas en los paquetes java.lang y java.util.
Se utilizan para almacenar conjuntos de objetos, realizar la interfaz con funciones del sistema de
bajo nivel, funciones matemáticas, generación de números aleatorios y manipulación de hora/fecha.
Clase Number
Autor: M.C.C. Roberto Solís Robles
Página 29 de 50
FUNDAMENTOS DE JAVA
Esta clase representa una interfaz a todos los tipos escalares estándar. Number tiene
métodos de acceso que devuelven el valor posiblemente redondeado del objeto de cada uno de los
tipos simples:
ƒ
doubleValue() devuelve un double
ƒ
floatValue() devuelve un float
ƒ
intValue() devuelve un int
ƒ
longValue() devuelve un long
ƒ
byteValue() devuelve un byte
ƒ
shortValue() devuelve un short
Las subclases de Number se dan a continuación.
Double y Float
Aparte de los métodos ya mencionados proporcionan varias funciones muy útiles para la
manipulación de valores double y float. Ambas clases tienen 2 constructores para inicializarlas con
valores double y float, o también se pueden inicializar con una representación String del valor.
Algunos de los métodos son:
ƒ
toString() convierte a String el número contenido en la clase
ƒ
valueOf(String)
convierte a float o double el String indicado
Byte, Short, Integer y Long
Estas sirven para almacenar datos tipo byte, short, int y long y tienen métodos para convertir
a cadena así como obtener enteros a partir de cadenas. Algunos de estos métodos son:
ƒ
parseInt(String)
convierte el String en el valor int, byte, short o long
dependiendo de la clase utilizada (Este método y el siguiente depende de la
clase usada y puede ser parseLong, parseShort o parseByte)
ƒ
parseInt(String, base) hace lo mismo que el anterior pero aquí se indica la base
del número en el String
Autor: M.C.C. Roberto Solís Robles
Página 30 de 50
FUNDAMENTOS DE JAVA
ƒ
toString() convierte a String el número contenido en la clase
Character
Esta es una clase que contiene un char. Tiene varios métodos de clase útiles como son:
ƒ
isLowerCase(char) Determina si el char es minúscula
ƒ
isUpperCase(char) Determina si el char es mayúscula
ƒ
isDigit(char) Determina si es un dígito
ƒ
toLowerCase(char) Convierte a minúscula
ƒ
toUpperCase(char) Convierte a mayúscula
Vector
Un Vector es un arreglo ampliable de referencias a objetos. Los objetos se pueden
almacenar al final del Vector usando el método addElement(Objeto) o en un índice dado con el
método insertElementAt(objeto, indice). Para determinar si un objeto se encuentra en un vector se
usa el método contains(Objeto), indexOf(Objeto) y lastIndexOf(Objeto). También se puede extraer
un objeto de una posición específica utilizando los métodos elementAt(indice), firstElement() y
lastElement().
Date
Esta clase se utiliza para representar una fecha y una hora (aunque a partir de la versión 1.1
ha sido sustituida por la clase Calendar. Se puede manipular el día, mes, año, día de la semana,
horas, minutos y segundos. Hay un constructor para objetos Date, Date(), el cual inicializa el objeto
con la fecha y hora actual.
Calendar
Esta es una clase abstracta que sirve para convertir entre un objeto Date y un conjunto de
campos enteros tales como YEAR, MONTH, DAY, HOUR, etc. JDK proporciona una subclase de
Calendar denominada GregorianCalendar. El método getInstance() regresa un objeto
GregorianCalendar cuyos campos han sido inicializados con la fecha y hora actuales.
Algunos de los métodos que tiene son:
Autor: M.C.C. Roberto Solís Robles
Página 31 de 50
FUNDAMENTOS DE JAVA
before(Calendar cuando) Devuelve verdadero si cuando es menor que la instancia que
llama.
after(Calendar cuando) Devuelve verdadero si cuando es mayor que la instancia que llama
equals(Calendar cuando) Devuelve verdadero si cuando y la instancia que llama son iguales
set(año, mes, dia) Para establecer la fecha en el objeto
set(año, mes, dia, horas, minutos, segundos). Para establecer fecha y hora
set(año, mes, dia, horas, minutos)
get(campo) Para obtener el valor de algun campo, el valor que se da como parámetro es uno
de las variables de clase de la clase Calendar que son:
AM_PM
DAY_OF_MONTH
DAY_OF_WEEK
HOUR
MILLISECOND
MINUTE
MONTH
SECOND
YEAR
Por último, el método toString convierte a una representación de cadena del objeto Calendar
con el siguiente aspecto: "Mon, 8 Mar 1999 10:56:23", toLocaleString() convierte a una cadena
más corta como: "03/03/99 10:56:23".
Math
Esta clase contiene todas las funciones en coma flotante que se utilizan en geometría y
trigonometría. Existen 2 constantes double que se utilizan en este tipo de cálculos, E
(aproximadamente 2.718) y PI (aproximadamente 3.14159)
Algunos de los métodos que contiene son:
ƒ
sin(double a) Devuelve el seno del ángulo a en radianes
ƒ
cos(double a) Devuelve el coseno del ángulo a en radianes
ƒ
tan(double a) Devuelve la tangente del ángulo a en radianes
ƒ
asin(double r) Devuelve el ángulo cuyo seno es r
ƒ
acos(double r) Devuelve el ángulo cuyo coseno es r
ƒ
atan(double r) Devuelve el ángulo cuya tangente es r
ƒ
atan2(double a, double b) Devuelve el ángulo cuya tangente es a/b
ƒ
pow(double b, double e) Devuelve el resultado de be
ƒ
exp(double r) Devuelve el resultado de elevar el número e a la r
Autor: M.C.C. Roberto Solís Robles
Página 32 de 50
FUNDAMENTOS DE JAVA
ƒ
log(double r) Devuelve el logaritmo natural de r
ƒ
sqrt(double r) Devuelve la raíz cuadrada de r
ƒ
ceil(double r) Devueve el número completo inmediato mayor o igual a r
ƒ
floor(double r) Devueve el número completo inmediato menor o igual a r
ƒ
rint(double r) Devueve el valor truncado de r
ƒ
round(double r) Devueve el valor de r redondeado como int
ƒ
round(float r) Devueve el valor de r redondeado como int
ƒ
abs(a)
ƒ
max(a,b) Devuelve el máximo de a y b
Devuelve el valor absoluto de a
ƒ min(a,b) Devuelve el mínimo de a y b
Estos últimos 3 métodos tienen varias formas para enteros (int, byte, short, long), double y
float
Random
Esta clase sirve para generar números seudoaleatorios. Cuando se inicializa un objeto
Random con una semilla se puede obtener a continuación lo que parece una secuencia aleatoria.
Generalmente, Java utiliza la hora actual como semilla para el objeto Random para disminuir la
probabilidad de obtener secuencias de números repetidas. Hay 5 tipos de números aleatorios que
ese pueden extraer de un objeto Random. Con el método nextInt se obtiene un int a lo largo de su
rango, con el método nextLong se obtiene un long a lo largo de su rango, con nextFloat se obtiene
un float, con nextDouble se obtiene un double (estas últimas 2 dan un número entre 0.0 y 1.0). Por
último, nextGaussian devuelve un double de distribución gaussiana centrada en 0.0 con una
desviación típica de 1.0. A esta distribución se le llama curva tipo campana.
Autor: M.C.C. Roberto Solís Robles
Página 33 de 50
FUNDAMENTOS DE JAVA
Paquetes
Los paquetes son tanto un mecanismo para dar nombres como un mecanismo de restricción
de visibilidad. Se pueden poner clases dentro de los paquetes sin permitir que el exterior sepa que
están allí. Cada archivo .java tiene las mismas cuatro partes internas, de las cuales solo hemos
hecho uso de una hasta el momento. A continuación se muestra el formato general de un archivo
fuente de Java.
Una sentencia de paquete (opcional)
Las sentencias de importación deseadas (opcional)
Una declaración de clase pública
Las clases privadas del paquete (opcional)
Para indicar que se tiene un paquete se usa la palabra reservada (package), la cual dice en
que paquete se deberían definir ls clases incluidas. Los paquetes definen un conjunto de espacios de
nombres particionados en los que se almacenan las clases. Si se omit la sentencia package, las
clases terminan en el paquete por defecto, que no tiene nombre. El compilador de Java utiliza
directorios del sistema de archivos para almacenar paquetes. Si se declara que una clase está dentro
de un paquete llamado MiPack, entonces el archivo fuente de esa clase se debe almacenar en un
directorio llamado MiPack. El formato de la sentencia package es el siguiente:
package paq1[.paq2[.paq3]];
Observe que se puede crear una jerarquía de paquetes dentro de paquetes separando los
niveles con puntos. Un paquete declarado como
package java.awt.imagen;
se debe almacenar en java\awt\imagen (si es que el sistema operativo es Windows
especificamente).
Sentencia import
Lo que se pone después de una sentencia package y antes de las definiciones de clase en un
archivo fuente en Java puede ser una lista de sentencias import. Esta sentencia permite incluir en el
programa las clases que se necesiten para su funcionamiento. La forma general del import es la
siguiente:
import paquete1[.paquete2].(nombres_clase | *);
paquete1 es el nombre de un paquete de alto nivel, paquete2 es el nombre de un paquete
opcional contenido en el paquete exterior separado por un punto(.). No hay ningún límite en cuanto
a la profundidad de la jerarquía de paquetes. Finalmente se especifica un nombre de clase explícito,
o bien, un asterisco para indicar que se debe obtener el paquete completo, es decir, todas las clases
que este tenga.
Autor: M.C.C. Roberto Solís Robles
Página 34 de 50
FUNDAMENTOS DE JAVA
Como ya se había mencionado con anterioridad, las clases incorporadas en el Java se
incluyen en un paquete denominada java. Las funciones del lenguaje básicas se almacenan dentro
del paquete de java denominada java.lang. Normalmente se tiene que importar cada paquete o clase
que se desea utilizar, pero debido a que Java no es útil sin gran parte de la funcionalidad de
java.lang, el compilador la importa implícitamente para todos los programas.
Si existe una clase con el mismo nombre dentro de 2 o mas paquetes distintos importados,
cuando se quiera hacer uso de una de ellas se debe indicar de manera completamente cualificada, es
decir, se tiene que indicar dentro de que paquetes se encuentra la clase específica deseada.
Protección de Acceso
Java proporciona muchos niveles de protección para permitir un control preciso de la
visibilidad. Las clases y los paquetes son dos medios de encapsular y contener el espacio de
nombres y el ámbito de las variables y métodos. Los paquetes actúan como recipientes de clases y
otros paquetes. Las clases actúan como recipientes de código y datos. Es obvio que dentro de una
clase, todas las variables y métodos son visibles para todas las otras partes de la misma clase, dado
que la clase es la unidad de abstracción más pequeña de Java. Por la existencia de paquetes, Java
debe distinguir 4 categorías de visibilidad entre elementos de clase:
ƒ
Subclases del mismo paquetes
ƒ
No subclases del mismo paquete
ƒ
Subclases en paquetes distintos
ƒ
Clases que no están ni en el paquete ni son subclases
Las palabras reservadas utilizadas para la protección son: public, private y protected cuyas
combinaciones así como el acceso que dan sobre a categorías arriba mencionadas se muestran en la
siguiente tabla:
Sin
private
protected
private
public
modificador
protected
Si
Si
Si
Si
Si
Misma clase
Si
No
Si
Si
Si
Misma subclase de
paquete
Si
No
Si
No
Si
Misma no subclase
de paquete
No
No
Si
Si
Si
Subclase de diferente
paquete
No
No
No
No
Si
No
subclase
en
diferente paquete
Autor: M.C.C. Roberto Solís Robles
Página 35 de 50
FUNDAMENTOS DE JAVA
MANEJO DE EXCEPCIONES
Una excepción es una condición anormal que surge en una secuencia de código durante la
ejecución. Tradicionalmente, los lenguajes de programación forzaban al programador a utilizar
códigos de retorno recibidos desde las llamadas a función para señalar errores al código llamante.
El manejo de excepciones de Java lleva el manejo del error en tiempo de ejecución al mundo
orientado a objetos. Una excepción en Java es un objeto que describe una condición excepcional
que se ha producido en un fragmento del código. Cuando surge una condición excepcional, se crea
un objeto Exception que se envía al método que ha provocado la excepción. Ese método puede
capturar la excepción en base a su tipo concreto. Los métodos también se pueden proteger frente a
una salida prematura mediante una exepción y hacer que se ejecute un bloque de código justo antes
de que una excepción provoque que se termine el método. Las excepciones pueden aparecer de
manera asíncrona en un método o pueden ser creadas manualmente y enviadas para informar de
alguna condición de error al método llamante.
Fundamentos
El manejo de excepciones de Java se hace mediate cinco palabras reservadas: try, catch,
throw, throws y finally. Básicamente, se intenta (try) ejecutar un bloque de código y si se produce
un error, el sistema lanza (throws) una excepción que se puede capturar (catch) en base al tipo de la
excepción o ser tratada finalmente (finally) por un manejador por default.
Esta es la forma básica de un bloque manejador de excepciones:}
try {
// bloque de código
} catch (TipoExcepcion1 e) {
// manejador de excepción para TipoExcepcion1
} catch (TipoExcepcion2 e) {
// manejador de excepción para TipoExcepcion2
throw(e) ; //volver a lanzar la excepción
} finally { // Código a realizarse al finalizar la ejecución del método
}
Tipos de Excepción
Hay una única clase en la parte superior de la jerarquía de clases de excepción llamada
Throwable (lanzable). Esta clase se utiliza para representar todas las condiciones excepcionales.
Cada tipo de excepción de la forma general anterior es una subclase de Throwable. Se definen 2
subclases inmediatas que dividen a las clases de Throwable en 2 ramas distintas. Una clase,
Exception, se utiliza para las condiciones excepcionales que los programas de usuario deberían
capturar. Es la clase de partida de las subclases que utilizaremos para crear nuestras propias
condiciones excepcionales y que esperamos que otros capturen. La otra rama es la clase Error, que
define las condiciones que no se deberían de capturar normalmente. Tenga cuidado al capturar las
Autor: M.C.C. Roberto Solís Robles
Página 36 de 50
FUNDAMENTOS DE JAVA
subclases Error, porque se crean habitualmente como respuesta a fallos catastróficos. Un
refinamiento adicional es una subclase de Exception, llamada RunTimeException (excepción
durante la ejecución), que esta pensada para condiciones excepcionales creadas por el intérprete.
Habitualmente, estas excepciones las crea automáticamente el intérprete como respuesta a algún
error de programa.
Excepciones no Capturadas
Los objetos de excepción los crea automáticamente el intérprete de Java como respuesta a
alguna condición excepcional. Por ejemplo, el siguiente programa incluye una expresión que tiene
una división entre cero durante la ejecución:
class Ejemplo {
public static void main (String a[])
{ int d=0;
int a=42/d;
}
}
Cuando el intérprete intenta ejecutar la división, se construye un objeto de excepción para
provocar que se detenga este código y trate esta condición de error. El interprete lanza la excepción
y el código debe capturar tal excepción y tratarla inmediatamente. El flujo del código se
interrumpirá en el operador de división y después se buscará en la pila de llamadas actual (que
contiene un registro de las llamadas a método) cualquier manejador de excepciones.
Un manejador de excepciones como ya se mencionó es algo establecido para tratar
inmediatamente la condición excepcional. En el ejemplo, no hay ninguno por lo que se ejecuta el
manejador por default. Este imprime el valor String de la excepción y el registro en la pila del lugar
donde se produjo la excepción:
C:\> java Ejemplo
java.lang.ArithmeticException: / by zero
at Ejemplo.main(Ejemplo.java:4)
El registro incluye el nombre de la clase, el nombre del método, el nombre del archivo
fuente y el número de línea que generó la excepción. Se puede ver también que el tipo de excepción
es una subclase especial de Exception denominada ArithmeticException que describe más
específicamente el tipo de error que se ha producido. A continuación se muestra una variante del
código del ejemplo anterior:
class Ejemplo {
static void subrutina()
{ int d=0;
int a=42/d;
}
public static void main (String a[])
{ subrutina();
Autor: M.C.C. Roberto Solís Robles
Página 37 de 50
FUNDAMENTOS DE JAVA
}
}
El registro de la pila al ejecutarlo sería el siguiente:
C:\> java Ejemplo
java.lang.ArithmeticException: / by zero
at Ejemplo.subrutina(Ejemplo.java:4)
at Ejemplo.main(Ejemplo.java:7)
Como puede ver, el final de la pila es la línea 7 de main, que llama al método subrutina, que
provocó la excepción en la línea 4.
try y catch
Es muy conveniente que el intérprete de Java muestre el registro de la pila detallado cuando
no se captura una excepción, pero a menudo será mejor que maneje la excepción usted mismo y
que continúe la ejecución. Como ya se mencionó se usa la palabra try para especificar el bloque de
código que se debería proteger frente a todas las excepciones, y adelante del bloque try se incluye
la cláusula catch para especificar el tipo de excepción que se desea capturar. Por ejemplo, para el
primer ejemplo el código sería como sigue:
class Ejemplo {
public static void main (String a[])
{ int d=0;
try {
int a=42/d;
} catch (AritmethicException e) {
System.out.println("Division entre cero");
}
}
}
Ahora, la salida sería:
C:> java Ejemplo
Division entre cero
En realidad, como la cláusula try y la cláusula catch tienen una sola sentencia no requieren
de llaves.
El objetivo de la mayoría de las cláusulas catch bien construidas deberían resolver la
condición excepcional poniendo las variables en algún estado razonable, y después de continuar
como si el error no hubiera sucedido nunca. Si un método no maneja una excepción, es una
decisión del que lo llamó el manejarla y así sucesivamente se sube por la cadena de llamadas hasta
Autor: M.C.C. Roberto Solís Robles
Página 38 de 50
FUNDAMENTOS DE JAVA
el manejador en tiempo de ejecución de Java más externo toma el control e imprime el registro de
la pila.
Cláusulas catch múltiples
En algunos casos, la misma secuencia de código puede activar más de una condición
excepcional. Se pueden tener para ello varias cláusulas catch, las cuales son inspeccionadas en el
orden en el que están y el primero que coincida con el tipo de excepción se ejecuta. Las clases de
excepción más específicas se deben poner primero. Por ejemplo el siguiente programa captura 2
tipos de excepción diferentes:
class Multicatch {
public static void main (String a[])
{ try {
int n=a.length;
System.out.println("n="+n);
int b=42/n;
int c[]={1};
c[42]=99;
} catch (ArithmeticException e) {
System.out.println("división entre cero:" + e);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Indice de arreglo no existente:" + e);
} catch (Throwable t)
System.out.println("Se ha obtenido t:" + t);
}
}
}
Este ejemplo provocará una excepción de división si no se le dan parámetros al programa,
en caso de darle parámetros la excepción que se generaría sería la de utilizar un índice no existente
en el arreglo c, que solo tiene un elemento.
Sentencias try anidadas
La sentencia try se anida de una manera muy similar a los ámbitos de las variables. Se
puede colocar una sentencia try envolviendo a una llamada a método y dentro de ese método, otra
sentencia try podría proteger a algún otro fragmento de código. Cada vez que se introduce una
sentencia try, se almacena en la pila el contexto de excepción hasta que terminan todas las
sentencias try anidadas. Si una sentencia try no tiene un manejador catch para una excepción en
concreto, se examina la pila buscandi los siguientes manejadores catch de sentencias try. Esto
continúa hasta que se agotan las sentencias try apiladas y en dicho momento se imprimirá el
registro de la pila y se detendrá la ejecución.
Autor: M.C.C. Roberto Solís Robles
Página 39 de 50
FUNDAMENTOS DE JAVA
class Anidada {
static void proceso() {
try
{
int c[]={1};
c[42]=99;
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Indice no existente:" + e);
}
}
public static void main(String a[]) {
try
{ int n = a.length;
System.out.println("n=" + n);
int b= 42/ n ;
proceso();
} catch (ArithmeticException e) {
System.out.println("división entre cero:" + e);
}
}
}
throw
La sentencia throw se utiliza para lanzar explícitamente una excepción. En primer lugar,
debe obtener un descriptor de una instancia de Throwable, mediante un parámetro en una cláusula
catch, o crear una utilizando el operador new. Esta es la forma general de una sentencia throw:
throw InstanciaThrowable;
El flujo de la ejecución se detiene inmediatamente después de la sentencia throw y
no se llega a la sentencia siguiente. Se inspecciona el bloque try que la engloba más cercano para
ver si tiene una cláusula catch cuyo tipo coincida con el de la instancia Throwable. Si la encuentra,
el control se transfiere a esa sentencia. Si no, se inspecciona el siguiente bloque try que la engloba y
así sucesivamente, hasta que el manejador de excepción más externo detiene el programa e
imprime el registro de la pila hasta la sentencia throw. A continuación se muestra un ejemplo:
class ThrowDemo {
static void demoproc()
{
try
{ throw new NullPointerException("demo");
} catch NullPointerException e) {
System.out.println("Excepcion capturada en demoproc");
throw e;
}
}
Autor: M.C.C. Roberto Solís Robles
Página 40 de 50
FUNDAMENTOS DE JAVA
public static void main (String a[])
{
try
{ demoproc();
} catch (NullPointerException e) {
System.out.println("Excepcion capturada de nuevo en main");
}
}
}
Este ejemplo tiene 2 oportunidades de tratar con el mismo error. Primero main establece un
contexto de excepción y luego llama a demoproc, el cual también establece un contexto de
excepción y lanza inmediatamente una nueva instancia de NullPointerException. Esta se captura en
la línea siguiente, imprime que ha sido captura y la vuelve a lanzar, capturandola ahora el catch en
main.
throws
Si un método es capaz de provocar una excepción que no maneja el mismo, debería
especificar este comportamiento para que los llamantes puedan protegerse frente a esta excepción.
La palabra reservada throws se utiliza para identificar la lista de excepciones posibles que un
método puede lanzar. Para la mayoría de las subclases de Exception, el compilador de Java le
obligará a declarar que tipos va a lanzar posiblemente un método. Si el tipo de excepción es Error o
RunTimeException o cualquiera de sus subclases, no se aplica esta regla, dado que no se espera que
se produzcan como algo normal en el funcionamiento del programa. La definición de un método
cambia a la siguiente:
tipo nombre (lista parametros) throws lista_excepciones
{
}
A continuación se muestra un ejemplo de un programa que intenta lanzar una excepción sin
tener código para capturarla y tampoco utiliza throws para declarar que se lanzará esta excepción,
por lo tanto no se compilará:
class ThrowsDemo1 {
static void proceso()
{ System.out.println("Capturada dentro de proceso");
throw new IllegalAccessException("demo");
}
public static void main (String a[])
{
proceso();
}
}
Para que se pueda compilar este programa hay que indicar que el método lanza una
excepción IllegalAccessException, con lo que se asciende el problema un nivel más arriba en la
Autor: M.C.C. Roberto Solís Robles
Página 41 de 50
FUNDAMENTOS DE JAVA
pila de llamadas. Ahora main llama a proceso, que se ha declarado que lanza una
IllegalAccessException pero main no tiene una sentencia try/catch que capture esta excepción, por
lo que no compilará, por lo tanto, para que el programa compile este debería ser como sigue:
class ThrowsDemo {
static void proceso() throws IllegalAcessException
{ System.out.println("Dentro de proceso");
throw new IllegalAccessException("demo");
}
public static void main (String a[])
{ try
{
proceso();
} catch (IllegalAccessException e) {
System.out.println("Capturada "+e);
}
}
}
La salida de este programa sería:
C:\>java ThrowsDemo
Dentro de proceso
Capturada java.lang.IllegalAccessException: demo
finally
Cuando se lanzan excepciones, la secuencia de código de un método sigue un trayecto no
lineal bastante brusco a lo largo del método, omitiendo algunas líneas e incluso es posible que se
termine prematuramente si no coincide ninguna de las cláusulas catch. A veces es necesario estar
seguro de que se ejecutará un fragmento de código dado independientemente de que excepciones se
provocan y capturan. Se puede utilizar la palabra reservada finally para identificar dicho bloque de
código. Incluso aunque no coincida con ninguna de las cláusulas, se ejecutará el bloque finally
antes del código que esta después del bloque try completo. Cada sentencia try requiere que haya al
menos una cláusula catch o finally que coincida con ella. Siempre que un método vaya a devolver
el control al llamante, mediante una excepción no capturada o una sentencia return explícita, se
ejecuta la cláusula finally justo antes del final del método. Esto puede resultar útil para cerrar
descriptores de archivo y liberar cualquier otro recurso que se hubiese asignado al comienzo de un
método con la intención de desprenderse de ellos antes de terminar. La cláusula finally es
totalmente opcional. A continuación se muestra un programa ejemplo:
class FinallyDemo {
static void procA()
{
try
{ System.out.println("Dentro de procA");
throw new RunTimeException("demo");
} finally {
Autor: M.C.C. Roberto Solís Robles
Página 42 de 50
FUNDAMENTOS DE JAVA
System.out.println("finally de procA");
}
}
static void procB()
{
try
{ System.out.println("Dentro de procB");
return;
} finally {
System.out.println("finally de procB");
}
}
public static void main (String a[])
{ try
{ procA();
} catch (Exception e) ;
procB();
}
En este ejemplo se puede ver que al terminar tanto el procA (por una excepcion)
como el procB (de manera normal) se ejecuta el bloque finally antes de que devuelvan el control.
Así pues, la salida de este programa sería:
C:\>java FinallyDemo
Dentro de procA
finally de procA
Dentro de procB
finally de procB
Subclases de excepción
Solamente se pueden capturar o lanzar subclases de la clase Throwable. Los tipos simples
como int o char y las clases que no son Throwable, como String no se pueden utilizar como
excepciones. La utilización mas habitual de las excepciones es crear un tipo de excepción
personalizado mediante la creación de una subclase de Exception. Estas subclases no tendrán
mucho que implementar, pero su simple existencia en los tipos permite la generación de código que
tiene modos de fallo comprensibles y que proporciona una interfaz limpia y orientada a objetos
para los clientes de las clases. Por lo tanto, la definición de métodos públicos incluye los tipos de
excepciones que se pueden lanzar. Este es un programa ejemplo que declara una nueva subclase de
Exception, y después utiliza esa subclase para señalar una condición de error en un método:
class MiException extends Exception {
private int Detalle;
MiExcepcion (int a) {
Detalle = a;
}
Autor: M.C.C. Roberto Solís Robles
Página 43 de 50
FUNDAMENTOS DE JAVA
public String toString() {
return "MiExcepcion["+Detalle+"]";
}
}
class DemoExcepcion {
static void calculo (int a) throws MiExcepcion {
System.out.println("Llamada a calculo("+a+").");
if (a > 10)
throw new MiExcepcion(a);
System.out.println("Salida normal.");
}
public static void main (String a[])
{ try
{ calculo(1);
calculo(20);
} catch (MiExcepcion e) {
System.out.println("Capturada "+e);
}
}
}
La salida de este programa sería:
C:\>java DemoExcepcion
Llamada a calculo(1).
Salida normal.
Llamada a calculo(20).
Capturada MiExcepcion[20]
Autor: M.C.C. Roberto Solís Robles
Página 44 de 50
FUNDAMENTOS DE JAVA
Entrada/Salida
La mayoría de los programas no pueden alcanzar sus metas sin acceder a datos externos.
Estos datos se recuperan a partir de un origen de entrada. Los resultados de un programa se envían
a un destino de salida. La noción genérica de una fuente de entrada puede representar muchos tipos
de entrada distintos como son los archivos de disco y el teclado. Del mismo modo, un destino de
salida puede ser un archivo de disco o el monitor. Estas abstracciones son una manera limpia de
tratar la entrada/salida (E/S) sin necesitar que todo el código comprenda la diferencia entre un
teclado y un archivo.
Java llama flujo a esta abstracción y la implementa con varias clases del paquete java.io. El
flujo de E/S representa todos los orígenes y destinos de los datos a través de una interfaz uniforme.
La entrada esta encapsulada en la clase InputStream y la salida en la clase OutputStream. Estas 2
clases abstractas son las que todos los objetos deberían referenciar cuando tratan la E/S en general.
Java tiene varias subclases concretas de cada una de ellas para tratar las diferencias entre archivos
de disco, conexiones de red o teclado y monitor.
Puesto que la E/S de archivo es una operación habitual, el paquete java.io incluye una clase
File para trabajar directamente con el sistema de archivos. Esta clase permite que se trabaje con los
atributos de fecha y hora de los archivos y que se pueda iterar a través de las jerarquías de
directorios.
File
Un File es es el único objeto del paquete de E/S que referencia a un archivo de disco real.
La clase File no especifica como se recupera o almacena la información en los archivos, solo
describe las propiedades de un objeto archivo.. Un directorio en Java se trata igual que un archivo
con una propiedad adicional -una lista de nombres de archivo que se puede examinar utilizando el
método list.
Los objetos archivo se pueden crear utilizando uno de los 3 constructores disponibles:
ƒ
El primero construye un objeto File utilizando un trayecto de directorio como
único parámetro
ƒ
El segundo usa 2 parámetros, el trayecto (ruta padre) y el nombre del archivo.
ƒ
El tercero usa 2 parámetros, el primero es un objeto tipo File que apunta a un
trayecto (ruta padre) y el segundo es el nombre de un archivo.
A continuación se muestra un ejemplo de cada uno de estos constructores:
File f1 = new File("\"),
f2 = new File("\","autoexec.bat"),
f3 = new File(f1,"autoexec.bat");
Autor: M.C.C. Roberto Solís Robles
Página 45 de 50
FUNDAMENTOS DE JAVA
Algunos de los métodos que tiene esta clase son:
boolean canRead()
Devuelve verdadero si el archivo se puede leer
boolean canWrite()
Devuelve verdadero si el archivo se puede escribir
int CompareTo(File f)
Compara la ruta del archivo con la del f y devuelve un entero de acuerdo a si es mayor,
menor o igual (numero positivo, negativo o cero respectivamente)
boolean createNewFile()
Crea un archivo nuevo y vacío con el nombre dado al construirse el objeto siempre y
cuando no exista aún.
boolean delete()
Elimina el archivo o directorio denotado por el objeto
void deleteOnExit()
Elimina el archivo o directorio denotado por el objeto al salir del programa
boolean exists()
Determina si el archivo o directorio denotado por el objeto existe
String getAbsolutePath()
Devuelve la ruta absoluta del archivo o directorio denotado por el objeto
String getName()
Devuelve el nombre del archivo o directorio denotado por el objeto
String getParent()
Devuelve la ruta padre del archivo o directorio denotado por el objeto
boolean isDirectory()
Determina si la ruta dada al crear al objeto se refiere a un directorio
boolean isFile ()
Determina si la ruta dada al crear al objeto se refiere a un archivo
boolean isHidden ()
Determina si la ruta dada al crear al objeto se refiere a un archivo oculto
boolean lastModified()
Devuelve la cantidad de segundos desde las 00:00 del 1 de enero de 1970 que habían
transcurrido cuando se modifico por última vez
Autor: M.C.C. Roberto Solís Robles
Página 46 de 50
FUNDAMENTOS DE JAVA
boolean renameTo(File X)
Le cambia el nombre al objeto denotado por el nombre almacenado en X
String toString()
Devuelve una cadena con el la ruta del archivo o directorio denotado
Directorios
Para manejar directorios con la clase File aparte de algunos métodos ya mencionados para
determinar si es un directorio existe el método:
String[] list()
el cual devuelve un arreglo de cadenas donde quedan almacenados los nombres de cada uno
de los archivos que contiene el directorio. Si este método se llama sobre un objeto File que no sea
un directorio se genera una excepción NullPointerException en tiempo de ejecución.
Para crear un directorio se usa el método:
boolean mkdir()
O bien si es una estructura jerárquica de directorios donde los de nivel mas alto todavía no
existen se usa el método:
boolean mkdirs()
FileNameFilter
A menudo se desea limitar el número de archivos devueltos por el método list para que se
incluyan únicamente aquellos archivos que cumplan un cierto patrón de nombre de archivo. Con
este fin, el paquete java.io incluye una interfaz llamada FileNameFilter. Un objeto de este tipo tiene
un solo método:
boolean accept(File dir, String nom)
el cual prueba si un archivo especificado debe ser incluido en la lista; el primer parámetro
contiene el directorio en el cual esta el archivo y el segundo es el nombre del archivo. Este método
debe devolver un valor true si se debe incluir el archivo en la lista o false si no. Este método en
realidad es solo una interfaz en el paquete java.io, lo cual significa que el código de tal método
debe ser realizado por uno mismo de acuerdo a lo que se quiere indicando que se va a implementar
la clase FileNameFilter. Por ejemplo, si queremos encontrar archivos de acuerdo a una extensión
especificada, entonces podemos hacer una clase a la cual se le pase la extensión deseada y que
determine si el archivo termina con esa extensión para ver si se acepta o no. Supongamos que la
clase se va a llamar porExt, entonces esta se definiría de la siguiente manera:
import java.io.*;
public class porExt implements FileNameFilter {
String extension;
public porExt(String ext) { // Constructor de la clase
extension="."+ext;
}
Autor: M.C.C. Roberto Solís Robles
Página 47 de 50
FUNDAMENTOS DE JAVA
public boolean accept(File dir, String nombre) {
return nombre.endsWith(extension);
}
}
Una vez que se tiene esta clase, entonces se crea un objeto de clase FileNameFilter
llamando al constructor de porExt y se usa el siguiente método de la clase File:
String[] list(FileNameFilter filtro)
La cual es una variante del método list ya descrito pero que ahora solo va a poner en la lista
los archivos que son aceptados por la implementación específica de FileNameFilter (en este
ejemplo, por la clase porExt):
FileNameFilter filtro = new porExt("txt");
f1= new File("\");
String s[]=f1.list(filtro);
En el ejemplo anterior quedaría en s la lista de los archivos que tienen extensión .txt del
directorio raíz.
InputStream
Esta es una clase abstracta que define el modelo de Java para el flujo de entrada. Todos los
métodos de esta clase lanzarán una IOException (excepción de E/S) si se producen condiciones de
error. A continuación se muestran algunos de sus métodos:
int read()
Devuelve una representación como entero del siguiente byte de entrada disponible.
int read(byte b[])
Intenta leer hasta b.length bytes situándolos en b y devuelve el número real de bytes que se
leyeron con éxito.
int read(byte b[], int offset, int len)
Intenta leer hasta len bytes situándolos en b, comenzando en b[offset] y devuelve el número
real de bytes que se leyeron con éxito.
int skip(long n)
Omite n bytes de la entrada y devuelve el número de bytes que se han omitido
int available()
Devuelve el número de bytes de entrada disponibles actualmente para su lectura.
void close()
Cierra el origen de entrada. Los intentos de lectura posteriores generarán una IOException.
Autor: M.C.C. Roberto Solís Robles
Página 48 de 50
FUNDAMENTOS DE JAVA
void mark(int limitelectura)
Coloca una marca en el punto actual del flujo de entrada seguirá siendo válida hasta que se
lean límitelectura bytes.
void reset ()
Devuelve el puntero de entrada a la marca establecida previamente.
boolean markSupported()
Devuelve true si se admiten mark/reset en este flujo.
System.in
Esta clase es para leer del teclado y desciende de InputStream. Cuando se lee desde
System.in los caracteres uno a uno, la operación se realiza a través de un buffer. No se volverá de
una llamada de lectura de byte único hasta que se cierra el archivo o se introduzca un avance de
línea (\n). El ENTER se debe presionar para que la entrada pase al programa.
Por ejemplo, para leer un byte del teclado, se hace lo siguiente:
int n;
...
n=System.in.read();
OutputStream
Igual que InputStream, esta es una clase abstracta que define un flujo de salida. Todos los
métodos de esta clase devuelven un valor void y lanzan una IOException en caso de error. Algunos
de los métodos que contiene son:
write(int b)
Escribe un byte especificado por el valor entero b.
write(byte b[])
Escribe un arreglo completo de bytes en el flujo de salida.
write(byte b[],int offset, int len)
Escribe len bytes del arreglo b a partir de la posicion offset.
flush()
Inicializa el estado de la salida
close()
Cierra el flujo de salida. Los intentos de escritura posteriores generarán una IOException.
Autor: M.C.C. Roberto Solís Robles
Página 49 de 50
FUNDAMENTOS DE JAVA
FileInputStream
Esta clase utiliza archivos de datos reales como base del flujo de entrada. Contiene dos
constructores:
FileInputStream(String nombrearchivo)
FileInputStream(File f)
Ambos generan una excepcion FileNotFoundException si el archivo no existe.
Cuando se crea un FileInputStream se abre para lectura, esta clase sobreescribe 6 de los
métodos de la clase abstracta InputStream. Si se intenta utilizar los métodos mark o reset se
generará una IOException.
FileOutputStream
Esta clase comparte el mismo estilo de constructorees que FileInputStream. Sin embargo, la
creación de FileOutputStram no depende de que el archivo ya exista. Esta clase crea el archivo
antes de abrirlo como salida cuando se crea el objeto, por lo tanto, si el archivo ya existe su
contenido se borra. Si se intenta abrir un archivo de solo lectura se lanzará una IOException.
Autor: M.C.C. Roberto Solís Robles
Página 50 de 50