Jose M. Fern�ndez Acerca del Author: Diplomado en inform�tica, en la especialidad de planificaci�n y control de sistemas inform�ticos por la universidad de M�laga a finales de los a�os 80. Desde entonces trabaj� primero como programador y despu�s como analista de aplicaciones en empresas siempre relacionadas con la Administraci�n. Siempre he trabajado con grandes sistemas (y profesionalmente sigo haci�ndolo) pero hace a�o y medio por casualidad tropec� con Linux y descubr� que en este mundo la libertad se escribe con letras MAY�SCULAS. Contenidos: Cuestiones Lexicas Tipos de datos, variables, operadores Sentencias de control Clases, M�todos, Herencia |
Resumen:
Esta serie de art�culos tiene como modelo los libros cl�sicos
de programaci�n por lo que intentaremos seguir su estructura en la
forma de presentar los contenidos. Una vez realizada una
introducci�n y definidas las caracter�sticas del lenguaje en el
primer art�culo, continuaremos en este segundo con los tipos de
datos, variables, sentencias de control etc., hasta llegar a las
clases, el tema central y m�s importante de toda la serie de
art�culos. Las clases son la base de este lenguaje de
programaci�n. Para poder centrarnos en el tema de las clases la
primera parte la haremos lo m�s esquem�tica posible ya que al fin
y al cabo no var�a mucho respecto al resto de lenguajes de
programaci�n.
Formalmente un programa en Java est� compuesto por un conjunto de comentarios, identificadores, literales, separadores, espacios en blanco y palabras clave.
El compilador recoge c�digo escrito en formato Unicode expandiendo el n�mero de bytes de los 8 del ASCII a 16 y por consiguiente amplia el juego de caracteres para adaptarse a los caracteres de los idiomas no latinos. Los espacios en blanco, tabuladores y los saltos de l�neas son eliminados por el compilador ya que no son parte del conjunto de s�mbolos, esto hace que los programas en Java se puedan formatear de la forma que m�s nos guste.
Hay tres estilos de comentarios en Java:
Los identificadores son los nombres que se dan a las variables, clases y m�todos. Pueden ser cualquier secuencia de letras en may�sculas y min�sculas, n�meros y los caracteres subrayado y signo d�lar($). No pueden comenzar por un n�mero.
En Java hay algunos caracteres que se utilizan como separadores. El separador utilizado con m�s frecuencia es el (;) pero adem�s encontraremos:
|
|
|
Contiene listas de par�metros en la definici�n y llamada a los m�todos. Se utiliza asimismo para precedencia en expresiones, contener expresiones en sentencias de control y en conversiones de tipos. |
|
Para contener los valores de las matrices inicializadas autom�ticamente. Para definir un bloque de c�digo, para clases, m�todos, y �mbitos locales. |
|
Para definir tipos matriz. Para referencia valores de una matriz. |
|
Separador de sentencias. |
|
Separa identificadores consecutivos en la declaraci�n de variables. Encadena sentencias dentro de una sentencia for. |
|
Para separar nombres de paquetes, subpaquetes y clases. Para separar una variable o m�todo de una variable de referencia. |
Las palabras claves son identificadores utilizados por el lenguaje Java y no pueden utilizarse de ninguna otra forma que la que est� definida por el mismo. En el cuadro siguiente mostramos todas las palabras claves de Java:
abstract | double | int | super |
boolean | else | interface | switch |
break | extends | long | synchronized |
byte | false | native | this |
byvalue | final | new | threadsafe |
case | finally | null | throw |
catch | float | package | transient |
char | for | private | true |
class | goto | protected | try |
const | if | public | void |
continue | implements | return | while |
default | import | short | |
do | instanceof | static |
En este punto hay que volver a insistir en que Java es un lenguaje fuertemente tipado, cada variable tiene un tipo y cada tipo est� definido estrictamente. En todas las asignaciones, bien sean expl�citas o a trav�s de paso de par�metros en llamadas a m�todos, se comprueba la compatibilidad de los tipos. No hay conversi�n autom�tica entre tipos. El compilador comprueba todas las expresiones y par�metros para asegurar que los tipos son compatibles.
En �l art�culo anterior comentamos que Java era un lenguaje totalmente orientado a objetos, pues bien, por razones de eficiencia Java define ocho tipos de datos "simples" que no son objetos. Adem�s por razones de portabilidad todos los tipos de datos tienen un rango definido estrictamente.
Los tipos de datos simples los podemos distribuir en cuatro grupos:
|
|
|
|
Entero | long | 64 |
-9.223.372.036.854.775.808 a 9.223.372.036.854.775.807 |
int | 32 |
-2.147.483.648 a 2.147.483.647 |
|
short | 16 | -32.768 a 37.767 | |
byte | 8 | -128 a 127 | |
Coma flotante | float | 32 | 3.4 e-038 a 3.4 e+038 |
double | 64 | 1.7 e-308 a 1.7 e+308 | |
Caracter | char | 16 | Unicode |
Boleano | boolean | true o false |
Una variable se define por la combinaci�n de un identificador y un tipo. Opcionalmente podemos inicializar la variable al mismo tiempo que la declaramos. Toda variable tiene un �mbito y un tiempo de vida. Todas las variables tienen que ser declaradas antes de ser usadas. Se pueden declarar en cualquier parte del programa, incluso en el mismo momento de ser utilizada por primera vez.
La forma general de la declaraci�n de una variable es:
tipo identificador [=valor] [,identificador [=valor]......]; |
donde tipo puede ser un tipo b�sico de Java, una clase o interfaces. Si inicializamos la variable, la expresi�n de inicializaci�n debe se del mismo tipo o compatible con el especificado en la variable.
Ejemplos :
int a = 4, b, c=7; char c; miclase clase; |
Como regla general, la variable definida dentro de un �mbito no podr� ser accedida desde fuera de �ste (se define como "�mbito" como la porci�n de c�digo delimitado entre llaves {}). Una variable no mantendr� su valor una vez que se ha salido de su �mbito.
La mayor�a de los lenguajes de programaci�n definen dos categor�as de �mbitos: global y local. Estos �mbitos tradicionales no encajan con el modelo orientado a objetos de Java. En �ste los dos principales �mbitos son los definidos por una clase y por un m�todo.
Java permite, aunque en la teor�a se niegue, asignar un valor de un tipo a una variable de otro tipo, si los dos tipos son compatibles se realiza una conversi�n autom�tica y si no lo son se puede realizar una conversi�n expl�cita entre tipos incompatibles. Para realizar una conversi�n autom�tica de tipos se debe cumplir las siguientes condiciones:
Por ejemplo, un tipo int es lo suficientemente grande como para almacenar un tipo byte por lo que no necesita una conversi�n expl�cita. Los tipos num�ricos no son compatibles con char o boolean y estos no son compatibles con el resto. Si quisi�ramos asignar un valor int a un byte tendr�amos que utilizar una conversi�n expl�cita que tiene el siguiente formato:
(tipo) valor |
donde tipo indica el tipo al que se va a convertir. Ejemplo :
int a; char b; a=(int) b; |
Con la conversi�n autom�tica de tipos hay que tener un poco de cuidado ya que al realizar la conversi�n de puede perder informaci�n. Por ejemplo:
La conversi�n de tipos en coma flotante a enteros pierde la parte decimal:
int a; double d= 125.43; a=(int) d; la variable a tiene el valor 125. byte b; int i=257; b=(byte) i; la variable b tiene el valor 1, que es el resultado de dividir 257 entre 256 donde 256 es el rango del tipo byte. byte b; double d= 340.123; b=(byte) d; donde b tendr� el valor de 84; |
Todas estas conversiones se realizan con el benepl�cito del compilador y del interprete que no ponen ning�n tipo de reparo a ello.
Existe un amplio conjunto de operadores, los cuales podemos agrupar en cuatro categor�as: aritm�ticos, a nivel de bit, relacionales y l�gicos. Como norma general funcionar�n exactamente igual que en otros lenguajes pero hay algunas peque�as diferencias que iremos matizando sobre la marcha.
|
|
|
Suma |
|
Resta |
|
Multiplicaci�n |
|
Divisi�n |
|
Modulo(resto de la divisi�n) |
|
Incremento |
|
Suma y asignaci�n |
|
Resta y asignaci�n |
|
Multiplicaci�n y asignaci�n |
|
Divisi�n y asignaci�n |
|
M�dulo y asignaci�n |
|
Decremento |
El operador m�dulo se puede aplicar tanto a valores enteros como en coma flotante. Por ejemplo:
int a= 38; double d= 41.95; int c= a % 10; double e= d % 10; |
La variable c contiene el valor 8. La variable e contiene el valor 1.95;
Los operadores con asignaci�n son �tiles en construcciones del tipo:
a = a + 4; es equivalente a a += 4;
a = a % 2; es equivalente a a %= 2;
En general podemos indicar que las sentencias de la forma:
var=var op expresi�n;
se pueden sustituir por:
var op= expresi�n;
Se definen algunos operadores a nivel de bit que se pueden aplicar a tipos entero: long, int, short, char y byte que pueden modificar los bits de sus operandos.
|
|
|
NOT un�rio a nivel de bit |
|
AND a nivel de bit |
|
OR a nivel de bit |
|
OR exclusivo a nivel de bit |
|
Desplazamiento a la derecha |
|
Desplazamiento a la derecha rellenando con ceros |
|
Desplazamiento a la izquierda |
|
AND a nivel de bit y asignaci�n |
|
OR a nivel de bit y asignaci�n |
|
OR exclusivo a nivel de bit y asignaci�n |
|
Desplazamiento a la derecha y asignaci�n |
|
Desplazamiento a la derecha rellenado con ceros y asignaci�n |
|
Desplazamiento a la izquierda y asignaci�n |
Determinan la relaci�n que un operando tiene con otro, espec�ficamente igualando y ordenando. El resultado de la operaci�n es un valor booleano.
|
|
|
Igual a |
|
Distinto de |
|
Mayor que |
|
Menor que |
|
Mayor o igual que |
|
Menor o igual que |
A diferencia de algunos lenguajes(C/C++) los valores booleanos son True y False, valores no num�ricos.
Operan �nicamente con operandos booleanos y dan como resultado otro operador booleano.
|
Descripci�n |
|
AND l�gico |
|
OR l�gico |
|
XOR l�gico(OR exclusivo) |
|
OR en cortocircuito |
|
AND en cortocircuito |
|
NOT unario l�gico |
|
Asignaci�n AND |
|
Asignaci�n OR |
|
Asignaci�n XOR |
|
Igual a |
|
Distinto de |
|
If-then-else ternario |
El operador OR en cortocircuito tiene como resultado verdadero cuando el primer operador es verdadero independientemente del segundo operador. De forma similar el operador AND en cortocircuito es falso cuando el primer operador es falso independientemente del valor del segundo operador.
El formato general del operador ternario es:
Expesion1 ? expesion2 : expresion3
Si Expresion1 es true se ejecutar� la expresion2, si es false se ejecutar� la expresion3.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|
Las sentencias de control el Java se pueden dividir en tres categor�as: Selecci�n, Iteraci�n y Salto.
|
|
|
|
|
if ( condici�n ) sentencia1; else sentencia2; |
|
if ( condici�n ) sentencia; else if ( condici�n) sentencia; else if ( condici�n) sentencia; . . else sentencia; |
|
|
switch ( expresi�n){ case valor1: sentencia; break; case valor2: sentencia; break; . . . . default: sentencia; } |
|
|
|
while ( condici�n) { sentencias; } |
|
do { sentencias; } while (condici�n) |
|
|
for (iniciaci�n, condici�n, iteraci�n) { sentencias; } |
|
|
|
Para escapar de un switch. Para escapar de un bucle |
|
Escapa de la iteraci�n del bucle pero continua en el mismo bucle | |
|
Volver expl�citamente desde un m�todo |
Como indicamos en el primer art�culo Java es un lenguaje que se dise�� partiendo de cero y como resultado de esto fue una aproximaci�n limpia y �til a la programaci�n orientada a objetos. De hecho todos los programas Java son orientados a objetos. Como puede comprender no intente buscar en este art�culo y los siguientes algo para ampliar sus conocimientos sobre la programaci�n orientada a objetos, para ello hay literatura abundante y amplia para profundizar en su conocimiento tanto como se quiera. Pero es tan importante la programaci�n orientada a objetos para Java que es necesario entender sus principios b�sicos antes de empezar a programar en este lenguaje. No nos queda m�s remedio que manejar y utilizar elementos principios y caracter�sticas de este paradigma aunque siempre seguiremos la nomenclatura de Java e intentaremos de la forma m�s breve y clara posible definir los elementos que hacen de Java un lenguaje totalmente orientado a objetos.
Es el n�cleo de Java. Define la forma y naturaleza de un objeto, constituye la base de la programaci�n orientada a objetos. Una clase define un nuevo tipo de dato, este nuevo tipo se puede utilizar para crear objetos de este tipo.
Una clase es un modelo (plantilla) para un objeto y un objeto es una instancia de una clase. Java no soporta funciones o variables globales todas las acciones (m�todos) de los programas se definen dentro de una clase.
Una clase se define utilizando la palabra clave class. La forma general de la definici�n de una clase es:
Class nombre_de_clase { Tipo variable_de_instancia1; Tipo variable_de_instancia2; . . ... tipo variable_de_instancia; tipo nombre_de_metodo1(lista_de_parametros){ //cuerpo del m�todo } . . .. tipo nombre_de_metodo(lista_de_parametros){ //cuerpo del m�todo } } |
Los datos o variables definidos en una clase se llaman variables de instancias. El c�digo est� contenido en los m�todos, estos son los que determinan como se pueden utilizar los datos de una clase.
Para obtener objetos de una clase es necesario realizar dos pasos:
Este segunda paso se realiza utilizando el operador new, su formato general es:
variable = new nonbre_de_clase(); |
Donde variable es una variable de la clase que se quiere crear y nombre_de_clase es el nombre de la clase que est� siendo instanciado. Gr�ficamente pod�amos representar el creaci�n de un objeto de la forma siguiente:
El formato general de un m�todo es:
tipo nombre_del_metodo (lista_de_parametros) { //cuerpo del m�todo } |
tipo indica el tipo de dato devuelto por el m�todo, puede ser cualquier tipo valido incluido los tipos de clase o no puede devolver ning�n valor (void).
La lista de par�metros es una secuencia de parejas de tipo-identificador separados por coma. Los par�metros son variables que reciben el valor de los argumentos que se pasan al m�todo, si el m�todo no tiene par�metros entonces la lista estar� vac�a.
Los m�todos que devuelven un valor distinto de void a la rutina que lo llama utiliza:
return valor; |
Donde valor es el valor devuelto.
Java da mucho poder y flexibilidad a los m�todos por lo que iremos, desde aqu�, hasta el final del art�culo, describiendo cada uno de los aspectos m�s importantes de los m�todos.
Aunque antes de seguir avanzando repasaremos todo lo visto hasta ahora viendo un ejemplo simple. Crearemos una clase que calcule la capacidad de un recipiente rectangular(como una especie de piscina):
|
|
class capacidad { double largo; double ancho; double alto; void CalcVolumen () { double volumen ; volumen= largo*ancho*alto; System.out.println("Volumen:" + volumen); } } |
Como vemos, hemos definido una clase que hemos llamado
capacidad en la que definimos tres variables de
instancia: largo, ancho y alto. Tambi�n
se define un m�todo que calcula el volumen del recipiente.
El archivo fuente lo llamaremos capacidad.java,
al compilarlo crear� una clase llamada
capacidad.class
|
Esta clase por s� sola no realiza ninguna acci�n ya que no es un "applet" ni tiene el m�todo main() para ejecutarlo desde la l�nea de comando. Hemos creado un modelo o plantilla para crear objetos o instancias de esta clase. Para poder ejecutarla crearemos una clase que se pueda ejecutar desde la l�nea de comandos.
|
|
class ejemplo { public static void main(String Arg[]){ capacidad p1=new capacidad(); capacidad p2=new capacidad(); p1.largo = 16; p1.ancho=3; p1.alto=2; // p2.largo = 25; p2.ancho=6; p2.alto=3; // p1.CalcVolumen(); // p2.CalcVolumen(); } } |
Declaramos dos variables del tipo capacidad p1,p2. Con el operador new creamos dos objetos del tipo capacidad a los cuales podemos referenciarnos a trav�s de las variables p1, p2. A continuaci�n asignamos valores a las variables de cada uno de los objetos creados. Llamamos al m�todo CalcVolumen del objeto referenciado en p1 y como resultado tendremos por pantalla: "el volumen es 80". Idem para el objeto referenciado en p2. Obtenemos como resultado: "el volumen es 450" |
Cuando se ejecuta p1.CalcVolumen(), el interprete de Java transfiere el control al c�digo definido dentro de CalcVolumen(), una vez que se ejecuta todas las sentencias el control vuelve a la rutina llamante y la ejecuci�n continua en la l�nea siguiente a la llamada.
La mayor�a de los m�todos se utilizan con par�metros que permiten generalizarlos. Adem�s los m�todos pueden a su vez devolver valores por lo que podemos construir m�todos que puedan trabajar con diversidad de datos y puedan ser utilizados en diferentes situaciones.
Nuestro ejemplo lo mejoraremos:
|
|
class capacidad { double CalcularVolumen (double l, double a, double p){ double volumen=l*a*p ; return volumen; } } |
El m�todo CalcVolumen ha sido modificado para que reciba tres par�metros. Adem�s se define para que devuelva un tipo double, acci�n que realiza con la instrucci�n return volumen. |
class ejemplo { public static void main(String Arg[]) { capacidad p1=new capacidad(); capacidad p2=new capacidad(); double vol; vol=p1.CalcVolumen(10,3,2); System.out.println("Volumen:" + vol); // vol=p2.CalcVolumen(25,5,2); System.out.println("Volumen:" + vol); } } |
La llamada al m�todo se realiza enviando los par�metros deseados. Adem�s devuelve el valor del m�todo en la variable vol, que debe ser del mismo tipo que el m�todo. |
Un aspecto importante de las clases son los constructores. Estos definen qu� ocurre cuando se crea un objeto de una clase. La mayor�a de las clases definen expl�citamente sus propios constructores dentro de la definici�n de la clase, pero si no se especifica, entonces Java utiliza un constructor por defecto (esto es lo que ocurre en nuestro ejemplo).
Un constructor incluido en una clase tiene exactamente el mismo nombre que la clase, sint�cticamente es similar a un m�todo. Es ejecutado autom�ticamente despu�s de crear el objeto, antes de que termine el operador new.
Los constructores no devuelven ning�n tipo, ya que impl�citamente devuelve el propio tipo de la clase. La tarea del constructor es inicializar todo el estado interno de un objeto para que el c�digo que crea una instancia tenga el objeto integro y utilizable inmediatamente. Los constructores por defecto inicializan las variables de instancias por defecto. Como ocurre con los m�todos, los constructores pueden tener par�metros con lo que hacen a estos muchos m�s �tiles. Volveremos a modificar nuestro ejemplo para ver estos nuevos aspectos.
|
|
Class capacidad { double largo; double ancho; double alto; // capacidad(double l, double a, double p){ largo=l; ancho=a; altao=p; } // void CalcularVolumen () { double volumen ; volumen= largo*ancho*alto; return volumen; } } |
A la clase se le a�ade un constructor, que tiene aspecto de un m�todo con el nombre igual a la clase pero sin tipo. Este constructor inicializa las variables de instancias declaradas con los argumentos pasados. |
class ejemplo { public static void main(String Arg[]) { capacidad p1=new capacidad(10,5,2); capacidad p2=new capacidad(25,6,2); double vol; vol=p1.CalcVolumen(); System.out.println("Volumen:" + vol); // vol=p2.CalcVolumen(); System.out.println("Volumen:" + vol); } |
Cuando no hay ninguna referencia a un objeto se asume que este objeto no se va a utilizar m�s y la memoria utilizada por dicho objeto se libera. No hay necesidad de destruir expl�citamente a los objetos, este proceso se hace de forma espor�dica y autom�tica durante la ejecuci�n del programa.
No obstante para a�adir un finalizador a una clase se realiza a�adiendo un m�todo finalice(), el interprete ejecutar� este m�todo cuando destruya al objeto. En este m�todo incluiremos aquellas acciones que se quieran realizar antes de destruir al objeto.
El polimorfismo (una interfaz m�ltiples m�todos) es uno de los pilares b�sicos de la programaci�n orientada a objetos. Java implementa el polimorfismo por medio de la sobrecarga de m�todos.
En una clase se pueden definir varios m�todos con el mismo nombre, pero con lista de par�metros distinta o tipo de valores devuelto. Cuando se invoca al m�todo sobrecargado el interprete de Java utiliza el tipo y/o los argumentos con los que se invoca para determinar la versi�n del m�todo que debe ejecutar.
Cada versi�n del m�todo sobrecargado puede realizar tareas distintas aunque esto hace totalmente imposible el polimorfismo, por lo que es muy recomendable que la sobrecarga de m�todos implique una relaci�n. De la misma forma que se sobrecargan los m�todos se pueden sobrecargas los constructores.
En general los lenguajes de programaci�n permiten pasar los argumentos de dos formas:
En Java existen tambi�n dos medios para pasar par�metros a los m�todos. Si el argumento es un tipo simple �ste se pasa por valor, pero cuando el argumento es un objeto se pasa por referencia.
Otro pilar b�sico de la programaci�n orientada a objeto es la encapsulaci�n. �sta relaciona los datos con el c�digo que la utiliza. Adem�s la encapsulaci�n proporciona el control de acceso, es decir que parte del programa puede acceder a los miembros de una clase.
Las especificaciones de acceso en Java son public, private y protected. Cuando un m�todo o variable de instancia se define como public entonces puede ser accedido por cualquier parte del programa. Si se define como private s�lo puede ser accedido por otros miembros de su clase. Por defecto todos los m�todos o variables de instancia (miembros) son public (para su propio paquete). El especificador protected se utiliza cuando se trabaja con herencias que veremos a continuaci�n.
Los tres elementos que define la programaci�n orientada objetos son el polimorfismo, la encapsulaci�n y por fin la herencia, por este mecanismo podemos definir una clase general (superclase) con unas caracter�sticas comunes y esta superclase puede ser heredada por otras clases m�s especificas a�adiendo cada una de estas cosas particulares.
Para que una clase B herede las caracter�sticas de una superclase A, en la definici�n de la clase B haremos:
Class B extends A { // defincion de la clase } |
La clase B incluye todos los miembros de la superclase A, �sta �ltima es tambi�n una clase aut�noma y puede ser utilizada libremente, adem�s B puede se una superclase de otra clase.
Java no permite una herencia m�ltiple de varias superclases en una subclase.
Si en la superclase hay miembros definidos como private no pueden ser accedidos por las clases herederas. Cuando una subclase necesite referenciar a una superclase inmediata se puede utilizar la palabra reservada super. Con esto podemos llamar al constructor o a miembros de la superclase que han sido ocultados por la subclase.
Cuando un m�todo de una subclase tiene el mismo nombre y tipo que un m�todo de la superclase se dice que el m�todo est� sobrescrito. Esto constituye la base de unos de los aspectos m�s poderosos de Java que es la "Selecci�n de m�todo din�mica", es decir, es en tiempo de ejecuci�n cuando se resuelve qu� m�todo es el llamado, es el tipo del objeto que est� siendo referenciado y no el tipo de la variable de referencia el que determina el m�todo a ejecutar.
En el siguiente art�culo veremos en toda su potencia la herencia con las clases abstractas, interfaces etc.
Texto original en Castellano
P�ginas web mantenidas por Miguel �ngel Sep�lveda © Jose M. Fernandez 1998 LinuxFocus 1998 |