Java en los Browser  

Posted by Danny in

JAVA EN LOS BROWSERS:------El primer lugar y el más frecuente, donde encontramos al lenguaje Java, es en los exploradores o navegadores de Internet. Veamos cómo llega hasta ahí.

La World Wide Web:------Llamada así por sus siglas WWW, es la aplicación que ha popularizado a Internet, y ha sido la causante de la explosión de la red de redes.

Hablando sencillamente, la WWW basa su existencia en dos aplicaciones: los servidores de Web y los clientes. Los primeros son programas dedicados, instalados en las máquinas nodos de la red, que atienden a todos los pedidos de los clientes. Estos solicitan archivos, recursos de la Web , en general, archivos HTML y gráficos. Los archivos HTML son archivos de texto, que contienen una descripción de lo que vemos como página en nuestro browser. La sigla HTML significa Hypertext Markup Languaje (lenguaje de marcación de hipertexto), y es el lenguaje que describe las páginas Web.

En esas páginas se colocan textos, gráficos y otros recursos. Es trabajo del cliente, nuestro browser, interpretar esa página, mostrarla en pantalla, y reclamar todo lo que se necesite para armarla, como los gráficos y archivos de sonido que la pueden acompañar.

Java en la Web:------Los programas Java son, al fin, otro recurso más, como pueden serlo una página HTML o un archivo gráfico. Al igual que estos últimos viajan desde el servidor a la máquina cliente, y se ejecutan en ésta.

Verá, cuando arme alguna applet, que existe una construcción, la marca HTML , que especifica un determinado lugar en una página Web, para que el browser posicione y ejecute una aplicación Java. Los archivos Java que viajan son de un tipo: se trata de archivos con extensión .class y contienen las instrucciones Java ya compiladas, no viajan en código fuente. Una applet se compone, como mínimo, de un archivo .class, pero puede requerir más archivos .class (con más código para ejecutar), que el browser recupera, o archivos gráficos, de sonido u otros, que la propia applet se encarga de recuperar.

Máquinas Virtuales:------Se ha mencionado que el lenguaje Java se compila, no pensando en una plataforma o procesador en particular, sino produciendo código (que se denomina bytecodes), destinado a ser interpretado por la llamada máquina virtual Java. Esta máquina no es una única, sino que hay una por cada plataforma y, en realidad, cada browser que implementa Java tiene la suya. Así, el Microsoft Explorer usará su máquina en Windows, mientras que el Netscape Navigator usará la suya, que variará de Windows a UNIX.

Pero todas tienen la misma funcionalidad (o debería esperarse eso). Tanto el usuario como los programadores no deberíamos preocuparnos por las distintas implementaciones. Sin embargo, se escuchan quejas de los desarrolladores, originadas en la pequeñas diferencias que se encuentran tanto entre una implementación y otra, como en el aspecto de la interface gráfica.

Además de la máquina virtual, cada browser instala una serie de clases, ya listas para usar, que Java espera tener disponibles en cualquier plataforma. Esas clases tienen una funcionalidad definida, que no debería sufrir modificaciones.

Netscape y Microsoft:------La empresa Netscape, creadora del Netscape Navigator, soporta Java desde la versión 2 de su browser. Microsoft no se ha quedado atrás y soporta Java desde la versión 2.0 de su browser. Microsoft no se ha quedado atrás (pues no le convenía, dado la mayoría de las páginas contiene - aunque sea - un poquito de Java) y soporta Java desde la versión 3.0 de su Internet Explorer. Ambos browsers instalan y usan su propia máquina virtual Java. No hay diferencias apreciables en las prestaciones de estos dos browsers, respecto de Java.

Hay que hacer algunas aclaraciones: en general, los browsers, de cualquier origen, soportan Java en ambientes que permiten la multitarea y los llamados múltiples hilos de ejecución (multihttrading).

Seguridad:------Debido a la naturaleza de Internet, traer programas desde un lugar lejano y no controlado a nuestra computadora, para ejecutarlo, puede ser riesgoso.

Con respecto a las applets Java debemos quedarnos tranquilos: Sun y los constructores de browsers han implementado una política de seguridad, que impide a una applet, por ejemplo, leer o escribir en nuestro disco, o interferir con otras aplicaciones en ejecución. Es tan grande la seguridad que, como programadores, nos puede llegar a molestar: en una applet nunca podremos grabar un archivo local, con datos transitorios o de configuración.

Nuevos browsers:
Entre Netscape (en múltiples plataformas) y Microsoft (en plataformas Windows) acaparan el mercado de los browsers.

Java sin browsers:

Pero no todo es Internet en Java. Este es un lenguaje de uso general, que sólo incidentalmente cobró popularidad en Internet. Podemos desarrollar aplicaciones Java que se ejecuten en nuestra máquina, sin necesidad de estar conectados a la red, y sin el auxilio de browsers. Mientras los programas Java para Internet y páginas HTML se llaman applets, los que pueden ejecutarse fuera de la red se llaman genéricamente aplicaciones.

Metro: Pila de webservices de Sun  

Posted by Danny in ,

Metro es la actualización del antiguo JWSDP (Java Web Services Developer Pack), y digo actualización porque la mayor parte del código se hereda de JWSDP (dicho por uno de sus desarrolladores, si el código es bueno y funciona bien, para que cambiarlo? ).

Esta incluido en Glassfish (Servidor de aplicaciones de Sun) a partir de su versión 2.

Metro realmente es un paquete de diferentes tecnologías, entre las que se encuentran JAX-WS, JAXB, y WSIT (implementación de webservices, implementación de XML-Bindings y Webservices intercomunication tecnology, que permite comunicar sin problemas webservices java y .net 3).

Según los desarrolladores de Metro,

Veamos que necesitamos para usarlo y un pequeño ejemplo.

AVISO: Este tutorial presupone el conocimiento por parte del lector de muchos de los términos e ideas que aquí se exponen, por tanto exige niveles de conocimiento altos en las tecnologías subyacentes. Los ejemplos se muestran como fragmentos que el lector debe completar.

Instalación

La instalación es muy sencilla. Hay que descargarse el jar (https://metro.dev.java.net/1.1/) y ejecutarlo (java -jar metro-installer.jar o doble clic sobre el archivo si estas en windows).

Lo que nos va a instalar es una serie de herramientas y los ficheros necesarios para su funcionamiento. Estas herramientas, al igual que en axis, son las que nos van a permitir la generación automática de código para poder crear nuestros webservices.

Tendremos por tanto 2 posibilidades de crear un webservice.

  • A partir de un fichero WSDL (WebServices Description Language).


      • útil cuando ya tenemos este tipo de fichero, o queremos reimplementar la funcionalidad de un webservice ya publicado en internet (y que nos da igual que este en .net, java o cualquier otra tecnología).
      • No es recomendable este método para generar un webservice desde 0, puesto que es trabajo de crear el fichero .wsdl puede llegar a ser muy tedioso.

      • En la versión usada, Metro 1.1, WSDL 2.0 no está soportado.



  • A partir de una clase java.
      • Perfecto para crear un webservice desde 0, o publicar ciertos métodos de una aplicación java que tenemos ya desarrollada.

      • No recomendable cuando tengamos el fichero wsdl (El webservice generado puede no ser totalmente compatible con el del wsdl que teníamos).

Veamos detalladamente cada uno de los pasos.


Crear un WebService


Para todos los ejemplos vamos a usar el webservice público definido en 'http://wscc.info/index.php?show=32031_SWE&&page_anchor=http://wscc.info/p32031/p32031_swe.php', y que devuelve información de geolocalización de una ip dada. Además el webservice está realizado en .net, y así comprobaremos si WSIT funciona.


Desde un fichero WSDL


Para generar el webservice desde este tipo de ficheros vamos a usar la herramienta que trae Metro, wsimport, y que nos va a crear todas las clases necesarias para poder poner en funcionamiento el webservice. Un ejemplo de uso del comandos sería:


wsimport.sh -s src/main/java -p com.autentia.service -Xnocompile http://ws.ip2location.com/ip2locationwebservice.asmx?wsdl

Donde:



  • -s: ruta donde se van a generar los fuentes.

  • -p : paquete en el que se generará el código.

  • -Xnocompile : indica a la herramienta que no compile el código generado.

y nos generará las siguientes clases:

IP2Location.java: Java bean de tipo de dato complejo.

Ip2LocationWebService.java: Proxy del webservice.

IP2LOCATION.java: Java bean de tipo de dato complejo.

Ip2LocationWebServiceSoap.java: Interfaz del servicio.

IP2LocationResponse.java: Java bean de la respuesta del servicio.

ObjectFactory.java: Factoría de objetos usados internamente por el servicio.

package-info.java: Archivo para javadoc.

Como lo que vamos a hacer es reescribir el servicio web (hacer un webservice compatible con el wsdl usado pero realizado en java), no nos quedaría nada más que crear la clase skeleton del webservice (la que implementa la lógica de negocio del webservice).

Creamos una nueva clase java que tendrá la siguiente estructura (en este ejemplo la llamaremos IP2LocationSkel.java):


@WebService(endpointInterface="com.autentia.service.Ip2LocationWebServiceSoap")  public class IP2LocationSkel implements Ip2LocationWebServiceSoap {          ...  }

Donde veis lo simple que es: creamos la clase y hacemos que implemente la interfaz generada anteriormente (no es obligatorio, pero si muy recomendable para saber cómo es el método a implementar en tiempo de compilación).


Lo que si es obligatorio es la anotación de la clase (y lo que le da potencia y sencillez a Metro): @WebService. La propiedad endpointInterface indica la clase (nombre cualificado) de la interfaz del webservice (y es por esto por lo que no es obligatorio implemetar la interfaz anterior).


Y ya está! Ya tendríamos nuestro webservice creado, en pocos pasos y de manera muy sencilla!


Desde java


Vamos a hacer ahora la operación inversa. Queremos realizar un webservice desde 0, no tenemos el fichero WSDL o ya tenemos una clase java de la que queremos hacer públicos alguno de sus métodos a través de webservice.


No tedríamos más que generar una clase java, que debe cumplir los siguientes requisitos:



  • La clase se debe anotar con @javax.jws.WebService.

  • Todos los métodos que se desean exponer como operación del webservice se pueden anotar con @javax.jws.WebMethod (si todos los métodos de la clase son operaciones del servicio web se puede omitir dicha anotación).

  • Todos los métodos que se desean exponer como operación del webservice pueden lanzar java.rmi.RemoteException, aparte de todas las excepciones específicas del servicio.

  • Todos los parámetros de los métodos del servicio y tipos de retorno deben ser compatibles con “JAXB 2.0 Java to XML Schema mapping definition".

  • Los parámetros de los métodos del servicio y tipos de retorno no pueden implementar directa o indirectamente la interfaz java.rmi.Remote.

Veamos una sección de la clase (una clase que implementa una pequeña calculadora):
@WebService  public class AddNumbersImpl {       @WebMethod   public int addNumbers(int number1, int number2) throws AddNumbersException {    ...   }  }


Fijaos en las anotaciones: hemos anotado la clase con @WebService, y el método addNumbers con @WebMethod (el único que expondremos como método del servicio web).

El siguiente paso: generar las clases de apoyo necesarias para poner en marcha el webservice, y para ello usaremos otra herramienta que nos provee Metro, y que se llama wsgen
wsgen.sh  -cp  -keep com.autentia.service.AddNumbersImpl
Donde:

  • -cp : indica el classpath a utilizar, es decir, la ruta o rutas de .jar o carpetas que contienen los .class necesarios para la compilación.

  • -keep : indica que no se borren los ficheros .java generados.

  • com.autentia.service.AddNumbersImpl: para el ejemplo, es la clase que implementa el webservice (denominado SEI: service endpoint implementation).

Que nos generará las siguientes clases:

AddNumbersExceptionBean.java : java bean para la excepción que puede lanzar el webservice.

AddNumbers.java : Skeleton del webservice.

AddNumbersResponse.java : clase de tratamiento de la respuesta SOAP.


Ya tenemos nuestro webservice! (sencillito, eh?)


Creando una aplicación web con nuestro webservice (war)

Una vez creado nuestro webservice veamos qué recursos y configuraciones debemos incluir para que el webservice funcione como una aplicación web y la podamos publicar (yo he usado tomcat y funciona sin problemas).

Ante todo debemos meter en la carpeta WEB-INF/lib de nuestro war los .jar (webservice*.jar) que vienen en la instalación de Metro.

Dentro de WEB-INF deben ir localizados web.xml y sun-jaxws.xml

El fichero de descripción de la aplicación web, web.xml, debe contener el siguiente fragmento (se define el servlet y filtros necesarios para que funcione Metro):

web.xml:
...  <listener>          <listener-class>                  com.sun.xml.ws.transport.http.servlet.WSServletContextListener          </listener-class>  </listener>  <servlet>          <description>JAX-WS endpoint - fromjava</description>          <display-name>metro ws engine servlet</display-name>          <servlet-name>metroServlet</servlet-name>          <servlet-class>                  com.sun.xml.ws.transport.http.servlet.WSServlet          </servlet-class>          <load-on-startup>1</load-on-startup>  </servlet>  <servlet-mapping>          <servlet-name>metroServlet</servlet-name>          <url-pattern>/ws/*</url-pattern>  </servlet-mapping>  ...

El fichero de descripción del webservice para Metro:


sun-jaxws.xml:


<endpoints xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime" version="2.0">


    <endpoint          name="addnumbers-example"          implementation="com.autentia.service.AddNumbersImpl"          url-pattern="/ws/addnumbers"/>  </endpoints>

Ojo! El url-mapping del servlet de webservice de metro y de la definición del webservice deben ser compatibles:








Una vez empaquetado el código convenientemente podemos instalar la aplicación en Tomcat, y acceder a http://localhost:8080/<war-name>/ws/addnumbers:








podemos ver el wsdl generado al pulsar sobre el link que nos propone la página.


Generar el cliente


Bien, ya he creado mi web service, ya lo he publicado... y ahora cómo lo uso? O cómo me conecto a un webservice externo?. Veamos cómo crear entonces un cliente apra webservice, y lamaera es muy sencilla, y es 99% igual que la forma en que generábamos un servicio web a partir de un wsdl.


Ejecutando el comando (la URI del wsdl tomaremos la del webservice del ejemplo comentado al inicio):


wsimport.sh -s src/main/java -p com.autentia.service -Xnocompile http://ws.ip2location.com/ip2locationwebservice.asmx?wsdl

con el que ya vimos anteriormente qué clases se generaban automáticamente.


La diferencia entre crear un webservice a aprtir de un WSDL y un cliente es la clase que tenemos que crear. Ahora codificaremos una clase como sigue, que será la que se conecte y haga la llamda al webservice:


public class IP2LocationStub implements Ip2LocationWebServiceSoap {     public IP2LOCATION ip2Location(String ip, String license) {      // Create Service    Ip2LocationWebService service = new Ip2LocationWebService();      // create proxy    Ip2LocationWebServiceSoap proxy = service.getIp2LocationWebServiceSoap();      // invoke    return proxy.ip2Location(ip, license);   }  }






Donde, como al crear el webservice, no es obligatorio que la clase implemente la interfaz Ip2LocationWebServiceSoap, pero si es muy recomendable.


Si llamáis al webservice del ejemplo necesitáis una clave de uso, con lo que la llamada volverá con los datos vacíos y con un mensaje de error, pero eso implica que el ejemplo funciona!!!


Conclusión


Ya habéis visto lo sencillo que es crear un servicio web y un cliente de webservice con Metro (y hemos probado además que WSIT funciona!).


En mi humilde opinión el desarrollo a base de anotaciones agiliza y simplifica mucho la tarea de generar web services, además nos permite reutilizar clases que ya teníamos.


En cuanto al rendimiento, existe en http://weblogs.java.net/blog/kohsuke/archive/2007/02/jaxws_ri_21_ben.html una comparativa de Metro vs Axis2, donde se muestra que para el envío de ciertos tipos de datos, Metro puede llegar a ser el doble de rápido que axis2 (por tanto más eficiente), aunque claro, la comparativa está realizada por uno de los propios desarrolladores de Metro... A final vuestra experiencia será la que diga la última palabra.


No os perdáis los próximos tutoriales sobre metro donde veremos cómo automatizar las tareas que realizábamos 'a mano' mediante maven2, y otro que nos enseñará a usar RESTFull con Metro.




Validación de documentos XML  

Posted by Danny in , ,

Veamos cómo se valida un documento XML.


import javax.xml.parsers.*;
import org.xml.sax.*;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.helpers.DefaultHandler;

public class Validate {

public Validate(String filename) {
StringBuffer buff = new StringBuffer();

try {
File f = new File(".", filename);
StringBuffer errorBuff = new StringBuffer();
InputSource input = new InputSource(new FileInputStream(f));

// Set systemID so parser can find the dtd with a relative URL in the source document.
input.setSystemId(f.toString());
SAXParserFactory spfact = SAXParserFactory.newInstance();

spfact.setValidating(true);
spfact.setNamespaceAware(true);

SAXParser parser = spfact.newSAXParser();
XMLReader reader = parser.getXMLReader();

//Instantiate inner-class error and lexical handler.
Handler handler = new Handler(filename, errorBuff);
reader.setProperty("
http://xml.org/sax/properties/lexical-handler ", handler);
parser.parse(input, handler);

if (handler.containsDTD && !handler.errorOrWarning) { // valid
buff.append("VALID " + filename +"\n");
}
else if (handler.containsDTD) { // not valid
buff.append ("NOT VALID " + filename + "\n");
buff.append(errorBuff.toString());
}
else buff.append("NO DOCTYPE DECLARATION " + filename + "\n");
}
catch (Exception e) {
buff.append("NOT WELL-FORMED " + filename + ". " + e.getMessage() + "\n");
}

System.out.print(buff.toString());
}

class Handler extends DefaultHandler implements LexicalHandler {
boolean errorOrWarning;
boolean containsDTD;
String sourceFile;
StringBuffer errorBuff;

Handler(String sourceFile, StringBuffer errorBuff) {
super();
this.sourceFile = sourceFile;
this.errorBuff = errorBuff;
errorOrWarning = false;
containsDTD = false;
}

public void error(SAXParseException exc) {
errorBuff.append(sourceFile + " Error: " + exc.getMessage()+ "\n");
errorOrWarning = true;
}

public void warning(SAXParseException exc) {
errorBuff.append(sourceFile + " Warning:" + exc.getMessage()+ "\n");
errorOrWarning = true;
}

public void startDTD (String name, String publicId, String systemId) throws SAXException {
containsDTD = true;
}

public void endDTD () throws SAXException {}
public void startEntity (String name) throws SAXException {}
public void endEntity (String name) throws SAXException {}
public void startCDATA () throws SAXException {}
public void endCDATA () throws SAXException {}
public void comment (char ch[], int start, int length) throws SAXException {}
}

public static void main(String[] args) {
Validate v = new Validate("birds.xml");
}
}

Glosario de Java  

Posted by Danny in

abstract: Abstracto.Aplicable a clases o métodos.

array: Variable que posee varias posiciones para almacenar un valor en cada posición. Las posiciones son accedidas mediante un índice numérico.

break: Palabra clave que finaliza la ejecución de un bucle o de una instrucción switch.

bucles: Tipo de estructura iterativa, que permite repetir un conjunto de instrucciones un número variable de veces.

clase: Estructura que define como son los objetos, indicando sus atributos y sus acciones.

clase base: Clase de la cuál se hereda para construir otra clase, denominada derivada.

CLASSPATH: Variable de entorno que permite a la máquina virtual java saber donde localizar sus clases.

constructor: Función especial empleada para inicializar a los objetos, cada clase posee sus propios constructores.

derivada: Clase que hereda de una clase base.

Excepcion: Objeto empleado para representar una situación de excepción (error) dentro de una aplicación java.

herencia: Característica que permite que una clase posea las características de otra, sin tener que reescribir el código.

herencia sencilla y múltiple: Dos tipos de herencia, con una sóla clase base, o con varias.

instancia: Un objeto creado a partir de una clase.

instanciación: Proceso de creación de un objeto a partir de una clase.

interfaz: Define un tipo de datos, pero sólo indica el prototipo de sus métodos, nunca la implementación.

JDK: Java Development Kit, es el conjunto de herramientas proporcionadas por sun, que permite compilar y ejecutar código java.

jerarquía de herencia: Árbol construido mediante las relaciones de herencia en las clases java.

máquina virtual: Es la encargada de ejecutar el código java.

multiplataforma: Posibilidad de existir en varias plataformas (sistemas operativos)

package: Paquete. Carpeta creada para contener clases java, y así poder organizarlas.

PATH: Variable de entorno, empleada por los sistemas operativos para saber donde localizar sus programas ejecutables.

Sobrescritura: Poseer el mismo método, pero con código distinto, en una clase base y en una clase que deriva de ella.

transformación de datos: Cómo cambiar el tipo de una información, por ejemplo cambiar el literal "23" al valor numérico 23.

try/catch/finally: Instrucciones empleadas para gestionar los posibles errores que se puedan provocar en un programa java.

Prácticas con excepciones  

Posted by Danny in ,

Crear el fichero Try1.java

Agregar el siguiente código:

public class Try1

{

public static void main(String arg[])

{

int [] array = new int[20];

array[-3] = 24;

}

}

Como podremos comprobar al ejecutar se generará el siguiente error:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException

at Try1.main(Try1.java:6)

Que indica que se ha generado una excepción del tipo java.lang.ArrayIndexOutOfBoundsException en la función Try1.main, dentro del fichero Try1.java y en la línea 6 del código. Esta excepción en particular, se lanza cuando intentamos acceder a una posición de un array y no existe dicha posición.


Vamos a gestionar esta interrupción mediante un bloque try/catch, el fichero crear es Try2.java, con el siguiente código:

public class Try2

{

public static void main(String arg[])

{

int [] array = new int[20];

try

{

array[-3] = 24;

}

catch(ArrayIndexOutOfBoundsException excepcion)

{

System.out.println(" Error de índice en un array");

}

}

}



Intentemos provocar también un error de tipo división por cero y pongamos un catch específico para dicho error (fichero Try3.java):

public class Try3

{

public static void main(String arg[])

{

int [] array = new int[20];

try

{

// array[-3] = 24;

int b = 0;

int a = 23/b;

}

catch(ArrayIndexOutOfBoundsException excepcion)

{

System.out.println(" Error de índice en un array");

}

catch(ArithmeticException excepcion)

{

System.out.println(" Error de índice en un array");

}

}

}

Podemos comprobar que se ejecuta el catch correspondiente al tipo de error generado. La línea que lanza el error de índice la hemos comentado para que no lo genere y podamos generar el error de división por cero.

Los tipos de error que se generan, son todos ellos clases, que heredan de la clase java.lang.Exception, que a su vez hereda de java.lang.Throwable, por lo tanto podríamos crear nuestros propios errores personalizados. Al igual que podríamos tener un solo catch que capture todos los errores, independientemente del tipo del error.


Excepciones  

Posted by Danny in

Excepcion es, o sencillamente problemas. En la programación siempre se producen errores, más o menos graves, pero que hay que gestionar y tratar correctamente. Por ello en java disponemos de un mecanismo consistente en el uso de bloques try/catch/finally . La técnica básica consiste en colocar las instrucciones que podrían provocar problemas dentro de un bloque try, y colocar a continuación uno o más bloques catch, de tal forma que si se provoca un error de un determinado tipo, lo que haremos será saltar al bloque catch capaz de gestionar ese tipo de error específico. El bloque catch contendrá el codigo necesario para gestionar ese tipo específico de error. Suponiendo que no se hubiesen provocado errores en el bloque try, nunca se ejecutarían los bloques catch.

Veamos ahora la estructura del bloque try/catch/finally:

try

{

//Código que puede provocar errores

}

catch(Tipo1 var1)

{

//Gestión del error var1, de tipo Tipo1

}

[ ...

catch(TipoN varN)

{

//Gestión del error varN, de tipo TipoN

} ]

[

finally

{

//Código de finally

}

]

Como podemos ver es obligatorio que exista la zona try, o zona de pruebas, donde pondremos las instrucciones problemáticas. Después vienen una o más zonas catch, cada una especializada en un tipo de error o excepción. Por último está la zona finally, encargada de tener un código que se ejecutará siempre, independientemente de si se produjeron o no errores.

Se puede apreciar que cada catch se parece a una función en la cuál sólo recibimos un objeto de un determinado tipo, precisamente el tipo del error. Es decir sólo se llamará al catch cuyo argumento sea coincidente en tipo con el tipo del error generado.



Práctica con interfaces  

Posted by Danny in ,

Vamos a definir el interfaz Cantante, un interfaz muy simple que sólo posee un método: cantar.

Crear el fichero Cantante.java

Agregar el siguiente código:

public interface Cantante

{

public void cantar();

}

Cojamos la clase Persona y hagamos que implemente el interfaz Cantante:

public class Persona implements Cantante

Además agreguemos el código para el método que define el interfaz cantante:

public void cantar()

{

System.out.println("La laa la raa laaa!");

}

Construyamos ahora una clase con función main (ArranqueInterfaz.java)para ejecutar:

public class ArranqueInterfaz

{

public static void main(String arg[])

{

Persona p = new Persona();

hacerCantar(p);

}

public static void hacerCantar(Cantante c)

{

c.cantar();

}

}




Interfaces III  

Posted by Danny in

Podemos ver que construimos un objeto (p) de tipo persona y se lo pasamos a la función hacerCantar. Esta función espera recibir un objeto Cantante, y una persona lo es, por tanto la recibe y llama al método cantar del objeto recibido.

Probemos a intentar pasar a la función hacerCantar en lugar del objeto Persona (p) un objeto String (texto), resultado: error de compilación.

Contruyamos ahora la clase Canario (Canario.java), pensando que también sabe cantar:

public class Canario implements Cantante

{

private int peso;

/* Aqui vendrían el resto de atributos y funciones propias de un canario */

public void cantar()

{

System.out.println("Pio Pio Pio");

}

}

Y ahora agreguemos en la clase ArranqueInterfaz el siguiente código, para crear un objeto canario y pasarselo a la función hacerCantar:

Canario c = new Canario();

hacerCantar(c);

Tras ejecutar comprobaremos que podemos pasar tanto una Persona como un Canario a la función hacerCantar, de tal manera que dentro de dicha función sólo accedamos a las funciones del interfaz y no habrá problemas. Por ejemplo, si pusiéramos:

c.SetNombre("Luis")

dentro de la función hacerPersona, podría funcionar si pasásemos un objeto Persona, pero no si pasamos uno de tipo Canario.




Interfaces II  

Posted by Danny in

Donde modif.visibilidad puede ser public o bien sin especificar, es decir visibilidad pública (desde cualquier clase se puede emplear el interfaz) o de paquete (sólo se puede emplear desde clases del mismo paquete).

nombreInterfaz por convenio, sigue las mismas reglas de nomenclatura que las clases, y en muchos casos acaba en able (que podíamos traducir como: 'ser capaz de').

La claúsula opcional extends, se emplea para conseguir que un interfaz herede las funciones de otro/s interfaces, simplemente listaInterfaces es una lista separada por coma de interfaces de los que se desea heredar.

En muchas ocasiones un interfaz es empleado para definir un comportamiento, que posteriormente será implementado por diversas clases, que podrán no tener nada que ver entre ellas, pero que todas se comportarán igual de cara al interfaz. Es decir, todas tendrán las funciones indicadas por el interfaz.

Cuando varios objetos de distintas clases pueden responder al mismo mensaje (función), aún realizando cosas distintas se denomina polimorfismo.

Interfaces I  

Posted by Danny in

Un interfaz es una lista de acciones que puede llevar a cabo un determinado objeto. Sorpresa, ¿eso no eran los métodos que se definen en una clase? Casi, en una clase además de aparecer los métodos aparecía el código para dichos métodos, en cambio en un interfaz sólo existe el prototipo de una función, no su código.

Veámoslo con un ejemplo: Pensemos en un interfaz en el que en su lista de métodos aparecen los métodos despegar, aterrizar, servirComida y volar. Todos pensamos en un avión, ¿verdad? El motivo es sencillamente que avión es el concepto que engloba las acciones que hemos detallado antes, a pesar que existan muchos objetos avión diferentes entre sí, por ejemplo Boeing 747, Boeing 737, MacDonell-Douglas.

Lo realmente interesante es que todos ellos, a pesar de pertenecer a clases distintas, poseen el interfaz avión, es decir poseen los métodos detallados en la lista del interfaz avión.

Esto significa también que a cualquier avión le podemos pedir que vuele, sin importarnos a que clase real pertenezca el avión, evidentemente cada clase especificará como volará el avión (porque proporciona el código de la función volar).

En java un interfaz define la lista de métodos, pero para que una clase posea un interfaz hay que indicar explícitamente que lo implementa mediante la claúsula implements. Pero veamos primero la estructura de un interfaz:

[modif.visibilidad] interface nombreInterfaz [extends listaInterfaces]

{

prototipo método1;

.....

prototipo método1;

}

Introducción a la transformación entre tipos de datos (II)  

Posted by Danny in

En ocasiones nos interesará transformar un tipo, por ejemplo entero, a otro tipo entero de menos precisión, es decir, transformar de long a int, para ello habrá que emplear el operador de moldeo:

(tipo)

para forzar la conversión de un tipo a otro:

long b =-234;

int a = (int)b;

Funcionará mientras que el valor almacenado en el long esté dentro del rango permitido al tipo int, si no, se truncará el valor. Lo mismo se puede indicar para los tipos float y double.

También se puede emplear el operador de moldeo para objetos. Veamos un ejemplo:

Coche c = new Coche();

Vector v = new Vector();

v.add(c);

Object o = v.get(0);

Coche recuperado = (Coche) o;

En este ejemplo creamos un objeto de la clase Coche, y un objeto de la clase Vector. Un Vector en java se emplea como un array dinámico.

En este caso agregamos al vector el coche mediante la función add. Para recuperar el objeto que está en la posición 0 usamos la función get, esta función devuelve un Object, cuando pensamos que debería devolver un objeto Coche. En realidad lo que devuelve es una referencia de la clase base Object, que apunta al objeto de la posición 0, es decir nuestro objeto coche. Pero necesitamos que nuestro objeto sea apuntado por una referencia de tipo Coche para poder llamar a las funciones de la clase Coche. Por ello hacemos una conversión de referencias en la última línea.



Introducción a la transformación entre tipos de datos (I)  

Posted by Danny in

En java será necesario transformar entre tipos de datos básicos, generalmente entre String hacia cualquier otro tipo tipo básico, o viceversa. Si es necesario transformar un tipo básico hacia String, la forma más rápida consiste en concatenar el valor a un objeto String, por ejemplo:

"" + 34

Con ello conseguiremos que se cree el literal "34".

Si en cambio queremos transformar el literal "2345" a un valor int para poder operar con el será necesario emplear:

int valor = Integer.parseInt("2345");

Integer es una clase empleada para representar al tipo básico int, y para transformar de String a int, pero puede lanzar excepciones, es por ello que siempre hay que usarla con try/catch:

int valor;

try{

valor = Integer.parseInt( "2345");

}catch(Exception e){ e.printStackTrace();}

System.out.println(valor*10);

Introducción a la entrada por teclado  

Posted by Danny in

En java para poder escribir se emplea el objeto System.out, pero para leer del teclado es necesario emplear System.in. Este objeto pertenece a la clase InputStream, esto significa que para leer tenemos que emplear sus métodos, el más básico es read, que permite leer un carácter:

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

Pero como podemos comprobar es muy incómodo leer de letra en letra, por ello para poder leer una línea completa emplearemos el siguiente código:

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

String línea = br.readLine();

En el cuál creamos un InputStreamReader a partir de System.in y pasamos dicho InputStreamReader al constructor de BufferedReader, el resultado es que las lecturas que hagamos sobre br son en realidad realizadas sobre System.in, pero con la ventaja de que se permite leer una línea completa.

Es necesario realizar un import de java.io para poder emplear esta lectura de líneas.

Además la línea del readLine puede lanzar Excepciones, es por ello que hay que meterla entre instrucciones try/catch para poder gestionar el posible error:

String línea;

try{

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

línea = br.readLine();

}catch(Exception e){ e.printStackTrace();}

System.out.println(línea);

Tercera práctica con instrucciones iterativas (II)  

Posted by Danny in ,

Prácticas:

Crear el fichero BreakContinue.java y agregar el siguiente código:

public class BreakContinue1{

public static void main(String arg[]){

for (int contador = 0; contador<=15 ; contador ++)

{

System.out.println(contador);

// if(contador==10) break;

// if(contador==10) continue;

System.out.println("Despues del if");

}

}

}

Al ejecutar aparecerá:

0

Despues del if

pero variando de 0 a 14.

Ahora vamos a descomentar la línea del break y ejecutamos, el resultado será el mismo, pero ahora variará de 0 a 10 y además para el caso 10 no aparecerá el texto después de if.

Ahora comentamos la línea del break y descomentamos la línea del continue, ejecutamos. Podremos apreciar que aparecen los valores de 0 a 14, pero en el caso 10 no aparece el mensaje "Después de if".

Tercera práctica con instrucciones iterativas  

Posted by Danny in ,

En esta equivalencia veremos que inicialización es empleada para dar un valor inicial a la variable que utilizaremos para ser evaluada posteriormente en la condición. La condición, que será evaluada para comprobar si se detiene o no el bucle for, y la evaluación, empleada para indicar los incrementos que se realizarán sobre la variable.

Prácticas:

Crear una aplicación que muestre los primeros 256 caracteres por pantalla, en cada fila aparecerán 5 caracteres.

Crear el fichero For1.java

Agregar el siguiente código:

public class For1{

public static void main(String arg[]){

for (int nLetra = 0; nLetra<=255 ; nLetra ++)

{

System.out.print(" " + nLetra + ": " + (char)nLetra);

if (nLetra%4==0) System.out.println("");

}

}

}

Para los tres tipos de bucles existen dos palabras claves que se pueden emplear: break y continue.break consigue que se detenga el bucle y siga el flujo de ejecución después del bucle, mientras que continue provoca que se regrese al comienzo del bucle. Este regreso no provoca que se reinicialicen las variables empleadas.

Segunda práctica con Instrucciones iterativas  

Posted by Danny in ,

public static String leerLinea(){

try{

java.io.BufferedReader d = new java.io.BufferedReader(new java.io.InputStreamReader(System.in));

return d.readLine();

}catch(Exception e) {}

return "";

}

}

for

La sintaxis del bucle for es:

for (inicialización;condición;evaluación){

//instrucciones a ejecutar

}

Antes de nada, veamos una equivalencia de un bucle while configurado como un bucle for:

inicialización;

while (condición)

{

//Instrucciones a ejecutar

evaluación;

}

Instrucciones iterativas (II)  

Posted by Danny in

Este bucle comienza ejecutando las instrucciones que hay en su interior, una vez ejecutadas comprueba el valor de condición, si es true vuelve de nuevo a repetir el proceso ejecutar/evaluar. Si la evaluación de condición es false, entonces finaliza la ejecución del bucle.

Un bucle while ejecutará sus instrucciones de 0 a n veces, dependiendo del valor de las condiciones. Mientras que un bucle do while ejecutará sus instrucciones de 1 a n veces dependiendo del valor de la condición.

Prácticas:

Crear una aplicación que solicite una contraseña al usuario, si es correcta mostrará que es correcta, si el usuario se equivoca tres veces finalizará el programa.

Crear el fichero DoWhile1.java

Agregar el siguiente código:

public class DoWhile1{

public static void main(String arg[]){

String clave = "Sin clave";

String candidata;

int nVeces = 0;

do

{

System.out.println("Introduzca la clave: ");

candidata = leerLinea();

nVeces++;

}while(!clave.equals(candidata) && nVeces<3);>

if(nVeces==3 && !clave.equals(candidata))

{

System.out.println("Lo siento no acertó.");

}

else

{

System.out.println("Clave correcta.");

}

}

/* Esta función permite leer una línea de texto, veremos su funcionamiento cuando lleguemos al capítulo de flujos de entrada y salida */

Práctica con instrucciones iterativas  

Posted by Danny in ,

Vamos a construir una aplicación que tome un número como argumento y muestre la tabla de multiplicar de dicho número.

Crear While1.java

Agregar el siguiente código:

public class While1{

public static void main(String arg[]){

if ( arg.length>0) {

int valor = Integer.parseInt(arg[0]);

int contador = 1;

while (contador<=9)

{

System.out.println("" + valor + " * " + contador + " = " + (valor*contador));

contador++;

}

}

else

{

System.out.println("No hay ningún parámetro");

}

}

}

do while :

La sintaxis es:

do

{

//Instrucciones a ejecutar

} while (condición);

Instrucciones iterativas (I)  

Posted by Danny in

También conocidas como bucles, las instrucciones iterativas tienen la misión de ejecutar las mismas instrucciones de código un número de veces, determinado por una condición.

En java tenemos tres bucles: while, do while y for.

while :

La sintaxis es:

while (condición)

{

//Instrucciones a ejecutar

}

Este bucle evalúa la condición, si es cierta ejecutará las instrucciones de su interior, una vez ejecutadas regresará al comienzo y se repetirá el proceso de evaluar/ejecutar. Este proceso sólo finalizará cuando en la evaluación la condición de como resultado false.

Mas de Instrucciones Condicionales II  

Posted by Danny in

El operador ternario tiene la misión de devolver un valor, dependiendo del valor de una condición booleana. La sintaxis es:

((condición)?valor1:valor2)

Se evalúa la condición y si es true se devuelve valor1, y si es false se devuelve valor2.

Practica:
Construir una aplicación que tome un valor entero como argumento y que muestre si es par o no por pantalla.
Crear el fichero Ternario1.java
Agregar el siguiente código:
public class Ternario1{
public static void main(String arg[]){
if ( arg.length>0) {
int valor = Integer.parseInt(arg[0]);
String resultado = ((valor%2==0)?"par":"impar");
System.out.println("El número es "+resultado);
}
else
{
System.out.println("No hay ningún parámetro");
}
}
}

Práctica completa con Instrucción Condicionales (II)  

Posted by Danny in ,

case 4:

nombreMes = "Abril";

break;

case 5:

nombreMes = "Mayo";

break;

case 6:

nombreMes = "Junio";

break;

case 7:

nombreMes = "Julio";

break;

case 8:

nombreMes = "Agosto";

break;

case 9:

nombreMes = "Septiembre";

break;

case 10:

nombreMes = "Octubre";

break;

case 11:

nombreMes = "Noviembre";

break;

case 12:

nombreMes = "Diciembre";

break;

default:

nombreMes = "desconocido";

}

System.out.println("El mes es " + nombreMes);

}

}

Ejecutar y comprobar su correcto funcionamiento.

Eliminar todas las instrucciones break del código, y comprobar que siempre se devuelve el mismo valor, independientemente del valor pasado como argumento.

Práctica completa con Instrucción Condicionales (I)  

Posted by Danny in ,

La instrucción switch toma la variable que le pasamos como argumento, y obtiene el valor de dicha variable. Después lo compara con los valores que hay junto a las etiquetas case, comenzando a ejecutar el código que hay debajo de la etiqueta case que coincida. Cuando se encuentre con la instrucción break finalizará la ejecución del switch.

En caso de no encontrar una etiqueta case coincidente, ejecutará el código que existe dentro de la etiqueta default. La etiqueta default es opcional, por tanto en caso de no tenerla simplemente no hace nada la instrucción.

Práctica:

Construir una aplicación que tome un valor entero como argumento, y que muestre el mes equivalente al entero introducido.

Crear el fichero Switch1.java

Agregar el siguiente código:

public class Switch1{

public static void main(String arg[])

{

if ( arg.length == 0 )

{

System.out.println("Uso: \n\tjava Switch1 entero");

return;

}

int mes = Integer.parseInt(arg[0]);

String nombreMes;

switch(mes){

case 1:

nombreMes = "Enero";

break;

case 2:

nombreMes = "Febrero";

break;

case 3:

nombreMes = "Marzo";

break;



Prácticas con instrucciones condicionales (I)  

Posted by Danny in ,

Vamos a construir una clase java que permita recibir un parámetro al ejecutar la clase y comprobemos que existe al menos un parámetro, y en caso de que exista que lo visualice.

Construyamos la clase if1.java

Agreguemos el siguiente código:

public class If1{

public static void main(String arg[]){

if ( arg.length>0) {

System.out.println(" Al menos hay un parámetro, y el primero es: " + arg[0] );

}

else

{

System.out.println("No hay ningún parámetro");

}

}

}

Ejecutar sin pasar nigún parámetro, o pasando al menos un parámetro y comprobemos lo que sucede. La instrucción switch permite ejecutar código, pero dependiente del valor de una variable:

switch (variable)

{

case val1:

------

------

break;

.

.

.

case valn:

------

------

break;

default:

------

------

}


Instrucciones Condicionales I  

Posted by Danny in

Java proporciona las instrucciones if/else, switch y el operador ternario para poder tomar decisiones en función del resultado de la evaluación de una condición o variable.

La instrucción if tiene la siguiente estructura:

if (condición)

{

//Código a ejecutar si condición es true

}

else

{

//Código a ejecutar si condición es false

}

Esta instrucción evalúa la expresión condición, y si es true, ejecuta el código que hay entre las llaves que hay debajo de if. Si condición fuese false, el código a ejecutar sería el contenido entre las llaves que existen debajo de else.

La parte else es opcional, es decir, esto también es correcto:

if (condición)

{

//Código a ejecutar si condición es true

}

En este caso si condición es false no sucede nada, la instrucción no ejecuta ninguna instrucción.

Otra simplificación también correcta es que en caso de que sólo exista una instrucción dentro de las llaves (del if, o del else) se pueden eliminar las llaves, es decir:

if (condición) //instrucción a ejecutar si condición es true;

else //instrucción a ejecutar si condición es false;

Lo que no está permitido eliminar en ningún caso, son los puntos y coma de las instrucciones que empleemos en la parte verdadera (if) o falsa (else), tengamos o no las llaves.

Precedencia de Operadores en Java  

Posted by Danny in

Por el hecho de poder emplear varios operadores en la misma expresión nos encontramos con la necesidad de conocer el orden de evaluación de los operadores:

Precedencia de Operadores en Java

Existe una palabra clave llamada instanceof que puede ser interpretada como un operador, encargado de comprobar si un objeto es una instancia de una determinada clase, por ejemplo:

String cad = "unTexto";

Bolean resultado = cad instanceof String;

Operadores lógicos, nivel de bit y asignación  

Posted by Danny in

Operadores lógicos:

Nota: Los operadores logicos siempre devuelven un valor booleano.

Operadores a nivel de bit:

Los operadores a nivel a bit toman los operadores, los transforman a binario y realizan las operaciones trabajando con los bits uno a uno.

Operadores de asignación:

Nota: Estos operadores son en realidad abreviaturas de otros operadores unidos junto al operador asignación.




Operadores relacionales  

Posted by Danny in

Nota: Los operadores relacionales siempre devuelven un valor booleano.

Hay que hacer especial mención a los operadores == y !=, además de ser empleados en los tipos básicos del lenguaje pueden ser utilizados para comparar dos objetos, o más específicamente, comparar dos referencias a objetos. Al comparar dos referencias a objetos lo que realmente se comprueba es si ambas referencias apuntan al mismo objeto o no. No confundir esto con comparar dos referencias de tipo String, no se compararía si el texto es el mismo, sino si ambas referencias apuntan al mismo objeto String. Para comparar String es necesario hacerlo mediante los métodos que para ellos existen dentro de la clase String, como por ejemplo equals:

String cad1 = "Texto";

String cad2 = "Texto2";

boolean resultado = cad1.equals(cad2);

Operadores aritméticos  

Posted by Danny in

Además, en una instrucción simple pueden aparecer operadores, los hay de dos tipos: los que actúan sobre un operador, o los que lo hacen sobre dos. Los operadores los clasificaremos por su empleo:

Operadores aritméticos

(*) En java también se emplea el operador + para concatenar cadenas de texto.

Instrucciones del lenguaje  

Posted by Danny in

Existen varios tipos de instrucciones en java: Instrucción simple, Instrucción condicional, Instrucción iterativa y Instrucción simple

Una instrucción simple debe finalizar en punto y coma, y puede ser una expresión con operadores, una llamada a un método, una declaración de variable o una instrucción compuesta por varias instrucciones simples:

int a = 5; //Declaración de variable

System.out.println(a); //Llamada a método

a = a+4; // Expresión con operadores

System.out.println(++a); //instrucción compuesta de llamada a método y operador ++

Para definir una variable se emplea la misma sintaxis que para la definición de un atributo en una clase, pero sin utilizar los modificadores de visibilidad, ni los modificadores de atributos.

Práctica con matrices, arrays o vectores (III)  

Posted by Danny in ,

Crear el fichero Array3.java

Lo que vamos a hacer es tratar de ejecutar nuestra clase Array3, pero en lugar de ejecutarla mediante: "java Array3" vamos a ejecutarla mediante "java Array3 Esto es una prueba", es decir, vamos a pasar argumentos a nuestro programa. Dichos argumentos son recibidos dentro del array llamado arg que existe en la definición del método main.

Agreguemos el siguiente código dentro del fichero Array3.java:

public class Array3

{

public static void main(String arg[])

{

System.out.println( "Hay " + arg . length + " parametros." );

System.out.println( "Los parámetros son: " );

int i = 0;

while(i

System.out.println( "parámetro " + i + ": " + arg[i]);

i++;

}

}

}

Práctica con matrices, arrays o vectores (II)  

Posted by Danny in ,

Ahora vamos a tratar de escribir el mismo código, pero empleando en lugar del tipo int, el tipo Persona:

Práctica:

Crear el fichero Array2.java

Agregar el siguiente código en el fichero:

public class Array2

{

public static void main(String arg[])

{

Persona [] lasPersonas = new Persona[10];

lasPersonas[4].setNombre("Luis");

System.out.println(lasPersonas [4].getNombre());

}

}

Veamos: definimos un array de 10 objetos de tipo Persona y lo asignamos a la variable lasPersonas. Accedemos a la persona 4 del array y la asignamos un nombre al objeto 4 mediante el método setNombre de la clase Persona. Posteriormente mostramos por pantalla el nombre del objeto Persona 4.

Compilemos y ejecutemos: ERROR!!! Al ejecutar genera el error NullPointerException. La explicación es sencilla: Al crear un array de objetos en realidad el array no contiene objetos, sino que contiene variables de tipo referencia para apuntar a los objetos. Arreglemos nuestro código para poder ejecutarlo de nuevo:

Persona [] lasPersonas = new Persona[10];

lasPersonas[4] = new Persona();

lasPersonas[4].setNombre("Luis");

System.out.println(lasPersonas [4].getNombre());

Si es necesario se puede averiguar el tamaño de cualquier array java, mediante de un atributo público que poseen todos los objetos de tipo array, independientemente del tipo de objetos que almacene dicho array en su interior. Este atributo se denomina length y para usarlo:

miArray.length

En la siguiente práctica usaremos dicho atributo para crear un bucle (los veremos más adelante) que permita mostrar por pantalla todos los elementos que hay en un array llamado arg.

Práctica con matrices, arrays o vectores (I)  

Posted by Danny in ,

Crear el fichero Array.java

Agregar el siguiente código en el fichero:

public class Array

{

public static void main(String arg[])

{

int [] losValores = null;

losValores[4] = 100;

System.out.println(losValores[4]);

}

}

Compilamos el código, ejecutemos y...error!!! Parece extraño que el error sea NullPointerException, pero tiene sentido, recordemos que una variable java, que no sea de tipo básico es una referencia que puede apuntar a objetos y por tanto losValores también es una referencia y debe de apuntar a objetos de tipo array de enteros. Es decir, el código de la función main es necesario modificarlo:

int [] losValores = new int[10];

losValores[4] = 100;

La modificación consiste básicamente en asignar a la variable losValores un objeto de tipo array de enteros. La sintaxis para crear un objeto de tipo array es:

new tipo[cantidad]

Donde tipo es el tipo de datos que contendrá el array. cantidad es el número máximo de elementos que podemos almacenar dentro del array. A la hora de acceder a las posiciones del array hay que tener en cuenta que la primera posición es 0 y la última cantidad-1.




Matrices, arrays o vectores en java  

Posted by Danny in

Java posee la capacidad de definir un conjunto de variables del mismo tipo agrupadas todas ellas bajo un mismo nombre, y distinguiéndolas mediante un índice numérico.

Para definir un array en java es como definir una variable o atributo, pero al especificar el tipo lo que hacemos es colocar un par de corchetes [] para indicar que lo que estamos definiendo es un array. Por ejemplo:

public int [] losValores;

en la que definimos un array de enteros llamado losValores. Vamos a intentar realizar un ejemplo para ver como funciona:

Práctica:

Crear el fichero Array.java

Agregar el siguiente código en el fichero:

public class Array

{

public static void main(String arg[])

{

int [] losValores = null;

losValores[4] = 100;

System.out.println(losValores[4]);

}

}

Compilamos el código, ejecutemos y...error!!! Parece extraño que el error sea NullPointerException, pero tiene sentido, recordemos que una variable java, que no sea de tipo básico es una referencia que puede apuntar a objetos y por tanto losValores también es una referencia y debe de apuntar a objetos de tipo array de enteros. Es decir, el código de la función main es necesario modificarlo:

int [] losValores = new int[10];

Prácticas con la herencia en java  

Posted by Danny in

Ahora vamos a agregar la función getNombre dentro de la clase Taxista, es decir, tenemos la misma función en Persona y en Taxista:

public String getNombre()

{

return "Soy un taxista y me llamo: " + super.getNombre();

}

Compilamos Taxista y ejecutamos ArranqueTaxista2. Veremos que el mensaje que aparece en pantalla demuestra que la función getNombre llamada es la de del tipo real del objeto construido, en este caso la de la clase derivada que es Taxista.

Tambien apreciamos que para acceder al atributo nombre es necesario acceder al método getNombre de la clase base (y por ello emplear super).

En java los atributos y métodos de la clase base pueden cambiar su modificador de visibilidad dentro de la clase derivada, la siguiente tabla recoge dichos cambios:

Modificadores en la clase base

public

private

protected

paquete

En la clase derivada se transforman en

public

inaccesible

protected

paquete

Inaccesible significa que, a pesar de haber sido heredado, no hay permisos en la clase derivada para poder acceder a dicho elemento inaccesible, pero aún así, se pueden llamar a métodos de la clase base que si pueden acceder y modificar al elemento.

Recordemos que protected significa que es private, pero que al heredar no se hace inaccesible, es decir que desde la clase derivada se puede acceder.

La herencia en java (III)  

Posted by Danny in

Se genera un error de compilación, debido a que los constructores no se heredan, sino que hay que definir nuestros propios constructores. Agreguemos en la clase Taxista los siguientes constructores:

public Taxista(int licencia)
{
super();
nLicencia = licencia;
}
public Taxista(String nombre,int licencia)
{
super(nombre);
nLicencia = licencia;
}

Ahora si podremos compilar y ejecutar la clase ArranqueTaxista2. La llamada al método super indica que estamos llamando a un constructor de la clase base (pensemos que un Taxista antes que Taxista es Persona y por tanto tiene sentido llamar al constructor de Persona antes que al de Taxista). Además gracias al número de parámetros de la llamada a super podemos especificar cuál de los constructores de la clase base queremos llamar.

En java se pueden emplear dos palabras clave: this y super .

Como vimos en la introducción a la programación orientada a objetos, this hace alusión a todo el objeto y super hace alusión a la parte heredada, por ello empleamos super para referenciar al constructor de la clase base.

La herencia en java (II)  

Posted by Danny in

Y construyamos ArranqueTaxista.java:

public class ArranqueTaxista {

public static void main (String arg[]){

Taxista tax1 = new Taxista();

tax1.setNombre("Luis");

tax1.setEdad(50);

System.out.println( tax1.getNombre());

System.out.println(tax1.getEdad());

}

}

Ahora intentemos usar el constructor que existía en la clase Persona que recibia el nombre de la persona y vamos a usarlo para la clase Taxista. Para ello construyamos la clase ArranqueTaxista2.java:

public class ArranqueTaxista2 {

public static void main (String arg[]){

Taxista tax1 = new Taxista("Jose");

tax1.setEdad(50);

System.out.println( tax1.getNombre());

System.out.println(tax1.getEdad());

System.out.println(tax1.getNLicencia());

}

}

 

Posted by Danny in

Java permite el empleo de la herencia , característica muy potente que permite definir una clase tomando como base a otra clase ya existente. Esto es una de las bases de la reutilización de código, en lugar de copiar y pegar.

En java, como ya vimos la herencia se especifica agregando la claúsula extends después del nombre de la clase. En la claúsula extends indicaremos el nombre de la clase base de la cuál queremos heredar.

Al heredar de una clase base, heredaremos tanto los atributos como los métodos, mientras que los constructores son utilizados, pero no heredados.

Practicas:

Construyamos la clase Taxista.java con el siguiente código:

public class Taxista extends Persona {

private int nLicencia;

public void setNLicencia(int num)

{

nLicencia = num;

}

public int getLicencia()

{

return nLicencia;

}

}

Prácticas con Definición de constructores de una clase  

Posted by Danny in ,

Vamos a agregar a la clase Persona un par de constructores, uno que la inicialice asignando a la edad un valor 0 y al nombre "anónimo", y otro que permita asignar al nombre un parámetro recibido en el constructor:

public Persona(){

edad = 0;

nombre = "anónimo";

}

public Persona(String nuevoNombre){

edad = 0;

nombre = nuevoNombre;

}

y vamos a crear una clase ArranqueConstructor con el siguiente código:

public class ArranqueConstructor {

public static void main (String arg[]){

Persona per1 = new Persona();

System.out.println( per1.getNombre());

System.out.println(per1.getEdad());

Persona per2 = new Persona("Luis");

System.out.println( per2.getNombre());

System.out.println(per2.getEdad());

}

}

Definición de constructores de una clase (II)  

Posted by Danny in

Para modifVisibilidad se aplica las mismas normas que para atributos y métodos:

public: indica que es un método accesible a través de una instancia del objeto.

private: indica que a través de una instancia no es accesible el método. Al heredar el método se convierte en inaccesible.

protected: indica que a través de una instancia no es accesible el método. Al heredar si se puede usar desde la clase derivada.

Sin especificar: indica visibilidad de paquete, se puede acceder a través de una instancia, pero sólo de clases que se encuentren en el mismo paquete.

nombreConstructor debe de coincidir con el nombre de la clase.

listaParámetros es la lista de los parámetros que tomará la función separados por comas y definidos cada uno de ellos como:

tipo nombreParámetro

La cláusula opcional throws es empleada para indicar que, dentro del método, se pueden generar errores en su ejecución, y que debemos estar preparados para tratarlos.

listaExcepciones es el nombre de todos esos posibles errores, su utilización la veremos en el punto dedicado a la gestión de errores mediante try y catch.

El constructor posee un par de llaves, dentro de las cuales estará el código que se ejecutará al ser llamada la función. Dicho código estará formado por instrucciones válidas en el lenguaje, finalizadas generalmente por punto y coma.

Definición de constructores de una clase  

Posted by Danny in

Cuando se construye un objeto es necesario inicializar sus variables con valores coherentes, imaginemos un objeto de la clase Persona cuyo atributo color de pelo al nacer sea verde, un estado incorrecto tras construir el objeto persona. La solución en los lenguajes orientados a objetos es emplear los constructores. Un constructor es un método perteneciente a la clase que posee unas características especiales:

Se llama igual que la clase.

No devuelve nada, ni siquiera void.

Pueden existir varios, pero siguiendo las reglas de la sobrecarga de funciones.

De entre los que existan, tan sólo uno se ejecutará al crear un objeto de la clase.

Dentro del código de un constructor generalmente suele existir inicializaciones de variables y objetos, para conseguir que el objeto sea creado con dichos valores iniciales.

Para definir los constructores se emplea la siguiente sintaxis:

[modifVisibilidad] nombreConstructor (listaParámetros) [throws listaExcepciones]

{

}

Práctica con definición de métodos de una clase II  

Posted by Danny in ,

Regresemos a la clase Arranque, y localicemos dentro del método main la línea comentada

//per1.nombre = "Luis"

Vamos a sustituirla (como está comentada no es necesario borrarla) por:

per1.setNombre("Luis");

Lo mismo vamos realizar en la segunda línea comentada, sustituyamosla por:

System.out.println(per1.getNombre());

Compilamos y ejecutamos la clase Arranque.

Ahora estaremos pensando que para que necesitamos métodos públicos para acceder a variables privadas cuando es más sencillo tener variables públicas y acceder a ellas libremente sin tener que emplear funciones. Vamos a modificar algunas cosas para entender porque es más interesante emplear funciones de acceso a atributos privados.

Modificar el código de la función setEdad para que sea:

if(laEdad<0){>

System.out.println("Una persona no puede tener una edad negativa.");

}

else

{

edad = laEdad;

}

Volvamos a la clase Arranque, en el método main, y además del código que ya hay en su interior agregaremos:

per1.setEdad(4);

System.out.println(per1.getEdad());

per1.setEdad(-35);

Compilar y ejecutar la clase Arranque.

Práctica con Definición de métodos de una clase  

Posted by Danny in ,

Continuamos con la clase Persona:

Vamos a crear 4 métodos que permitan acceder a los atributos privados de la clase persona. Los agregamos dentro de la clase:

public int getEdad()

{

return edad;

}

public void setEdad(int laEdad)

{

edad = laEdad;

}

public String getNombre()

{

return nombre;

}

public void setNombre(String elNombre)

{

nombre = elNombre;

}

Definición de métodos de una clase II  

Posted by Danny in

listaParámetros es la lista de los parámetros que tomará la función separados por comas y definidos cada uno de ellos como:

tipo nombreParámetro

modifFunción puede tener los siguientes valores:

static: el método pertenece a la clase, no a los objetos creados a partir de la clase.

final: el método no puede ser sobrescrito en una clase derivada.

abstract: En esta clase no se proporciona el código para la función, se debe de proporcionar en alguna clase derivada. En el caso de poseer un método abstracto la clase debe de llevar a su vez el modificador abstract. En caso de ser abstracto un método, se debe de sustituir las llaves que contienen el código por un punto y coma.

native: Es un método no escrito en java, sino en código nativo, que será usado en java como un método propio de java.

synchronized: Es un método que sólo puede ser ejecutado por un hilo, y hasta que ese hilo no acabe la llamada al método, no puede comenzar la llamada al método otro hilo. Lo emplearemos al trabajar con hilos.

La cláusula opcional throws es empleada para indicar que dentro del método se pueden generar errores en su ejecución, y que debemos estar preparados para tratarlos.

listaExcepciones es el nombre de todos esos posibles errores, su utilización la veremos en el punto dedicado a la gestión de errores mediante try y catch.

El método posee un par de llaves, dentro de las cuales estará el código que se ejecutará al ser llamada la función. Dicho código estará formado por instrucciones válidas en el lenguaje, finalizadas generalmente por punto y coma.

Definición de métodos de una clase I  

Posted by Danny in

Para definir los métodos se emplea la siguiente sintaxis:

[modifVisibilidad] [modifFunción] tipo nombreFunción (listaParámetros) [throws listaExcepciones]

{

}

Para modifVisibilidad se aplica las mismas normas que para atributos:

public: indica que es un método accesible a través de una instancia del objeto.

private: indica que a través de una instancia no es accesible el método. Al heredar el método se convierte en inaccesible.

protected: indica que a través de una instancia no es accesible el método. Al heredar si se puede usar desde la clase derivada.

Sin especificar: indica visibilidad de paquete, se puede acceder a través de una instancia, pero sólo de clases que se encuentren en el mismo paquete.

nombreFunc debe de ser un identificador válido en el lenguaje.

tipo es el tipo del valor devuelto por la función, pudiendo ser:

Un tipo básico.

Un objeto de una clase o interfaz. En este tipo de objetos se incluyen las matrices o vectores.

void, en el caso de no devolver ningún valor.

BlogESfera Directorio de Blogs Hispanos - Agrega tu Blog

Archives