jueves, 23 de diciembre de 2010

TODO ES UN OBJETO

TEMA 2
TODO ES UN OBJETO

  • Los objetos se manipulan mediante referencias
  • Es necesario crear todos los objetos
    • Los lugares de almacenamiento
    • Caso especial: tipos primitivos
    • Matrices en Java
  • Nunca es necesario destruir un objeto
    • Ámbito
    • Ámbito de los objetos
  • Creación de nuevos tipos de datos: class
    • Campos y métodos
  • Métodos, argumentos y valores de retorno
    • La lista de argumentos
  • Construcción de un programa java
    • Visibilidad de los nombres
    • Utilización de otros componentes
    • La palabra clave static
  • Nuestro primer programa Java
    • Compilación y ejecución
  • Comentarios y documentación embebida
    • Documentación mediante comentarios
    • Sintaxis
    • HTML embebido
    • Algunos marcadores de ejemplo
    • Ejemplo de documentación
  • Estilo de codificación
  • Ejercicios


Si habláramos otro lenguaje, percibiríamos un mundo algo distinto. (Ludwig Wittgenstein)

TODO ES UN OBJETO
Java está basado en C++ pero está más orientado a objetos.
C++ y Java son lenguajes híbridos, es decir, permiten múltiples estilos de programación. C++ es más híbrido que Java, por eso soporta compatibilidad descendente con C (cualquier compilador de C++ compila C). C++ es un superconjunto de C y por tanto incluye algunos de los aspectos menos deseables de este lenguaje.
Cuando vamos a programar en Java debemos tener presente que sólo lo podemos hacer mediante programación orientada a objetos, por tanto, tenemos que tener la mente en este tipo de programación. La ventaja es que programaremos en un lenguaje fácil de aprender y utilizar. En Java casi todo es un objeto.


Los objetos se manipulan como referencias
En Java todo se trata como un objeto, pero los identificadores que manipulamos son en realidad referencias a objetos. Por ejemplo, una televisión sería el objeto y el mando sería la referencia. Cuando queremos cambiar de canal o subir el volumen utilizamos la referencia mando que manipula el objeto televisión, necesitamos la referencia para manejar el objeto.
El mando a distancia puede existir sin que haya una televisión, es decir, puede haber una referencia sin objeto. Así, si queremos almacenar una palabra o frase, podemos crear una referencia de tipo String:


String s;


Aquí sólo tenemos la referencia a un objeto. Si mandásemos un mensaje a s en este momento, obtendríamos un error porque s no está asociado a nada (no hay televisión). Por tanto, cada vez que creemos una referencia debemos inicializarla.


String s=”Hola”;


Esta inicialización es un poco especial. Ya veremos que cada vez que queramos inicializar una referencia hay una forma más general de hacerlo.

Es necesario crear todos los objetos
Cada vez que se crea una referencia es necesario asociarla a un objeto. Para ello se emplea new, lo cual significa crear un nuevo ejemplar de ese tipo de objeto. El ejemplo anterior se podría escribir así:


String s=new String(“Hola”);


Aquí no sólo inicializamos un nuevo objeto String, sino que le proporcionamos información de cómo hacerlo.

Java tiene una multitud de tipos predefinidos como String, pero nosotros también podremos crear nuestros propios tipos.

Los lugares de almacenamiento
Vamos a ver cómo está organizada la memoria cuando ejecutamos un programa:

  1. Registros. Los registros se encuentran dentro del procesador y por tanto, es el tipo de almacenamiento más rápido. El inconveniente es que el número de registros es pequeño y sólo se asignan según vayan siendo necesarios. Nosotros no podemos controlarlos mediante Java.
  2. La pila. Esta zona se encuentra en la RAM y el procesador tiene soporte directo para la pila, el puntero de pila. El puntero se mueve hacia abajo para crear memoria y hacia arriba para liberarla. Es una forma rápida de asignar memoria. Sin embargo a la hora de crear el programa, Java debe conocer el tiempo de vida de todos los elementos que se almacenan en la pila. Por este motivo los objetos Java no se colocan en la pila y sí las referencias a objetos.
  3. El cúmulo. También se sitúa dentro de la RAM y aquí se colocan todos los objetos Java. El compilador no necesita saber el tiempo que los objetos van a ocupar el espacio de almacenamiento dentro del cúmulo. Cada vez que creamos un objeto con new, se le asigna un espacio de almacenamiento en el cúmulo en el momento de la ejecución. El inconveniente que tenemos es que necesitamos más tiempo para asignar y liberar espacio en este área de almacenamiento.
  4. Almacenamiento constante. Los valores constantes se suelen ubicar dentro del código del programa y nunca varían. Las constantes se almacenan por separado, incluso se pueden almacenar en memorias ROM.
  5. Almacenamiento fuera de la RAM. Hay datos que pueden existir incluso cuando el programa no se esté ejecutando. Los ejemplos principales son los objetos stream, en los cuales los objetos se transforman en flujos de bytes, normalmente para enviarlos a otras máquinas y los objetos persistentes que son objetos que se almacenan en disco conservando su estado incluso después de finalizar el programa. Los objetos almacenados de este modo deben ser transformados en objetos normales basados en RAM cuando sea necesario.
Caso especial: tipos primitivos
Hay un grupo especial de tipos que se utilizan mucho, los tipos predefinidos, que tienen un tratamiento especial. Si creamos un objeto con new, éste se almacenaría en el cúmulo. Sin embargo, si creamos una variable “automática” que no es una referencia, almacenaría el valor de la variable directamente y se colocaría en la pila, siendo por tanto mucho más eficiente.
Java determina el tamaño de los tipos predefinidos y éstos no cambian de una arquitectura de máquina a otra. Este es uno de los motivos por los que los programas Java son muy portables. A continuación tenemos una tabla con los tipos predefinidos:




Tipo primitivoTamañoMínimoMáximoTipo envoltorio
boolean---Boolean
char16 bitsUnicode 0Unicode 2 16-1Character
byte8 bits-128127Byte
short16 bits-2 15+2 15-1Short
int32 bits-2 31+2 31-1Integer
long64 bits-2 63+2 63-1Long
float32 bitsIEEE754IEEE754Float
double64 bitsIEEE754IEEE754Double
void---Void

Todos los números tienen signo.
Los tipos “envoltorio” permiten crear tipos predefinidos que se almacenen en el cúmulo y que se traten como objetos.


char c='x';
Character ch=new Character(c);


Hay una característica en Java SE5 llamada autoboxing que permite convertir un tipo primitivo a uno envoltorio y viceversa, así:


Character ch='x';


Y a la inversa:


char c=ch;


Aritmética de alta precisión
Tenemos dos clases para realizar aritmética de alta precisión: BigInteger y BigDecimal. No tienen el correspondiente tipo primitivo.
Ambas clases disponen de métodos para realizar las operaciones que se realizan con los tipos primitivos.

  • BigInteger. Soporta números enteros de precisión arbitraria. Podemos representar valores enteros de cualquier tamaño sin perder información.
  • BigDecimal. Soporta números de coma fija y precisión arbitraria. Un ejemplo de uso es la realización de cálculos monetarios precisos.
Matrices en Java
Casi todos los lenguajes de programación soportan algún tipo de matriz.
En Java se garantiza que las matrices siempre son inicializadas y que no podemos acceder a un elemento que esté fuera del rango autorizado. Esto último conlleva gastar una pequeña cantidad de memoria adicional y también tiempo, ya que se comprueban los índices de la matriz en tiempo de ejecución. El resultado es un incremento en la productividad y la mejora de la seguridad.
Cuando creamos una matriz, es una matriz de referencias con un valor null para cada uno de sus valores. Por tanto es necesario asignar un objeto a cada referencia antes de utilizarla, ya que si se intenta usar una referencia sin haber sido inicializada, nos encontraremos con un error en tiempo de ejecución.
Si la matriz es de tipos primitivos, el compilador rellena de ceros la memoria de la matriz.

Nunca es necesario destruir un objeto

En algunos lenguajes de programación el tiempo de vida de una variable, desde que se crea hasta que se destruye, requiere un gran esfuerzo de programación. Sin embargo en Java este problema se simplifica mucho.

Ámbito

El ámbito define el tiempo de vida y la visibilidad de lo nombres definidos dentro del mismo. En Java lo vemos con un ejemplo:


{
int x=12;
{
int q=96;
// Aquí están disponibles tanto x como q
}
// Aquí sólo está disponible x, q está fuera del ámbito
} 


Una variable definida en un ámbito está disponible hasta que ese ámbito termina.

La sangría izquierda que se añade en un programa de Java facilita la lectura del código. A la hora de la compilación no se tienen en cuenta estos espacios en blanco (espacios, tabuladores, retornos de carro).

Lo siguiente no es correcto:

{
int x=12;
{
int x=14;
}
}

Ámbito de los objetos
Los objetos en java no tienen el mismo tiempo de vida que las primitivas. Cuando creamos un objeto con new, éste continúa existiendo una vez que se ha alcanzado el final del ámbito. Si usamos:



{
String s=new String(“Cadena de caracteres”);
} 



La referencia s desaparece al finalizar el ámbito, sin embargo, el objeto String continuará ocupando memoria. Después de alcanzar el final del ámbito, no hay forma de acceder al objeto.

Pero entonces en Java, ¿los objetos existen perpetuamente? ¿Por qué no se llena la memoria? En Java hay una varita mágica, el depurador de memoria, que examina la memoria y determina qué objetos creados con new no tienen ninguna referencia que les apunte. La memoria ocupada por estos objetos es liberada y así puede ser utilizada para crear otros objetos nuevos. No nos tenemos que preocupar por tanto de liberar memoria, así evitamos las “fugas de memoria” que se producen en otros lenguajes cuando un programador se olvida de liberar la memoria.

Creación de nuevos tipos de datos

Si todo es un objeto, ¿qué determina su comportamiento y qué aspecto tiene una clase concreta de objeto? La mayoría de los lenguajes orientados a objetos han utilizado la palabra clave class para definir el aspecto de un nuevo tipo de objeto. Una nueva clase se define del siguiente modo:

class ATypeName {
/* Cuerpo de la clase */
}


Con esta clase no podríamos hacer nada ya que el cuerpo de la clase es un comentario, pero sí que podríamos definir un objeto de esta clase utilizando new de la forma:


ATypeName a=new ATypeName(); 


Campos y métodos
En una clase se pueden definir dos tipos de elementos: campos (miembros de datos) y métodos (funciones miembro). Un campo es un objeto de cualquier tipo con el que nos comunicamos a través de su referencia o bien un tipo primitivo. Si es una referencia a un objeto hay que inicializar esa referencia con new, (asociar el mando con la televisión).

Cada objeto tiene su propio almacenamiento para sus campos, los campos normales no son compartidos entre los distintos objetos. Ejemplo de clase con algunos campos definidos:
class SoloDatos{
int i;
double d;
boolean b;
}

Esta clase solo almacena datos, pero podemos crear un objeto de esta clase:


SoloDatos datos=new SoloDatos();


Podríamos asignar valores a los campos. Para referirnos a un miembro de un objeto debemos indicar el nombre de la referencia al objeto, seguida de un punto y el nombre del miembro concreto dentro del objeto, por ejemplo:
datos.i=48;
datos.d=1.45;
datos.b=false;

También es posible que el objeto contenga otros objetos, que a su vez contengan los datos que queremos modificar, basta con utilizar los puntos necesarios. Por ejemplo:


myPlane.leftTank.capacity=100;


Para comprender cómo funcionan los métodos, es preciso entender primero los conceptos de argumentos y valores de retorno que definiremos en breve.

Valores predeterminados de los miembros de tipo primitivo
Cuando tenemos variables de tipo primitivo, Java garantiza que tendrán un valor predeterminado en caso de que no se inicialicen:

Tipo primitivo Valor predeterminado
boolean False
char 'u\0000' (null)
byte (byte) 0
short (short) 0
int 0
long 0L
float 0.0f
double 0.0d

Los valores predeterminados son sólo los valores que Java garantiza cuando se emplea la variable como miembro de una clase. Así, las variables miembro siempre son inicializadas, reduciendo así posibles errores. Sin embargo, lo mejor es inicializar siempre las variables, ya que este valor inicial puede no ser correcto.

Esta inicialización no se aplica a las variables locales, aquellas que no son campos de clase. Si en un método tenemos:


int x;


Esta variable adoptaría algún valor arbitrario. Si no le asignamos ningún valor, en Java tendríamos un error en tiempo de compilación.

Métodos, argumentos y valores de retorno
En muchos lenguajes (como C y C++), una función es una subrutina con nombre. En Java el término más común es método, es decir, una forma de llevar algo a cabo.

Los métodos determinan los mensajes que un objeto puede recibir. Las partes de un método son: nombre, argumentos, tipo de retorno y cuerpo. La forma básica sería:

TipoRetorno NombreMetodo(/*Lista de argumentos */){
/*Cuerpo del método */
}

El tipo de retorno es el valor devuelto por el método después de ser invocado. La lista de argumentos es la lista de los tipos y nombres de las variables que hayamos pasado al método. El nombre del método y la lista de argumentos identifican de forma unívoca al método.

Los métodos sólo se pueden crear dentro de una clase, sólo se pueden invocar para un objeto (excepto los métodos static) y dicho objeto debe ejecutar esa invocación de método. Para invocar un método para un objeto, se nombra el objeto seguido de un punto y el nombre del método más la lista de argumentos:


NombreObjeto.NombreMetodo(arg1,arg2,arg3);


Supongamos que tenemos un método f() sin argumentos que devuelve un valor de tipo int. Si tuviéramos un objeto a para el que pudiera invocarse f() tendríamos:


int x=a.f();


El valor de retorno es compatible con x. La invocación de un método se denomina enviar un mensaje a un objeto. En el ejemplo anterior el mensaje es f() y el objeto a. Por eso se dice que la POO consiste en enviar mensajes a objetos.

La lista de argumentos
La lista de argumentos especifica la información que se le pasa al método. Esta información adopta la forma de objetos. En la lista de argumentos se especifican el tipo y el nombre de los objetos. Lo que realmente pasaremos son referencias. El tipo de la referencia debe ser correcto. Si el argumento es String deberemos pasar un String, si no tendremos un error en tiempo de compilación.

Un ejemplo de método en cuya lista de argumentos admite un String sería:

int storage(String s){
return s.length()*2;
}

El método nos dice el número de bytes necesarios para almacenar un objeto String, cada char en un objeto String ocupa 2 bytes. Se utiliza el método length() que devuelve el número de caracteres que hay en una cadena.

La palabra clave return le dice al método que finalice y también si el método ha generado algún valor, se indica a continuación de return. Por ejemplo, return s.length()*2.

Si no queremos devolver nada, utilizamos la palabra clave void, veamos algunos ejemplos:
boolean flag(){ return true; }
double naturalLogBase(){ return 2.718; }
void nothing(){ return; }
void nothing2(){}

Cuando un método devuelve void es necesario indicar el final del método con return. Todos los métodos que devuelvan un tipo diferente de void, deberán devolver un valor del tipo apropiado, independientemente del lugar en que salgamos del método.

Un programa consiste en una serie de objetos con métodos que aceptan otros objetos como argumentos y envían mensajes a esos otros objetos.

Construcción de un programa Java

Visibilidad de los nombres
Uno de los problemas que nos podemos encontrar en cualquier lenguaje de programación es el control de los nombres. Si empleamos un nombre en un módulo de un programa y ese mismo nombre lo utilizamos en otro módulo del programa, ¿cómo distinguimos un nombre del otro y cómo evitamos la colisión entre los dos nombres?

En Java para generar un nombre no ambiguo para una biblioteca se emplean los nombres de dominio de Internet en orden inverso, ya que los nombres de dominio son unívocos. Si tenemos el nombre de dominio ejemplo.com, una biblioteca de utilidades llamada tabla se denominaría com.ejemplo.utilidades.tabla. Después del nombre del dominio invertido, los puntos representan subdirectorios. Los nombre completos de paquetes se escriben en minúsculas.

Utilización de otros componentes
Si en un archivo de código fuente tenemos más de una clase, las podemos utilizar de manera directa.
Pero, ¿qué pasa con las clases almacenadas en otros archivos? Para decirle al compilador qué clases vamos a emplear debemos importarlas con la palabra clave import. Con import cargamos un paquete, que en realidad es una biblioteca de clases. Un ejemplo:


import java.util.ArrayList; 


Con esto le decimos al compilador que queremos utilizar la clase ArrayList de util. Si escribimos:


import java.util.*;


Podríamos utilizar todas las clases de util.

La palabra clave static
Cuando creamos una clase en realidad lo que hacemos es describir el aspecto de los objetos y su comportamiento. Hasta que no creamos un objeto con new no tendremos ningún objeto, es en ese momento cuando se asigna el almacenamiento y los métodos del objeto están disponibles.

Existen dos situaciones en las que esta técnica no es suficiente. Una es cuando queremos disponer de un único espacio de almacenamiento para un campo concreto, independientemente del número de objetos que se creen, incluso si no se crea ninguno. La otra situación es cuando queremos disponer de un método que no esté asociado a ningún objeto concreto de esa clase y al que podamos invocar incluso cuando no se cree ningún objeto.

Ambas cosas podemos conseguirlas utilizando la palabra clave static. Todos los campos o métodos static pueden ser invocados sin necesidad de crear ningún objeto de esa clase, cosa que sí es necesaria para los campos y métodos no static. Los métodos static no pueden acceder directamente a ningún miembro o método que no sea static.

A estos campos y métodos nos podemos referir utilizando los términos datos de la clase y métodos de la clase.

Vamos a ver cómo se crearía un campo static:
class StaticTest {
static int i=47;
}

Si creamos dos objetos StaticTest existiría un único espacio de almacenamiento para la variable i. Así:


StaticTest st1=new StaticTest();
StaticTest st2=new StaticTest();


Tanto st1.i y st2.i tienen el mismo valor 47 porque hacen referencia a la misma posición de memoria.

Aunque podemos hacer referencia a una variable static de la forma anterior (st1.i y st2.i), lo normal es que se haga de la siguiente manera:


StaticTest.i;


Nombre de la clase seguida de la variable static, así se distingue más claramente de una variable normal. Con los métodos ocurre lo mismo, si tenemos:



class Incrementable{static
void increment() {
StaticTest.i++;
}
}


Podemos referirnos al método de las formas:


Incrementable sf =new Incrementable();
sf.increment();

O bien:


Incrementable.increment();


Esta sería la forma más normal.

Cuando creamos un campo static, creamos un campo global para la clase. También cuando creamos un método static, además podemos invocar tanto objetos como métodos sin necesidad de crear objetos y esto es muy importante sobre todo para los métodos.

Nuestro primer programa Java
Vamos a escribir nuestro primer programa en Java.
// HelloDate.java

import java.util.*;

public class HelloDate{

public static void main(String[] args){
System.out.println(“Hola, hoy es: “);
System.out.println(new Date());
}
}

Al principio del programa tenemos las instrucciones import necesarias para cargar las clases adicionales que vamos a necesitar. Hay una biblioteca de clases que se carga automáticamente, java.lang. Podemos descargarnos de la página http://www.oracle.com/technetwork/java/index.html la documentación del kit JDK, donde vienen explicadas todas las clases incluidas en Java. En nuestro programa, como la clase Date no está incluida en java.lang hay que importarla de su biblioteca correspondiente, en este caso java.util. Si no sabemos donde está una biblioteca, podemos seleccionar Tree en la documentación de Java y vemos todas las clases incluidas. Con la función Buscar encontraremos Date.

La clase java.lang.System tiene varios campos entre ellos out. Se trata de un objeto staticPrintStream por lo que no es necesario crear ningún objeto con new. Lo que puede hacerse con este objeto está determinado por su tipo PrintStream. Dentro de PrintStream hay varios métodos, en el caso del ejemplo se utiliza println() que imprime un mensaje que se le pasa como argumento en la consola y termina con un carácter de avance de línea.

El nombre del archivo que contiene la clase tiene que coincidir con el nombre de la clase y la extensión es java, en nuestro ejemplo el archivo se llamaría HelloDate.java. Si el programa contiene más de una clase al menos una de ellas tiene que coincidir con el nombre del archivo. Esta clase tiene que tener un método main() de la siguiente forma:


public static void main (String[] args){

Este método está disponible para todo el mundo (public). El argumento de main es una matriz de objetos String. En esta matriz de objetos args se almacenan los argumentos de la línea de comandos.

La línea:


System.out.println(new Date());


El argumento de println es un objeto Date que se crea para enviar su valor. Una vez finalizada la instrucción este objeto es innecesario y el depurador lo podrá eliminar.

La clase System tiene muchos métodos que nos permiten producir muchos efectos interesantes, como información del entorno de ejecución, nombre de usuario y java.library.path.

Compilación y ejecución

Para compilar y ejecutar un programa Java necesitamos un entorno de programación Java. Hay disponibles diversos entornos de programación (Eclipse y Netbeans son quizá las más populares) pero en este libro se utiliza el kit de desarrollo JDK (Java Developer's Kit) de Oracle, el cual es gratuito. Eclipse y Netbeans son también gratuitos.

Desde http://www.oracle.com/technetwork/java/index.html podemos descargar el JDK para la plataforma que estemos utilizando.

Una vez instalado y modificado el path de manera correcta compilamos el programa de la siguiente forma:

javac HelloDate.java

Si no produce ninguna respuesta de error la compilación es correcta. Si hay algún mensaje de error éste describirá cuál es el problema.

Una vez compilado debemos ejecutar el programa de la siguiente manera:

java HelloDate

Obtendremos el mensaje y la fecha como salida.

Así se compilarán y ejecutarán todos los programas del libro. El código fuente de este libro también dispone de un archivo llamado build.xml en cada capítulo con comandos “Ant” para construir automáticamente los archivos correspondientes a ese capítulo. Los archivos de generación y Ant se describen en detalle en http://www.mindview.net/Books/BetterJava, una vez instalado Ant (http://ant.apache.org) basta con escribir ant en la línea de comandos para compilar y ejecutar los programas de cada capítulo.

Comentarios y documentación embebida
Existen dos tipos de comentarios en Java. Uno es de la forma /* y */, todo lo que vaya entre estos dos símbolos se ignora y puede ocupar varias líneas.
/* Este es un
* comentario que
* ocupa varias líneas
*/

También:


/* Este comentario ocupa
varias líneas */


El segundo tipo de comentario es de la forma // y sólo ocupa una línea. Es cómodo y sencillo.


// Este es un comentario monolínea.


Documentación mediante comentarios
La tarea más complicada a la hora de documentar código es mantener dicha documentación. Si separamos la documentación del código resulta bastante complicado modificar la documentación cada vez que se cambie el código. En Java se integra el código con la documentación y se incluye todo en un mismo archivo. Para ello se dispone de una sintaxis especial para los comentarios que componen la documentación, y alguna herramienta para extraer estos comentarios y formatearlos de manera útil.

La herramienta para extraer los comentarios es Javadoc que se instala con el JDK. Esta herramienta extrae los marcadores especiales de comentarios incluidos en un programa y el nombre de la clase o método asociado al comentario.

La salida de Javadoc es un archivo HTML que se puede ver con cualquier explorador web.

Si queremos realizar operaciones especiales con la información procesada por Javadoc disponemos de una herramienta llamada doclet. Los doclets se explican en el suplemento que encontramos en http://MindView.net/Books/BetterJava.

En la documentación del JDK podemos encontrar más información, más concretamente en el subdirectorio tooldocs.

Sintaxis
Todos los comandos están incluidos entre los símbolos /** y */. Hay dos formas de utilizar Javadoc, mediante HTML embebido o mediante marcadores de documentación. Los marcadores de documentación autónomos son comandos que comienzan con @ y se incluyen al principio de una línea de comentarios (un carácter inicial * será ignorado). Los marcadores de documentación en línea pueden incluirse en cualquier punto de un comentario Javadoc y también comienzan con @ pero van encerrados entre llaves.

Vamos a ver con un ejemplo los tres tipos de documentación de comentarios, cada comentario precede al elemento que comenta:
//: object/Documentation.java

/** Comentario de clase */
public class Documentation1{

/** Comentario de campo */
public int i;

/** Comentario de método */
public void f(){}
}

Javadoc sólo procesa la documentación de los comentarios para miembros public y protected. Los comentarios para miembros private y miembros con acceso de paquete se ignoran. Para incluir un comentario de un miembro private usaremos el indicador private para incluirlo.

Podemos guardar el ejemplo anterior como Documentation1.java y si hacemos:

javadoc Documentation1.java

Vemos que se generan varios archivos html, nos podemos ir a index.html o Documentation1.html donde se nos muestra la información que hemos incluido en los comentarios.

HTML embebido
Podemos añadir dentro de la documentación etiquetas HTML y así dar formato al código, por ejemplo:

/**
* < pre >
* System.out.println(new Date());
* < /pre >
*/

También podemos dar formato al texto de las descripciones:
/**
* Se puede < em > incluso < /em > insertar una lista:
*< ol >
*< li >Elemento uno< /li >
*< li >Elemento dos< /li >
*< li >Elemento tres< /li >
*< /ol >
*/

Los asteriscos situados al principio de cada línea son ignorados. No debemos utilizar encabezados como <h1> o <hr> en el HTML embebido porque Javadoc inserta sus propios encabezados

Algunos marcadores de ejemplo
Vamos a ver algunos marcadores Javadoc disponibles para la documentación de código. Para ver las diferentes formas de uso de Javadoc consultar la documentación del JDK.

@see
Permite hacer referencia a la documentación de otras clases. Javadoc genera el HTML necesario, hipervinculando los marcadores @see a los otros fragmentos de documentación. Las posibles formas de este marcador son:

@see nombre clase
@see nombreclase – completamente – cualificado
@see nombreclase – completamente – cualificado #nombre – método

Cada uno de estos marcadores añade una entrada “See also” hipervinculada al archivo de documentación generado. Javadoc no comprueba los vínculos.

{@link paquete.clase#miembro etiqueta}
Muy similar a @see, excepto porque se puede utilizar en línea y emplea la etiqueta como texto del hipervínculo en lugar de “See also”.

{docRoot}
Genera la ruta relativa al directorio raíz de la documentación. Útil para introducir hipervínculos explícitos a páginas del árbol de documentación.

{inheritRoot}
Este indicador hereda la documentación de la clase base más próxima de esta clase y la inserta en el comentario del documento actual.

@version
Tiene la forma:

@version información – versión

Información – versión es cualquier información significativa que queramos incluir. Esta información se muestra de forma especial en la documentación HTML generada.

@author
Tiene la forma:

@author información – autor

donde información – autor es normalmente nuestro nombre, o también podría ser nuestro correo electrónico, aunque podríamos incluir cualquier otra información adecuada. Esta información se muestra de manera especial en la documentación HTML generada.

Si vamos a añadir varios marcadores de autor para incluir una lista de autores, debemos poner estos marcadores de forma consecutiva y Javadoc los agrupará en un único párrafo.

@since
Permite indicar la versión del código en la que se empezó a usar una característica concreta. En la documentación HTML de Java se emplea para indicar qué versión del JDK se está utilizando.

@param
Se utiliza para la documentación de métodos y tiene la forma:

@param nombre – parámetro descripción

nombre – parámetro es el identificador dentro de la lista de parámetros del método y descripción es un texto explicativo. La descripción se considera acabada cuando nos encontramos con un nuevo marcador de documentación.

@return
Se utiliza para la descripción de métodos y es de la forma:

@return descripción

donde descripción indica el significado del valor de retorno. Puede ocupar varias líneas.

@throws
Las excepciones son objetos que pueden ser generados cuando un método falla. Sólo se puede generar un objeto de excepción cada vez que invocamos un método pero cada método puede generar diferentes tipos de excepciones, todas las cuales habrá que describir, así @throws tiene la forma:

@throws nombre – clase – completamente – cualificado descripción

donde nombre – clase – completamente – cualificado nos da un nombre no ambiguo de una clase de excepción definida en alguna otra parte y descripción (puede ocupar más de una línea) indica porqué razón puede generarse este tipo concreto de excepción después de la llamada al método.

@deprecated
Indica alguna característica que ha quedado obsoleta porque se ha introducido alguna otra característica mejorada. Nos indica que no se utilice esa característica concreta ya que seguramente en un futuro se eliminará. El compilador generará una advertencia si se usa un método marcado como @deprecated. En Java SE5 el marcador Javadoc @deprecated ha sido sustituido por la anotación @Deprecated.

Ejemplo de documentación
Vamos a añadir a nuestro primer programa Java comentarios de documentación:
//: object/HelloDate.java

import java.util.*;

/** El primer ejemplo del libro Piensa en Java
* Muestra un String y la fecha de hoy
* @author Bruce Eckel
* @author www.MindView.net
* @version 4.0
*/

public class HelloDate {

/** Punto de entrada a la clase y aplicación
* @param args El argumento es un array de string
* @throws exceptions Ninguna excepción lanzada
*/

public static void main(String[] args) {
System.out.println("Hola, hoy es: ");
System.out.println(new Date());
}
} /* Output: (55% match)
Hola, hoy es:
Wed Oct 05 14:39:36 MDT 2005
*///:~

La primera línea del archivo contiene el marcador especial '//:' seguido por la carpeta contenedora y el nombre del archivo fuente. La última línea termina con un comentario y éste '///:~' indica el final del listado de código fuente, lo que permite actualizarlo automáticamente dentro del texto de este libro después de comprobarlo con un compilador y ejecutarlo.

El marcador /* Output: indica el comienzo de la salida que generará este archivo. Con esta forma se puede comprobar automáticamente para verificar su precisión. El texto (55% match) indica al sistema de pruebas que la salida será bastante distinta en cada ejecución del programa, es decir, un 55% de correlación con la salida que aquí se muestra.

Estilo de codificación
Vamos a ver algunas “reglas” que se siguen al escribir código en Java. Los nombres de las clases comienzan por mayúsculas. Si el nombre de la clase tiene varias palabras, se pone en mayúscula la primera letra de cada palabra, por ejemplo, NombreDeClase.

Todos los demás elementos como nombres de métodos, campos y referencias a objetos se escriben igual pero la primera letra del identificador se escribe en minúscula, por ejemplo, nombreDeMetodo, nombreDeCampo.

La longitud de los identificadores no debe ser excesiva.

EJERCICIOS
Ejercicio 1. Cree una clase que contenga una variable int y otra char que no estén inicializadas e imprima sus valores para verificar que Java se encarga de realizar una inicialización predeterminada.
Ejercicio 2. A partir del ejemplo HelloDate.java de este capítulo, cree un programa "hello, world" que simplemente muestre dicha frase. Sólo necesitará un método dentro de la clase, (el método "main" que se ejecuta al arrancar el programa). Acuérdese de definir este método como static y de incluir la lista de argumentos, incluso aunque no la vaya a utilizar. Compile el programa con javac y ejecútelo con java. Si está utilizando otro entorno de desarrollo distinto de JDK, averigüe cómo compilar y ejecutar programas en dicho entorno.
Ejercicio 3. Recopile los fragmentos de código relacionados con ATypeName y transfórmelos en un programa que se pueda compilar y ejecutar.
Ejercicio 4. Transforme los fragmentos de código DataOnly en un programa que se pueda compilar y ejecutar.
Ejercicio 5. Modifique el ejercicio anterior de modo que los valores de los datos en DataOnly se asignen e impriman en main().
Ejercicio 6. Escriba un programa que incluya e invoque el método storage() definido como fragmento de código en el capítulo.
Ejercicio 7. Transforme los fragmentos de código Incrementable en un programa funcional.
Ejercicio 8. Escriba un programa que demuestre que, independientemente de cuántos objetos se creen de una clase concreta, sólo hay una única instancia de un campo static concreto definido dentro de esa clase.
Ejercicio 9. Escriba un programa que demuestre que el mecanismo automático de conversión de tipos funciona para todos los tipos primitivos y sus envoltorios.
Ejercicio 10. Escriba un programa que imprima tres argumentos extraídos de la línea de comandos. Para hacer esto, necesitará acceder con el índice correspondiente a la matriz de objetos String extraída de la línea de comandos.
Ejercicio 11. Transforme el ejemplo AllTheColorsOfTheRainbow en un programa que se pueda compilar y ejecutar.
Ejercicio 12. Localice el código para la segunda versión de HelloDate.java, que es el ejemplo simple de documentación mediante comentarios. Ejecute Javadoc con ese archivo y compruebe los resultados con su explorador web.
Ejercicio 13. Procese Documentation1.java, Documentation2.java y Documentation3.java con Javadoc. Verifique la documentación resultante con su explorador web.
Ejercicio 14. Añada una lista HTML de elementos a la documentación del ejercicio anterior.
Ejercicio 15. Tome el programa del Ejercicio 2 y añádale comentarios de documentación. Extraiga esos comentarios de documentación con Javadoc para generar un archivo HTML y visualícelo con su explorador web.
Ejercicio 16. En el Capítulo 5, Inicialización y limpieza, localice el ejemplo Overloading.java y añada documentación de tipo Javadoc. Extraiga los comentarios de documentación Javadoc para generar un archivo HTML y visualícelo con su explorador web.


4 comentarios:

  1. Creo que el ejemplo de creación de referencia mediante operador new citado no es correcto:

    1 String s=new s(“Hola”);// error

    debría ser

    1 String s=new String(“Hola”);

    Solo como reporte de error.

    Me parece muy interesante y util este blog y ánimo para seguir publicando los restantes temas.
    Saludos

    ResponderEliminar
  2. Hola:
    Pues tienes toda la razón del mundo, claro que está mal, ya lo he corregido. Gracias por avisarme de este error y me alegro de que te guste el blog. Quiero publicar todos los temas del libro, la pena es no tener más tiempo para hacerlo más rápido.
    Un saludo y gracias.

    ResponderEliminar
  3. Hola:
    Excelente el resumen del libro, la verdad que me sirve demasiado. Te hago una consulta, tendras los ejercicios resueltos? Gracias

    ResponderEliminar
    Respuestas
    1. Hola:

      Tienes todos los ejercicios resueltos en esta dirección:

      http://sites.google.com/site/piensaenjavadesdecero

      Esta dirección la tienes en un enlace situado arriba a la derecha del blog.

      Un saludo y espero que te sean de ayuda.

      Eliminar