Introducción a la Programación Orientada a Objetos (POO)

APARTADOS

1) Introducción
2) Principios básicos de Java
  JVM, JDK, JRE
  Variables entorno
  Nuestro primer programa en Java
  Arrays y matrices
  Wrappers
  Entrada y salida
  Control de excepciones
  Constructores
  Liberar recursos y destructores
  Paquetes
  Propiedades "static"
  Métodos "static"
  Sobrecarga de operadores

 

1) Introducción

* Programación lineal
* Programación modular
* Programación estructurada
* Programación orientada a objetos

La POO es una técnica de programación que usa los objetos como bloque esencial de construcción.


Inicialmente si se quería almacenar información, por ejemplo de la entidad “cliente” existían una serie de datos “aislados”: nombre, domicilio, localidad, fecha última compra. Por tanto para hacer una factura todos estos elementos eran procesados de forma individual.

Abstracción

Un primer intento de construir tipos de datos más complejos, que se parecieran a las situaciones del mundo real y que pudieran ser tratados (más o menos) como una unidad, lo constituyen, entre otros, las "estructuras" del C clásico ("registros" en otros lenguajes). 

En esta etapa ya podía crearse una estructura "cliente" que albergara toda la información antes dispersa. Pero las herramientas para manipularlos seguían siendo elementos totalmente diferenciados.

Abstracción

Las clases son conjuntos de datos definidos por el programador, parecidos a las mencionadas "estructuras", pero con la importante novedad de incluir también las herramientas necesarias para su manipulación: operadores y funciones de la programación tradicional. 

Un TAD es un tipo de dato en el cual existe un conjunto de operaciones las cuales se pueden aplicar a ellos mismos. Un objeto también va a ser una colección de datos con operaciones asociadas pero tendrá una serie de propiedades que le dotan de una gran potencia:

Herencia
Encapsulación
Polimorfismo


Un objeto estará formado por datos y funciones ( a éstos se les llama miembros ). Tanto los datos como las funciones se “encapsulan” y solamente serán accesibles mediante las funciones miembro.
Las funciones miembro son también conocidas como “métodos”.

Las clases serán plantillas o modelos que describen objetos de un mismo tipo.
Para crear un objeto se tiene que instanciar una clase.


Un mensaje es la petición de un objeto a otro para que ejecute uno de sus métodos.
Un mensaje tiene tres partes:


Identidad objeto receptor
Método que se quiere ejecutar
Parámetros que necesite el objeto receptor para ejecutar dicho método


El principio de la herencia es que cada subclase comparta características de la clase de la cual se deriva.

Cada subclase tendrá sus propias características particulares.

NOTA IMPORTANTE: La herencia permite “reutilización de código” pues deja definir nuevas clases a partir de clases ya existentes


Una misma operación puede tener distintos comportamientos según el objeto del que se trate ( polimorfismo )

Por ejemplo el operador “+” tendrá distinto significado si tenemos operadores de tipo numérico que si tenemos operadores de tipo cadena (concatenación)


Cada objeto (instancia de una clase) tendrá sus propias variables pero compartirá sus métodos con el resto de los objetos de la misma clase.

Por ejemplo, un punto en el plano tendrá sus propias coordenadas y una serie de operaciones que se pueden realizar sobre él

Para poder representar las clases independientemente del lenguaje utilizado se usa UML (Unified Model Language-Lenguaje Unificado de Modelado). Las clases se representan mediante cajas: parte superior "nombre clase", parte intermedia "propiedades" y parte inferior "métodos". Tanto las propiedades como los métodos podrán ser públicos (+), privados (-) y protegidos (#):

Punto

- x: double

- y : double

+ Punto()

+ Punto(double, double)

+ trasladar (double, double)

+ distancia(Punto): double

+ abscisa(): double

+ ordenada(): double

Tanto los métodos, como las propiedades y las clases, tendrán la siguiente visibilidad:

NOTA: No asustarse, no tenéis que memorizar la tabla, podéis usarla cada vez que os haga falta consultando esta documentación.

2) Principios básicos de Java

JVM, JDK, JRE

Sun Microsystems elabora un lenguaje de programación para su uso en electrodomésticos (año 1991).

Java puede usarse, fundamentalmente, en los siguientes tipos de proyectos:

* Stand-alone Application. Aplicación independiente

* Applet. Aplicación ejecutada en el navegador. Primero se descarga la aplicación y luego es ejecutada en la máquina cliente.

* Servlet. Aplicación que se ejecuta en el servidor (no suele tener interfaz gráfica). Generalmente se desarrollan aplicaciones en las cuales se comunica el servlet con el applet.

Para el desarrollo de programas se usa el JDK(Java Development Kit o también conocido como SE - Standard Edition). Si solamente queremos "ejecutar" código en Java hará falta únicamente el JRE(Java Runtime Environment).

El intérprete de Java es el JVM(Java Virtual Machine). El JVM "interpreta" el byte code(código intermedio: código menos abstracto, más compacto y más orientado a la máquina ) transformándolo al código de la CPU usada.

Por tanto habrá que realizar dos pasos:

1) Compilar programas para convertilos en bytecode. (javac ejemplo.java)

2) Ejecutarlo mediante un intérprete de bytecode. (java ejemplo)

 

 

 

Variables entorno

Para poder llamar a java.exe o a javac.exe se tendrá que conocer la ruta. Por tanto habrá que especificarla en la variable de entorno PATH (set PATH=.;c:\jdk1.2\bin;%PATH%).

¿Cómo sabe dónde se encuentran las librerías o las clases?. Para ello habrá que especificarlo en la variable de entorno CLASSPATH (set CLASSPATH=.\;c:\jdk1.2\lib\classes.zip;%CLASSPATH%). El punto que hay después del igual es imprescindible escribirlo pues es la forma de indicar que busque también en el directorio actual.

Existe la posibilidad de especificar la carpeta donde se encuentran las librerías en el comando de ejecución. Ejemplo:

java -classpath .\;c:\proyecto\misClases.jar programaCreado (también se puede usar -cp para no tener que escribir la palabra -classpath)

En el ejemplo anterior podéis observar un archivo con extensión .jar. Este tipo de archivos se usa para comprimir en un único archivo un cierto contenido para su posterior distribución y uso. Para ejecutar un archivo .jar se escribe la siguiente sentencia: java -jar archivo.jar.

Las variables de entorno en Windows XP se configuran en: Propiedades del sistema>>Solapa Opciones Avanzadas>>Variables de Entorno.

Si tienes propiedades con el propio intérprete de Java tendrás que dirigirte al registro de windows (regedit): MI PC>>HKEY_LOCAL_MACHINE>>SOFTWARE>>JavaSoft>>Java RunTime Environment. En esa clave tendrás que modificar el valor de "CurrentVersion" (algunas ves se tendrá que cambiar la versión, por ejemplo algunas aplicaciones solamente funcionan con versiones concretas como la 1.6...)


EJERCICIO:

1) Bájate la última versión JDK también conocida como SE (Standard Edition)

2) Comprueba que está bien configurada. Ir a la interfaz de comandos (INICIO>EJECUTAR>"cmd") y escribir el comando "java -version". Si no aparece la versión, configura las variables de entorno tal y como se explica justo en este apartado

3) Bájate la API de Java buscándola en la página de Sun o con un motor de búsqueda(Java™ Platform, API Specification). Descomprímela en una carpeta y añade en favoritos el archivo "index.html" de dicha carpeta.


Nuestro primer programa en Java

Descargue el JDK y haga los cambios en las variables de entorno tal y como se dijo en el apartado anterior.

Crea un archivo con un editor de texto puro y llámalo "PrimerProgramaJava". Copia el siguiente contenido:

//***************************************************************************************************************

//Así se escribe un comentario en Java para una única línea
/*Comentarios
de más
de una línea*/

class PrimerProgramaJava
{

//==>DECLARACIÓN DE CONSTANTES
//"final" se usa para declarar una CONSTANTE. Por tanto no se podrá cambiar su valor. Generalmente también se declara como "static" para no tener que crear un //objeto si únicamente se va a usar la constante. Puedes ver la explicación del modificador "static" en los siguientes apartados
//final String saludo=" hola a todos";

  //==>FUNCIÓN PRINCIPAL. Toma como parámetro los argumentos enviados al programa(array de tipo String)
//==>CLASE "String".
//Se pueden declarar variables String de dos formas:
//1)String cadena1= "Hola a todos";
//2)String cadena2 = new String("Hola a todos");

public static void main(String args[])
{
   

//Se crea una referencia a la clase mediante la variable "primero". Porque aunque el main esté dentro de la clase si queremos

//usar las propiedas y/o métodos de la clase tendremos que crear una instancia de la misma.

PrimerProgramaJava primero;

//Se instancia la clase(se crea el objeto). Por tanto se llamará al constructor
primero = new PrimerProgramaJava();

//==>El operador "+" en cadenas servirá para la concatenación
//==>println es un método para la visualización de cadenas. "out" es una variable
//estática y "System" es una clase (esta clase pertenece al package por defecto
//"java.lang")

//Se está accediendo a la propiedad "saludo"
System.out.println("Buenas" + primero.saludo);

  }  
}    

//***************************************************************************************************************

En la línea de comandos primero tendrás que crear el archivo bytecode:

javac PrimerProgramaJava.java

Una vez generado el archivo .class ahora podrás ejecutarlo:

java PrimerProgramaJava

NOTA: Lee el código fuente del programa anterior


EJERCICIO: Usando una IDE de Java (Eclipse, NetBeans, JBuilder, etc...) crear el proyecto "proyectoPunto" y codifica el siguiente código:

c l a s s Punto {

/ / Coordenadas punto
pr ivate double x , y ;


/ /Incrementa coordenadas del puntro
public void t r a s l ada r ( double a , double b ){

x = x + a ;
y = y + b ;

}

/ / Devuelve la distancia entre este punto y el argumento
public double di s t anc i a ( Punto pto ) {

return Math . sqr t (Math .pow( x - pto . x , 2) + Math .pow( y - pto . y , 2) ) ;


}
/ / Devuelve coordenada x
public double abs c i s a ( ) { return x ;
}
/ / Devuelve coordenada y
public double ordenada ( ) { return y ;
}
/ / Cambia valor de abscisa
public void abs c i s a ( double nuevaX) { x = nuevaX ;
}
/ / Cambia valor de ordenada
public void ordenada ( double nuevaY) { y = nuevaY ;
}

}


EJERCICIO: Crea el procedimiento main para probar el funcionamiento de la clase (public static void main(String args[]))


Arrays y matrices

Los arrays en Java son arrays de objetos. Para crear un array habrá que usar el operador "new" seguido del tipo y el número de elementos:

double []datos; //Se crea una referencia. Se podría poner también double x[];

datos= new double[200]; //Se crea el array

//Las dos instrucciones anteriores se podrían haber realizado en una sola: double []datos = new double[200];

//Otras formas de inicializar los arrays

String diasSemana[] = {"lunes", "martes", "miercoles", "jueves", "viernes", "sabado", "domingo"};

//Si se ejecuta "diasSemana.length" devolverá el número de elementos de la tabla

//Arrays de objetos:

MiClase objetos[]= new MiClase[10]; /

for (i=0;i<10;i++)

objetos[i] = new MiClase();

//MATRICES

double [][]datos;

datos = new double[numero_filas][];

for(i=0;i<numero_filas;i++)

datos[i] = new double[numero_columnas];

//También se puede crear una matríz de la siguiente manera

float datosSalario = new float[4][3];

//Forma de inicializar la matriz

int [][]datosEnterosMatriz = { {0,1,2},

{3,4,5}};


EJERCICIO: Imprimir en pantalla el nombre de los doce meses que conforman un año. (Pista: Puedes ver en los ejemplos de arriba cómo se ha declarado la variable "diasSemana"). Para saber cuántos elementos tiene el array será obligatorio el uso de "length".


EJERCICIO: Crear el proyecto "sumaNumero". Este proyecto tendrá la clase "suma.java". Esta clase mostará en pantalla la suma de 20 números, estos números serán números seleccionados al hazar.

NOTA PARA HACER EL EJERCICIO:

1) Habrá que importar la clase Random (import java . u t i l .Random;)

2) Se creará un objeto de la clase Random (Random rnd = new Random( ) )

3) Para generar un número aleatorio, por ejemplo del tipo double, se haría de la siguiente manera: rnd . nextDouble ( ) ; Queda como ejercicio que el programador busque en la API de Java qué método devuelve un valor entero.


Wrappers (Clases envoltorio)

Los tipos primitivos (float, char, double, long, byte, short, etc...) se pasan por "valor" a los procedimientos, sin embargo los objetos se pasan por referencia. Por tanto no se podrían modificar las variables que pertenezcan a un dato primitivo, y una solución para ello es usar los "Wrappers" (envoltorios).

Para cada tipo primitivo existe un Wrapper: Float, Double, Long, Integer, Byte, etc...

Ejemplo:

Integer num = new Integer(17);

Por tanto Java hace distinción entre tipos primitivos y clases. Supongamos el caso de disponer de una lista que sea capaz de almacenar objetos y nosotros poseemos una tabla de enteros -> SOLUCIÓN: Convertir estos tipos primitivos en sus envoltorios correspondientes, este proceso sería la encapsulación. Ejemplo:

Integer [ ] l i = new Integer [ 3 ] ;
l i [ 0 ] = new Integer ( 4 ) ;
l i [ 1 ] = new Integer ( ” 87 ” ) ;
l i [ 2 ] = new Integer (22) ;

Lo que ocurre es que Java es capaz de hacer la conversión sin indicarlo de forma explícita. Ejemplo:

Integer [ ] l i = new Integer [ 3 ] ;
l i [ 0 ] = 4;
l i [ 1 ] = Integer . par seInt ( ” 87 ” ) ;
l i [ 2 ] = 22;


EJERCICIO: Dado un array de 5 números ordenarlos mediante el método de la burbuja.

NOTA: Los 5 números no serán introducidos por el usuario sino que vendrán ya definidos en el propio código

Entrada y salida

Salida estándar

System.out.println("Buenas tardes");

"println" es un método de visualización. Soporta como parámetro una cadena, un carácter, etc...

(void println(char x), void println(char[] x),void println(double x),void println(float x),void println(int x),void println(long x),

void println(String x),...)

"out" es una variable estática y "System" es una clase (esta clase pertenece al package por defecton"java.lang")

Entrada estándar

Para la entrada estándar se podría usar el objeto "in". Ejemplo:

int c;

c=System.in.read();

Usar el objeto "in" sería bastante pesado pues se tendría que recuperar carácter por carácter. Para solucionar esto se podría redireccionar la entrada de tal forma que se capture líneas (secuencia de caracteres hasta pulsar la tecla ENTER). Para ello primero habrá que importar el package "io" y seguir los siguientes pasos:

import java.io.*;

//Primer paso. Se redirecciona la entrada.

InputStreamReader entrada = new InputStreamReader(Sytem.in);

//Segundo paso. Crear un buffer de entrada para la entrada redireccionada en la sentencia anterior

BufferedReader bufferEntrada = new BufferedReader(entrada);

//Lógicamente se podría haber creado en una única línea:

//BuffedReader bufferEntrada = new BufferedReader(new InputStreamReader(System.in));

//YA SE PUEDE USAR LA ENTRADA Y EL BUFFER CREADO

//Para capturar una línea escribir la siguiente sentencia

String cadena = bufferEntrada.readLine();

El código de arriba funciona perfectamente. Pero, ¿qué ocurre si lo que queremos es capturar un entero?. La respuesta es muy sencilla se captura una cadena y luego se convierta a tipo entero:

int numero = Integer.parseInt(cadena);


EJERCICIO: Crea la clase "capturaEntrada" según la especificación del siguiente diagrama:

capturaEntrada

- cadenaCaptura: String

+ capturaLinea():String

+ capturaEnteroPrimitivo():int

+ capturaEnteroLargoPrimitivo():long

+ capturaRealPrimitivo(): float

+ capturaDoblePrimitivo(): double

+ capturaBooleanPrimitivo():boolean

+ capturaEntero():Integer

+ capturaEnteroLargo():Long

+ capturaReal():Float

+ capturaDoble(): Double

+ capturaBooleanPrimitivo():Boolean

Todos devolverán el tipo de dato indicado.

La comprobación de errores se hará en un ejercicio posterior (es decir, que se solicite al usuario un entero y él introduzca por ejemplo un número decimal)


Control de excepciones

Los programas pueden producir errores en tiempo de ejecución. Ejemplos: un fichero que no existe, un índice fuera de rango, etc...

Dentro de "try" irían las instrucciones que pueden provocar excepciones, en los bloques "catch" irían los manejadores de excepciones.

"finally" es opcional, y su función es la de dejar el programa en un estado correcto independientemente de lo que suceda dentro del bloque try (cerrar ficheros, liberar recursos, ...). Siempre se ejecuta

PrintWriter out = null;

try {

out = new PrintWriter(new FileWriter(“out.txt”));
for (int i = 0; i < SIZE; i++) {
out.println(“valor: ” + i + “ = ” + v[i]);

}


}

catch (ArrayIndexOutOfBoundsException e) {

System.err.println(“Índice fuera de rango”);

}

catch (IOException e) {


System.err.println(“out.txt no pude abrirse");


}

finally {


if (out != null) {


out.close();


}


}
}

A veces, es mejor no tratar la excepción y dejar que el método superior que haya invocado a dicho método sea el que los trate ( pila de llamadas):

public void escribeLista() throws IOException, ArrayIndexOutOfBoundsException

Se puede provocar una excepción con la instrucción "throw":

public void pop() throws EmptyStackException {


if (size == 0) {
throw new EmptyStackException();
}

Ejemplo de uso de control de excepciones:

public void insertar(int pos, T elem) {


// Se comprueba que la posición "pos" está dentro del rango permitido
if ((pos < 0) || (pos > tamaño)) {


throw new RuntimeException("Índice fuera de rango");


}

else {


if (tamaño >= lista.length) {


//Si lista esta llena se duplica su tamaño
T[] listaNueva = (T[]) new Object[2 * lista.length];


for (int i = 0; i < tamaño; i++) {


listaNueva[i] = lista[i];


}


lista = listaNueva;


}


// Ya se puede hacer la inserción...
for (int i = (tamaño - 1); i >= pos; i--) {
lista[i + 1] = lista[i];

}


lista[pos] = elem;
tamaño++;


}
}


EJERCICIO: Modifica la clase "capturaEntrada" para que detecte (mediante control de excepciones) entradas no válidas. Ejemplo: se solicita al usuario un entero y escribe un número decimal. Observar el ejemplo anterior para poder realizar este ejercicio


Constructores

Los constructores indican cómo crear objetos estableciendo sus valores iniciales. El nombre de los constructores tiene que coincidir con el nombre de la clase.

c l a s s Punto {

/ / Constructor para inicializar ambas coordenadas a cero
public Punto ( ) { x = y = 0 ; }
/ / Constructor que inicializa las dos coordenadas a los valores dados
Punto ( double a , double b ) { x = a ; y = b ; }

....................

}


EJERCICIO: Al proyecto "proyectoPunto" añadir los dos constructores definidos en el apartado anterior. Verificar su funcionamiento


EJERCICIO: Comprobar y entender el funcionamiento del siguiente código (llamarlo "cPersona.java"):

//***************************************************************************************************************

//Descripción: Implementación de la clase cPersona. Esta clase almacena las propiedades: apellidos, nombre,
//edad y dni. Dispone de una serie de métodos para recuperar y establecer valores en dichos campos

//Autor: Daniel Leyva Cortés
//Contacto: transistor47@hotmail.com

import java.io.*; //Para poder recuperar datos de la "entrada" estándar habrá que importar el paquete "io"

class cPersona
{

 
//Declaración de propiedades de la clase:
private String apellidos;
private String nombre;
private int edad;
private long dni;
private boolean rellenado;

//==>DECLARACIÓN DE CONSTANTES
// final tipo_dato nombre_constante = valor;

public final int MAXIMO = 50;


//Declaración de métodos
//Contructor. Tendrá el mismo nombre que la clase, y lógicamente tendrá que se público

public cPersona()
{

    apellidos= new String("");
nombre = new String("");
edad=0;
dni = 0;
rellenado=false;
  }

//Método para visualizar las propiedades de la clase
public void visualiza()
{
    if(!rellenado)
{
      System.out.println("No se ha inicializado ningún valor");
    }
else
{
   



System.out.println("*******************************************");
System.out.println("Nombre: " + nombre);
System.out.println("Apellidos: " + apellidos);
System.out.println("Edad: " + edad);
System.out.println("DNI: " + dni);
System.out.println("*******************************************");
    }  
  }

//Métodos para agregar valores en los campos
public void setApellidos(String apellidos)
{
//IMPORTANTE: Esta sentencia en C++ sería "this->" pues era un puntero a un objeto, pero en Java
//es directamente un objeto
    this.apellidos = new String(apellidos);
rellenado= true;
  }

//Métodos para agregar valores a los campos
public void setEdad(int edad)
{

    this.edad = edad;
rellenado= true;
  }

//Métodos para agregar valores a los campos
public void setDNI(long dni)
{

    this.dni = dni;
rellenado=true;
  }

public void setNombre(String nombre)
{

    this.nombre = new String(nombre);
rellenado=true;
  }

//Programa principal. En este ejemplo lo usaremos únicamente para comprobar que
//la clase funciona correctamente

public static void main(String args[])
{

    cPersona persona;

String apellidosLocal;
String nombreLocal;
int edadLocal;
long dniLocal;

//Para capturar datos de la entrada estándar
cEntrada entrada = new cEntrada();

//Se instancia la clase(se crea el objeto). Por tanto se llamará al constructor
persona = new cPersona();

System.out.println("************************************");
System.out.println("Introduzca los siguientes datos");

System.out.print("Nombre: ");
nombreLocal = entrada.leeCadena();

System.out.print("Apellidos: ");
apellidosLocal = entrada.leeCadena();

//leeCadena devuelve únicamente cadenas => habrá que modificar el tipo de dato
System.out.print("Edad: ");
edadLocal = Integer.parseInt(entrada.leeCadena());

System.out.print("DNI: ");
dniLocal = Long.parseLong(entrada.leeCadena());

//Sentencias para probar el objeto creado
persona.setApellidos(apellidosLocal);
persona.setNombre(nombreLocal);
persona.setEdad(edadLocal);
persona.setDNI(dniLocal);

persona.visualiza();

  }    
class cEntrada
{
//Variables para la entrada y el buffer respectivamente
InputStreamReader entrada;
BufferedReader bufferEntrada;
  public cEntrada()
{
    //Primer paso. Se redirecciona la entrada.
entrada = new InputStreamReader(System.in);

//Segundo paso. Crear un buffer de entrada para la entrada redireccionada en la sentencia anterior
bufferEntrada = new BufferedReader(entrada);

//YA SE PUEDE USAR LA ENTRADA Y EL BUFFER CREADO

  }

public String leeCadena()
{
    String cadena = new String("");

//Inicializamos la cadena con valor cadena vacía pues si no se puede ejecutar el bloque try
//devolvería un valor nulo. Es más cuando se compile aparecería el siguiente error:
//variable cadena might not have been initialized
//return new String(cadena);

try
{

      //Se recupera cadena
cadena = bufferEntrada.readLine();
   

catch(java.io.IOException excepcionProducida )
{
//Si no se captura dicha excepción al intentar compilar este archivo aparecería el siguiente error:
//cPersona.java:146: unreported exception java.io.IOException; must be caught or
//declared to be thrown. En definitiva, la excepción tiene que ser capturada.

System.err.println("Problema al intertar leer de la entrada estándar...");
}

//Podría incluirse opcionalmente, en el tratamiento de las excepciones, el siguiente bloque
//finally
//{
//}
//finally es un bloque de código que siempre se ejecuta independientemente de si se ha producido o
//no alguna excepción

//Se devuelve cadena recuperada
return new String(cadena);

  }    
}      

//***************************************************************************************************************


Una vez analizado el código se podrá comprobar que conviven dos clases en el mismo archivo: cPersona y cEntrada. La clase principal tendrá que llevar el mismo nombre que el archivo al cual pertenece (esta clase será la que tendrá el procedimiento main definido)

Liberar recursos y destructores

El propio sistema se encargará de liberar de forma automática los objetos de los cuales se haya perdido referencia. Este sistema se denomina "Garbage collection".

Para llamar de forma explícita al recogedor de basura se escribirá la siguiente sentencia:

System.gc();

Existe un método especial denominado "finalize()". En este método se suelen cerrar ficheros, conexiones de red, etc... Este método sería el destructor de la clase

El garbage collector libera memoria reservada con el operador "new", pero si se usa "malloc y free" se tendrián que escribir las sentencias necesarias para liberar memoria.

El finalizador tendrá que llamar al finalizador de la superclase.

Paquetes

Los paquetes permiten almacenar y organizar archivos java, pues éstos actuan como contenedores de clases.

Para que una clase forme parte de un paquete (package) habrá que indicarlo de forma explícita en la primera línea de código (sin contar las líneas de comentarios):

package nombrePaquete;

Los paquetes hacen referencia a archivos bytecode (*.class)

Si se usa la sentencia "import nombrePaquete" se consigue abreviar los nombre de clases, variables y métodos cada vez que se use, sin tener que escribir el nombre del paquete.

Generalmente se nombran las clases con denominaciones únicas en internet, y para conseguirlo se usa el nombre del dominio. Ejemplo:

import es.almudeyne.infor2.ordenar.*; //Estas clases deberían estar en el directorio: classpath \es\almudeyne\infor2\ordenar

Hay un paquete que es importado automáticamente por el JDK y es el paquete java.lang. Por tanto no habrá que importarlo de forma explícita.

A continuación se verá un ejemplo en el cual estará organizado de la siguiente manera:

1) En la carpeta "d:\java\PaqueteEjemplo\Paquete" estarán ubicados los archivos "cCirculo.java" y "cEntrada.java". Estos dos archivos constituyen la implementación del paquete

2) En la carpeta "d:\java\PaqueteEjemplo\" estará situado el archivo "usaPaquete.java". La finalidad de este archivo es el uso del paquete creado.

//************************************ cCirculo.java ****************************************

//Descripción: Ejemplo de paquete en Java
//Autor: Daniel Leyva Cortés, Contacto: transistor47@hotmail.com
package Paquete;

public class cCirculo
{

  private double radio;
private final double PI= 3.1416;


public cCirculo(double radio)
{

    this.radio = radio;
  }

public double superficie()
{

    return(PI*radio*radio);
  }  
}    

//************************************ cEntrada.java ****************************************

public class cEntrada
{
InputStreamReader entrada;
BufferedReader bufferEntrada;
  public cEntrada()
{
    entrada = new InputStreamReader(System.in);
bufferEntrada = new BufferedReader(entrada);
  public String leeCadena()
{
    String cadena = new String("");

try
{

      cadena = bufferEntrada.readLine();
    }
catch(java.io.IOException excepcionProducida )
{
      System.err.println("Problema al intertar leer de la entrada estándar...");
    }
return new String(cadena);
  }    
}      

Para compilarlos habría que escribir en la línea de comandos las siguientes sentencias:

1) javac -cp d:\java\PaqueteEjemplo\ cCirculo.java

2) javac -cp d:\java\PaqueteEjemplo\ cEntrada.java

//************************************ usaPaquete.java ****************************************

/Descripción: Uso de un paquete simple
//Autor: Daniel Leyva Cortés, Contacto: transistor47@hotmail.com
//Se importa el paquete completo
import Paquete.*;

class usaPaquete
{

  public static void main(String args[])
{
    double radio;
double superficie;
cCirculo circ;

cEntrada entrada = new cEntrada();
System.out.println("Introduzca el radio del círculo: ");
radio = Float.parseFloat(entrada.leeCadena());
//Ahora ya podemos llamar al constructor
circ = new cCirculo(radio);
superficie = circ.superficie();
System.out.println("La superficie del círculo es : " + superficie);
  }  
}    

Para compilar este archivo la sentencia sería la siguiente:

javac -cp d:\java\PaqueteEjemplo\ usaPaquete.java

Para ejecutar el archivo:

java -cp d:\java\PaqueteEjemplo\ usaPaquete


EJERCICIO: Crear el paquete "estructuraDatos". Este paquete contendrá las clases "cPila" y "cCola". ç

La clase cPila tendrá que tener implementado los siguientes subprogramas: push (inserta valor en pila), pop (extrae elemento pila), numeroElementos (devuelve el número de elementos de la pila),elemento (devuelve el elemento pero sin destruirlo) y "toString" (visualiza el contenido completo de la pila)

La clase cCola tendrá que tener implementado los siguientes subprogramas: inserta, extrae, numeroElementos y "toString" (visualiza el contenido completo de la cola)

Ambas clases tendrán métodos de inicialización para cada una de las estructura de datos.


Propiedades "static"

Cada objeto tiene su propia copia de las propiedades de la clase sobre la que se instancia, pero ¿y si nos interesase que una propiedad fuese común para todos los objetos que perteneciesen a la misma clase?. Para ello están las propiedades estáticas. La zona de código donde se inicializan estas propiedades estáticas se denomina "inicializador estático". Solamente se llamará una vez al incializador estático.

Los inicializadores estáticos también se usan para llamar a métodos nativos. Ejemplo:
static
{
System.loadLibrary("libreriaNativa");
}

A continuación se va a ver un ejemplo con sus correspondientes comentarios:

class VariablesStatic
{
//Inicialización de la variable estática. Solamente se hará una vez
static float salario=0;

  //Métodos para actualizar la propiedad salario y para devolver el valor actual
public void agregaSalario(float valor)
{
salario+=valor;
}
public float devuelveSalario()
{
return(salario);
}

public static void main(String args[])
{
   

//Se crean una referencia a la clase
VariablesStatic obj1, obj2;
//En las siguientes sentencias es cuando realmente
//se crean los objetos
obj1 = new VariablesStatic();
obj2 = new VariablesStatic();

//Las dos siguientes llamadas van a modificar la misma propiedad
//pues esta es común a todos los objetos

obj1.agregaSalario(10);
obj2.agregaSalario(5);

System.out.println("\nSalario: " + obj1.devuelveSalario());

  }  
}    

Ejercicio 1:

Almacenar los datos de 5 empleados. Se registrarán: apellidos, nif y saldo. Cada vez que se rellenen los datos de un empleado tendrá que actualizarse una propiedad común denominada "saldo total". En cada momento se podrá consultar toda la información que contenga la clase. NOTA: Se tendrá que crear un objeto por empleado.

Ejercicio 2:

Desarrollar clase radio con propiedades x,y, radio (de tipo float); métodos: calculaLongitud (el cálculo es 2*PI*radio), calculaSuperficie (el cálculo es PI*radio*radio). Añadir un método que visualice el número de objetos de esa clase que se hayan creado

Métodos "static"

Los métodos que acceden únicamente a propiedades estáticas se pueden declarar como métodos estáticos.

Los métodos estáticos lógicamente no podrán usar el operador this.

Veamos un ejemplo de uso:

class MetodosStatic
{
//Inicialización de la variable estática. Solamente se hará una vez
static float salario=0

 

//Métodos para actualizar la propiedad salario y para devolver el valor actual

//IMPORTANTE: Se han declarado los métodos de tipo estático
public static void agregaSalario(float valor)
{
salario+=valor;
}
public static float devuelveSalario()
{
return(salario);
}

public static void main(String args[])
{

   

//Se crean una referencia a la clase
MetodosStatic obj1, obj2;
//En las siguientes sentencias es cuando realmente
//se crean los objetos
obj1 = new MetodosStatic();
obj2 = new MetodosStatic();

//Las dos siguientes llamadas van a modificar la misma propiedad
//pues esta es común a todos los objetos
obj1.agregaSalario(10);

//Directamente se puede poner el nombre de la clase seguido del método
MetodosStatic.agregaSalario(5);

System.out.println("\nSalario: " + MetodosStatic.devuelveSalario());

  }  
}    

Ejercicio 3:

Crear la clase cOperaciones, la cual cuenta con los siguientes métodos estáticos:calculaFactorial y calculaPotencia. También se podrá acceder a una constante que identifique al número PI, ésta estará en la propia definición de la clase

Sobrecarga de operadores

En c++ se puede sobrecargar cualquier operador, sin embargo en JAVA no. Un operador que sí se deja sobrecargar es el operador de concatenación de cadenas.

Si tenemos la siguiente sentencia:

cadenaC = cadenaA + cadenaB

Se interpreta en java de la siguiente manera:

cadenaC = new StringBuffer (cadenaA).append (cadenaB).toString ();

Volver al sumario