Este tutorial se usará en la asignatura Diseño de Aplicaciones Informáticas de los estudios de Ingeniero en Telecomunicaciones de la Universidad de Granada. Te ruego que no lo uses fuera de este ámbito, y recuerda a la autora y el tiempo que le dedicó.
Objetivos
Repasar los conocimientos aprendidos en primer curso sobre el lenguaje Java
Repasar conceptos de orientación a objetos, viendo cómo se implementan en Java.
Analizar con más profundidad los conceptos de herencia, ligadura dinámica y polimorfismo.
Hacer programas sencillos usando estructuras de control y todos los conceptos anteriores.
Recordar que siempre hay que hacer un diseño antes de sentarse a programar.
Ver también:
http://pisuerga.inf.ubu.es/lsi/Invest/Java/Tuto/Autores.htm
boolean: true y false,
char: 'a', \n,...
byte: entero de 8 bits
short: entero de 16 bits
int: entero de 32 bits
long: entero de 64 bits
float: 15.3, 1.8e1, (32bits)
double: (64 bits)
int numero;
int numero=9;
int numeros[]={1, 2, 3}
int numeros[] = new int[10];
numeros[1]=8;
char letras[]= new char[8];
Declaración de la clase Trabajador
public class Trabajador {
private String nombre; //variables de instancia
private int edad;
static String oficio; //variables de clase
Trabajador (String n, int e) { //constructor, inicializador
nombre= n; edad= e;}
static void trabajarEn( String o ){oficio=o;} //método de clase
public void cantar( )
{System.out.println("lala");} //método de instancia
}
Para el ocultamiento de información, y siguiendo la orientación a objetos todas las variables de instancia deberían ser declaradas como privadas, es decir, sólo podrían ser consultadas mediante un método de instancia.
Subclases, Herencia
Clase Estudiante que hereda de Trabajador
class Estudiante extends Trabajador {
private String estudios;
Estudiante(String n, int e, String c)
{ super(n, e);
estudios=c; }
public void estudiar(int creditos)
{....};
}
Agregación
Clase Empresa que contiene una variable Trabajador
class Empresa{
private String nombreEmpresa:
private String CIF;
private Trabajador empresario;
}
Uso
class Universidad {
private String nombreUni;
public void matricular (String
carrera, int creditos){ ...}
}
/* Se supone aquí que el método estudiar de la clase Estudiante hace uso o llama al método matricular de la clase Universidad . Ver código*/
4. Objetos (heap)
String nombre; //declaración
nombre= new String("Juanito"); //asignación
Trabajador p = new Trabajador("Pepito", 20);
Estudiante e = new Estudiante("Ana", 19,"Física");
5. Operaciones
· Precedencia de operadores:
(), [], aritméticos, relacionales, lógicos, asignación
· Operadores lógicos especiales:
true && false
true | | false
· Concatenación de cadenas de caracteres:
'H' +"ola " + "primo"
· Conversiones:
double d = 7.99
long l = (long) d //"conversión" o "casting"
(float) Math.sqrt(8);
· Tipos básicos y clases
// CREA un objeto de clase Integer a partir de una variable de tipo int
int j=8;
Integer n = new Integer(j);
// OBTIENE una variable de tipo int a partir de un objeto de la clase Integer. Es un mensaje.
int m;
m = n.intValue() /
int numero=9;
int otroNumero = 10;
numero = otroNumero;
String nombre = "Juanito";
String otroNombre = "Pedro";
nombre = otroNombre;
char[] unArray = new char [9];
char[] otroArray
otroArray = unArray;
String nombre = "Ana";
Trabajador curro = new Trabajador("Juan", 21);
nombre = curro; !!!!!
class Persona {
private String nombre;
private int edad;
public void cantar( ){System.out.println("lalala"};
class Estudiante extends Persona { // subclase
private String estudios;
public void estudiar(int horas){....};
Estudiante (String carrera){ estudios=carrera} }
Creamos los siguientes objetos:
Persona p = new Persona();
Estudiante e = new Estudiante("Informática");
A los objetos podemos enviarles mensajes:
p.cantar()
e.cantar() // heredado de Persona
e.getClass() //heredado de Object
e.clone() //heredado de Object para copiar objetos
e.estudiar(3)
A las clases también podemos enviarles mensajes (sólo para consultar su estado):
Estudiante.getSuperClass();
Estudiante.isInstance(e);
Persona.getMethods();
8. Instrucciones de flujo de control
· int salida;
if ((hora > 12) & (hora<24))
salida=hora%12;
else
if (hora>24)
salida=-1;
else salida=hora;
return salida;
· switch (n)
case 0 : case 1: return si;
case 2: return no;
default: return casi;
· int suma=0;
int[] numeros = {1, 2, 3};
for (int i=0 ; i <= 2 ; i++) //la primera posición es la 0
suma = suma + numeros[i];
return suma;
· while (suma < 30) {
if (valor.lengh > i)
break;
else
i++;
suma += valor[i]; }
· do .... while(... )
Para usarlas hay que incluir al principio del programa: import java.util.*;
· Vector
Vector vehiculos = new Vector();
Coche c = new Coche("111 C");
Moto m = new Moto("222 M", 750);
vehiculos.addElement(c);
vehiculos.addElement(m);
System.out.println("Hay " + vehiculos.size() + " vehículos");
vehiculos.removeElement(m);
vehiculos.elementAt(0);
System.out.println("Matricula: " +
((Coche)vehiculos.elementAt(0)).matricula() );
/* Ver clase. Se supone que existe una clase Coche con variable de instancia matricula y un método matricula() que devuelve el valor de la variable matricula para un objeto coche. */
/*En la última instrucción es necesario un casting para indicar al compilador que debe buscar el método matrícula() en la clase Coche, y no en la clase Object como haría por defecto */
· Stack
String salida;
Stack pila = new Stack();
pila.push(7);
pila.push("dos");
if (! pila.empty())
salida= (String)pila.pop();
else salida="pila vacía";
· Otras colecciones son List, Collection, Dictionary,
HashTable, Map y Set.
10. Delimitación del acceso a una clase, variable o método.
· Clase
public: acceso desde todas las clases (por defecto sólo es accesible a las clases que estén dentro de su paquete)
abstract: la clase no puede instanciarse y debe tener un método abstracto
final: no se puede heredar de la clase
· Variable o método
public: accesible desde todas las clases
protected: sólo es accesible por sus subclases
package: es el acceso por defecto. Accesible a las clases que hay dentro del paquete.
private: accesible sólo para los métodos de la propia clase
static: indica que una variable o método es de clase, no de instancia
final: para variables con valor constante o métodos que no pueden ser sobreescritos
abstract: sólo para métodos, indicando que deben ser sobreescritos por las subclases
11. Interfaces
interface Ejercicios {
public int correr(int k); // no se implementa }
//clase basada en una interfaz
class Dieta implements Ejercicios {
public int totalCorrido = 40;
public int correr(int k) { return ( totalCorrido+ k) };}
Hay dos formas de usarlas:
1 - Llamada explícita.
Declaración de una clase que maneja excepciones
class TopeException extends Exception {}
Uso de la excepción
public void
temperatura(int temp){
try {
if (temp > 40)
throw (new TopeException());
// llamada explícita a la excepción
else
System.out.println("Temperatura: " + temp +
" grados");}
catch (TopeException t)
{System.out.println ("Hay un error: demasiado calor");
return;}
}
2 - Llamada automática cuando se produce un error
public void pruebaDivide(){
int d, a;
try { d = 0;
a= 3/d; //provoca un error, y busca una sección cath que lo trate
System.out.println("por aqui no pasa y esto no sale");
}
catch (ArithmeticException e) { //La clase que maneja esta excepción existe
System.out.println("No puedes dividir por 0"); }
}
13. Lectura de un String y un número por teclado
import java.io.*;
class Lectura{
public static void main(String args[]) throws IOException {
//definición de Stream para leer Strings
DataInputStream s = new DataInputStream(System.in);
//definición de Stream para leer números
StreamTokenizer n= new StreamTokenizer(System.in);
String nombre;
System.out.println("Escribe tu nombre ");
nombre= s.readLine();
int edad;
System.out.println(Escribe tu edad);
n.nextToken();
edad= (int) n.nval; //el casting permite reconocer el int leído
System.out.println("Tu nombre es: "+ nombre+ y tienes +
edad + años.);
}
}
/*Obsérvese que es obligatorio el uso de una clase excepción para poder detectar errores en la entrada de datos*/
Este ejemplo muy sencillo muestra la definición de la clase Carta de la Baraja
import java.io.*;
public class Carta {
// VARIABLES DE INSTANCIA
private String palo;
private Integer numero;
// MÉTODO DE INICIALIZACIÓN. CONSTRUCTOR
Carta( String pal, Integer num) {
palo = pal;
numero = num; }
// MÉTODO QUE MUESTRA EL PALO. CONSULTOR
public String palo() {
return palo;}
// MÉTODO QUE MUESTRA EL NÚMERO. CONSULTOR
public Integer numero() {
return numero; }
// MÉTODO QUE CAMBIA EL VALOR DEL PALO Y NUMERO DE UNA CARTA. MODIFICADOR
private void ponerPaloNumero(String pal, Integer num) {
palo= pal;
numero= num; }
// MÉTODO MAIN. Contiene sentencias para probar sus métodos
public static void main (String args[]) {
String p= "oros";
Integer n= new Integer (7);
String palillo;
Integer numerillo;
System.out.println("Ahora voy a crear una carta que es el 7 de oros");
Carta cartilla = new Carta(p,n);
System.out.println("Ahora voy a mostrar las variables de instancia");
System.out.println(cartilla.palo());
System.out.println(cartilla.numero());
System.out.println("Ahora voy a modificar las variables de instancia");
numerillo= new Integer(10);
cartilla.ponerPaloNumero("bastos", numerillo);
System.out.println("Los nuevos valores son:");
System.out.println(cartilla.palo());
System.out.println(cartilla.numero());}
}
En Java, el polimorfismo de métodos se implementa con la sobrecarga de métodos: métodos con el mismo nombre, y mismo número y tipo de argumentos.
Una variable también puede ser polimórfica, es decir, cambiar de forma o de clase de objeto al que referencia durante la ejecución de un programa. El polimorfismo de una variable en Java está limitado de tal forma que una variable que referencia a un objeto sólo puede especializarse, tal y como ocurre en la vida real.
Ejemplo con polimorfismo en el método canta y en la variable fulanito
class Persona{
private String nombre;
protected String cancion;
public void canta(){System.out.println("la la la");}
} //End Persona
class Ladron extends Persona{
private int ganancias;
public void canta(){System.out.println("Yo no he sido");}
public void roba(int n){ ganancias= ganancias + n; }
} //End Ladron
class Juez extends Persona {
public void canta() {System.out.println("Soy la ley");}
} //End Juez
public class Poli5 {
// ejemplo de polimorfismo de mensaje canta
public static void main(String args[])
{
Persona fulanito = new Persona();
Ladron ladroncito = new Ladron();
Juez juececito = new Juez();
fulanito.canta(); // canta una persona
fulanito = ladroncito;
fulanito.canta(); // canta un ladrón
fulanito.roba(100);
//error de compilación: fulanito es Persona. ¿Solución?
fulanito = juececito;
fulanito.canta (); // canta un juez
}
} // End Poli5
Restricción en Java al polimorfismo sintáctico: cambio a subclases o especialización.
Verificación estática de tipos: tiempo de compilación.
El polimorfismo en Java es posible gracias a la ligadura dinámica. en algunos casos, hasta tiempo de ejecución no se sabe de qué clase será una variable que referencia a un objeto, y por tanto no se sabe cómo responderá a un método y si está en su protocolo.
Ejemplo (estudiar detenidamente las sentencias con //**)
class Transporte {
void llevarCosas() {...}
}
class Coche extends Transporte {
void correr() {...}
}
class Barco extends Transporte {
void navegar() {...}
}
class Pesquero extends Barco {
void pescar() {...}
void navegar() {...}
}
class PruebaLigadura {
public static void main ( String args[]) {
Coche c1 = new Coche();
c1. llevarCosas();
c1.correr();
Coche c2;
c2=c1;
Barco b = new Barco();
b.llevarCosas();
b.navegar();
b.correr(); //**
b=c1; //**
Pesquero p;
p= new Pesquero();
p.navegar();
p.pescar();
p.llevarCosas();
p=b; //**
b=p;
b.navegar();
b.pescar();
Vector v= new Vector();
v.addElement(c1);
v.addElement(p);
(v.elementAt(1)).navegar(); //**
Otro ejemplo de ligadura dinámica en Java
import java.io.*;
/* SE DESCONOCE LA CLASE DEL OBJETO RECEPTOR EN TIEMPO DE COMPILACIÓN, POR TANTO, NO SE SABE QUÉ MÉTODO SE LIGARÁ AL OBJETO Y CUÁL SE EJECUTARA */
class Persona {
void canta(){System.out.println("la la la");}
}
class Ladron extends Persona{
void canta(){System.out.println("Yo no he sido");}
}
/*Se coloca el read y la creación dinamica de objetos entre try y catch para que no se provoque una excepción (error de compilación). */
public class Prue4{
public static void main(String args[]){
Persona uno; /* declaración de variable */
System.out.println("Introduzca 1 para ladron ");
try {
int dato = System.in.read();
if ((char)dato=='1')
uno = new Ladron( );
else
uno = new Persona( );
System.out.println("El objeto creado es de la
clase "+ (uno.getClass().getName()));
uno.canta(); }
/*El compilador comprueba que el método canta() esté definido en la clase Persona. (Ver declaración estática de la variable uno). Hasta la ejecución no se sabe qué método se ligará a este mensaje (Ligadura dinámica)*/
catch (Exception e){
System.out.println("Excepcion " + e);}
}
}
1. Diferencias y semejanzas entre el tipo int y la clase Integer.
2. ¿Porqué crees que se mantienen tipos y clases en el lenguaje?
3. ¿Para qué sirven las palabras public, protected y private, ... en la definición de una clase o método?
4. ¿Cómo se crean métodos de clase?¿Y un método de instancia?
5. ¿Dónde se puede cambiar el valor de una variable de clase?¿y de una variable de instancia?
6. ¿Cómo se distingue a las variables de clase de las variables de instancia?
7. El constructor de una clase en Java realmente puede dar valores a las variables de instancia de un objeto, luego ¿es un método de clase o de instancia?
8. Además de los tipos primitivos que ofrece el lenguaje, ¿se pueden crear nuevos tipos de datos en Java? ¿Cómo?
9. ¿Se pueden añadir métodos a las clases ya existentes en Java?¿Y variables?
10. ¿Cómo se implementa la herencia en Java?
11. ¿Se puede sobreescribir un método heredado? ¿y anularlo?
12. ¿Puede haber dos métodos iguales en dos clases diferentes?
13. ¿Qué es la máquina virtual de Java? ¿Es Java compilado o interpretado? ¿De verdad es portable?
14. ¿Hay restricciones para el polimorfismo de una variable?¿Porqué?
15. ¿Qué relación hay entre la herencia y el polimorfismo?
16. ¿Qué es la ligadura dinámica?¿Para qué sirve?