martes, 31 de diciembre de 2013

El Collectioiis Framework de Java 1.2 - III

Clases Wrapper: Colecciones con características adicionales, como no poder ser modificadas o estar sincronizadas. No se accede a ellas mediante constructores, sino mediante métodos "factory** de la clase Collections. 
Clases de utilidad: Son mini-implementaciones que permiten obtener sets especializados, como por ejemplo sets constantes de un sólo elemento (singleton) o lists con ti copias del mismo elemento (nCopies). Definen las constantes EMPTY_SET y MPTY_LIST. Se accede a través de la clase Collections. 
Clases históricas: Son las clases Vector y Hashtable presentes desde las primeras versiones de Jara. En las versiones acmales. implementan respectivamente las interfaces List y Map. aunque conservan también los métodos anteriores. 
Clases abstractas: Son las clases abstract de la Figura 4.2. Tienen total o parcialmente implemen- tados los métodos de la interface correspondiente. Sirven para que los usuarios deriven de ellas sus propias clases con un mínimo de esfuerzo de programación. 
Algoritmos: La clase Collections dispone de métodos static para ordenar, desordenar, invertir orden, realizar búsquedas, llenar, copiar, hallar el mínimo y hallar el máximo. 
Clase Arrays: Es una clase de utilidad introducida en el JDK 1.2 que contiene métodos static para ordenar, llenar, realizar búsquedas y comparar los arrays clásicos del lenguaje. Permite también vel- los arrays como lists. Después de esta visión general de la Java Collections Framework. se verán algunos detalles de las clases e interfaces más importantes.

El Collectioiis Framework de Java 1.2 - II

Las clases Collections y Arrays son mi poco especiales: no son abstract. pero no tienen constructores públicos con los que se puedan crear objetos. Fundamentalmente contienen métodos static para realizar ciertas operaciones de utilidad: ordenar, buscar, introducir ciertas características en objetos de otras clases, etc. 
  Elementos del Java Collections Framework Interfaces de la JCF: Constituyen el elemento central de la JCF. 
• Collection: define métodos para tratar una colección genérica de elementos 
• Set: colección que no admite elementos repetidos 
• SortedSet: set cuyos elementos se mantienen ordenados según el criterio establecido 
• List: admite elementos repetidos y mantiene un orden inicial 
• Map: conjunto de pares clave/valor, sin repetición de claves 
• SortedMap: map cuyos elementos se mantienen ordenados según el criterio establecido 
Interfaces de soporte: 
• Iterator: sustituye a la interface Enumeratiou. Dispone de métodos para recorrer una colección y para borrar elementos. 
• Listlterator: deriva de Iterator y permite recorrer lists en ambos sentidos. 
• Comparable: declara el método compareToQ que permite ordenar las distintas colecciones según un orden natural (String. Date. Integer. Double. ...). 
• Comparator: declara el método compareQ y se utiliza en lugar de Comparable cuando se desea ordenar objetos no estándar o sustituir a dicha interface. 
Clases de propósito general: Son las implementaciones de las interfaces de la JFC. 
• Hash Set: Interface Set implementada mediante una hash table. 
• TreeSet: Interface SortedSet implementada mediante un árbol binario ordenado. 
• ArrayList: Interface List implementada mediante un array. 
• LinkedList: Interface List implementada mediante una lista vinculada. 
• Hash Map: Interface Map implementada mediante una hash table. 
• WeekHashMap: Interface Map implementada de modo que la memoria de los pares clave/valor pueda ser liberada cuando las claves no tengan referencia desde el exterior de la WeekHashMap. 
• TreeMap: Interface SortedMap implementada mediante un árbol binario

lunes, 30 de diciembre de 2013

El Collectioiis Framework de Java 1.2 - I

En la versión 1.2 del JDK se introdujo el Java Framework Collections o "estructura de colecciones de Java" (en adelante JCF). Se trata de un conjunto de clases e interfaces que mejoran notablemente las capacidades del lenguaje respecto a estructuras de datos. Además, constituyen un excelente ejemplo de aplicación de los conceptos propios de la programación orientada a objetos. Dada la amplitud de Java en éste y en otros aspectos se va a optar por insistir en la descripción general, dejando al lector la tarea de buscar las características concretas de los distintos métodos en la documentación de Java. En este apartado se va a utilizar una forma -más breve que las tablas utilizadas en otros apartados- de informar sobre los métodos disponibles en una clase o interface. La Figura 4.1 muestra la jerarquía de interfaces de la Java Collection Framework (JCF). En letra cursiva se indican las clases que implementan las correspondientes interfaces. Por ejemplo, hay dos clases que implementan la interface Map. HashMap y Hashtable. Las clases vistas en los apartados anteriores son clases "históricas", es decir, clases que existían antes de la versión JDK 1.2. Dichas clases se denotan en la Figura 4.1 con la letra "h" entre paréntesis. Aunque dichas clases se han mantenido por motivos de compatibilidad, sus métodos no siguen las reglas del diseño general del JCF: en la medida de lo posible se recomienda utilizar las nuevas clases.
En el diseño de la JCF las interfaces son muy importantes porque son ellas las que determinan las capacidades de las clases que las implementan. Dos clases que implementan la misma interface se pueden utilizar exactamente de la misma forma. Por ejemplo, las clases ArrayList y LinkedList disponen exactamente de los mismos métodos y se pueden utilizar de la misma forma. La diferencia está en la implementación: mientras que ArrayList almacena los objetos en un array, la clase LinkedList los almacena en una lista vinculada. La primera será más eficiente para acceder a un elemento arbitrario, mientras que la segunda será más flexible si se desea borrar e insertar elementos. 
La Figura 4.2 muestra la jerarquía de clases de la JCF. En este caso, la jerarquía de clases es menos importante desde el punto de vista del usuario que la jerarquía de interfaces. En dicha figura se muestran con fondo blanco las clases abstractas, y con fondo gris claro las clases de las que se pueden crear objetos.

domingo, 29 de diciembre de 2013

Clase Hashtable

La clase java.util.Hashtable extiende Dictionary (abstract) e implementa Cloueabley Serializable. Una hash table es una tabla que relaciona una clave con un valor. Cualquier objeto distinto de nuil puede ser tanto clave como valor. La clase a la que pertenecen las claves debe implementar los métodos hashCodef) y equalsf). con objeto de hacer búsquedas y comparaciones. 
El método hashCode() devuelve mi entero único y distinto para cada clave, que es siempre el mismo en una ejecución del programa pero que puede cambiar de una ejecución a otra. Además, para dos claves que resultan iguales según el método equalsf). el método 1iashCode() devuelve el mismo entero. Las hash tables están diseñadas para mantener una colección de pares clave/valor, permitiendo insertar y realizar búsquedas de un modo muy eficiente Cada objeto de Hashtable tiene dos variables: capacity y load factor (entre 0.0 y 1.0). Cuando el número de elementos excede el producto de estas variables, la Hashtable crece llamando al método rehashf). Un load factor más grande apura más la memoria, pero será menos eficiente en las búsquedas. Es conveniente partir de una Hashtable suficientemente grande para no estar ampliando continuamente

Hashtable números = new Hashtable ();
numbers.put("uno", new Integer(1));
numbers.put("dos", new Integer(2));
numbers.put("tres", new Integer(3));
donde se ha hecho uso del método putQ. La Tabla 4.7 muestra los métodos de la clase Hashtable.

sábado, 28 de diciembre de 2013

Clase Vector

La clase java.útil. Vector deriva de Object. implementa Cloneable (para poder sacar copias con el método cloneQ) y Serializable (para poder ser convertida en cadena de caracteres). Como su mismo nombre sugiere. Vector representa un array de objetos (referencias a objetos de tipo Object) que puede crecer y reducirse, según el número de elementos. 
Además permite acceder a los elementos con un índice, aunque no permite utilizar los corchetes []. El método capacity() devuelve el tamaño o número de elementos que puede tener el vector. El método size() devuelve el número de elementos que realmente contiene, mientras que capacitylncrement es una variable que indica el salto que se dará en el tamaño cuando se necesite crecer. La Tabla 4.6 muestra los métodos más importantes de la clase Vector. Puede verse que el gran número de métodos que existen proporciona una notable flexibilidad en la utilización de esta clase.
Además de capacitylncrement. existen otras dos variables miembro: elementCount. que representa el número de componentes válidos del vector, y elementData[] que es el array de Objects donde realmente se guardan los elementos del objeto Vector (capacity es el tamaño de este array). Las tres variables citadas son protected.

viernes, 27 de diciembre de 2013

Interface Enumeratiou

La interface java.utiLEnumeration define métodos útiles para recorrer una colección de objetos. Puede haber distintas clases que implementen esta interface y todas tendrán un comportamiento similar. La interface Enumeratiou declara dos métodos: 
  1. public boolean hasMoreElements(). Indica si hay más elementos en la colección o si se ha llegado ya al final. 
  2. public Object nextElement(). Devuelve el siguiente objeto de la colección. Lanza una NoSuchElementException si se llama y ya no hay más elementos. Ejemplo: Para imprimir los elementos de un vector vec se pueden utilizar las siguientes sentencias:

for (Enumeration e = vec.elements(); e.hasMoreElements(); ) {
System.out.println(e.nextElement());
}

donde, como puede verse en la Tabla 4.6. el método elementsQ devuelve precisamente una referencia de tipo Enumeratiou. Con los métodos hasMoreElements() y nextElement() y un bucle for se pueden ir imprimiendo los distintos elementos del objeto Vector.

COLECCIONES

Java dispone también de clases e interfaces para trabajar con colecciones de objetos. En primer lugar se verán las clases Vector y Hashtable. así como la interface Enumeration. Estas clases están presentes en lenguaje desde la primera versión. Después se explicará brevemente la Java Collections Framework, introducida en la versión JDK 1.2.

jueves, 26 de diciembre de 2013

CLASE MATH

La clase joro.latig.Maíh deriva de Object. La clase Math proporciona métodos static para realizar las operaciones matemáticas más habituales. Proporciona además las constantes E y PI. cuyo significado no requiere muchas explicaciones. La Tabla 4.5 muestra los métodos matemáticos soportados por esta clase.

miércoles, 25 de diciembre de 2013

Clase Integer

La clase java.lang.Integer tiene como variable miembro un valor de tipo int. La Tabla 4.4 muestra los métodos y constantes de la clase Integer.
Los Wrappers Byte, Short y Long son similares a Integer.
Los Wrappers son utilizados para convertir cadenas de caracteres (texto) en números. Esto es útil cuando se leen valores desde el teclado, desde un fichero de texto, etc. Los ejemplos siguientes muestran algunas conversiones:

String numDecimalString = "8.978";
float numFloat=Float.valueOf(numDecimalString).floatValue(); // numFloat = 8,979
double numDouble=Double.valueOf(numDecimalString).doubleValue();// numDouble = 3,979
String numlntString = "1001";
int numlnt=lnteger.valueOf(numlntString).intValué();  // numlnt = 1001

En el caso de que el texto no se pueda convertir directamente al tipo especificado se lanza una excepción de tipo NumberFormatException. por ejemplo si se intenta convertir dilectamente el texto "4.897*' a un número entero. El proceso que habrá que seguir será convertirlo en primer lugar a un número float y posteriormente a número entero.

martes, 24 de diciembre de 2013

Clase Double

La clase java.lang,Double deriva de Number, que a su vez deriva de Object. Esta clase contiene un valor primitivo de tipo double. La Tabla 4.3 muestra algunos métodos y constantes predefinidas de la clase Double.
El Wrapper Float es similar al Wrapper Double.

lunes, 23 de diciembre de 2013

WRAPPERS

Los Wrappers (envoltorios) son clases diseñadas para ser un complemento de los tipos primitivos. En efecto, los tipos primitivos son los únicos elementos de Java que no son objetos. Esto tiene algunas ventajas desde el punto de vista de la eficiencia. pero algunos inconvenientes desde el punto de vista de la funcionalidad. 
Por ejemplo, los tipos primitivos siempre se pasan como argumento a los métodos por valor. mientras que los objetos se pasan por referencia. No hay forma de modificar en un método un argumento de tipo primitivo y que esa modificación se trasmita al entorno que hizo la llamada. Una forma de conseguir esto es utilizar IUI Wrapper. esto es un objeto cuya variable miembro es el tipo primitivo que se quiere modificar. Las clases Wrapper también proporcionan métodos para realizar otras tareas con lo tipos primitivos, tales como conversión con cadenas de caracteres en uno y otro sentido. Existe una clase Wrapper para cada uno de los tipos primitivos numéricos, esto es. existen las clases Byte. Short. Inte ge r. Long. Float y Double (obsérvese que los nombres empiezan por mayúscula, siguiendo la nomenclatura típica de Java). A continuación se van a ver dos de estas clases: 
Double e Integer. Las otras cuatro son similares y sus características pueden consultarse en la documentación on-line. 4.3.1 Clase Double La clase java.lang.Double deriva de Number. que a su vez deriva de Object. Esta clase contiene un valor primitivo de tipo double. La Tabla 4.3 muestra algunos métodos y constantes predefinidas de la clase Double.

domingo, 22 de diciembre de 2013

Métodos de la clase StringBuffer

La clase StringBuffer se utiliza prácticamente siempre que se desee modificar una cadena de caracteres. Completa los métodos de la clase String ya que éstos realizan sólo operaciones sobre el texto que no conllevan un aumento o disminución del número de letras del String. Recuérdese que hay muchos métodos cuyos argumentos deben ser objetos String. que antes de pasar esos argumentos habrá que realizar la conversión correspondiente. La Tabla 4.2 muestra los métodos más importantes de la clase StringBuffer.

Métodos de la clase String

Los objetos de la clase String se pueden crear a partir de cadenas constantes o /iteráis. definidas entre dobles comillas, como por ejemplo: "Hola". Java crea siempre un objeto String al encontrar una cadena entre comillas. A continuación se describen dos formas de crear objetos de la clase String.

String strl = "Hola";    // el sistema más eficaz de crear Strings
String str2 = new String("Kola"); // tarabién se pueden crear con un constructor


El primero de los métodos expuestos es el más eficiente, porque como al encontrar un texto entre comillas se crea automáticamente un objeto String. en la práctica utilizando new se llama al constructor dos veces. También se pueden crear objetos de la clase String llamando a otros constructores de la clase, a partir de objetos StringBuffer. y de arrays de bytes o de chars. La Tabla 4.1 muestra los métodos más importantes de la clase String.
Un punto importante a tener en cuenta es que hay métodos, tales como System,out.println(), que exigen que su argumento sea un objeto de la clase String. Si no lo es. habrá que utilizar algún método que| lo convierta en String. El lócale, citado en la Tabla 4.1. es la forma que java tiene para adaptarse a las peculiaridades de los idiomas distintos del inglés: acentos, caracteres especiales, forma de escribir las fechas y las horas, unidades monetarias, etc.

viernes, 20 de diciembre de 2013

CLASES STRING Y STRINGBUFFER

Las clases String y StringBuffer están orientadas a manejar cadenas de caracteres. La clase String está orientada a manejar cadenas de caracteres constantes, es decir, que no pueden cambiar. La clase StringBuffer pennite que el programador cambie la cadena insertando, borrando, etc. 
La primera es más eficiente, mientras que la segunda permite más posibilidades. Ambas clases pertenecen al package jara.long. y por lo tanto no hay que importarlas. 
Hay que indicar que el operador de concatenación (+) entre objetos de tipo String utiliza internamente objetos de la clase StringBuffer y el método appendf). Los métodos de String se pueden utilizar directamente sobre literals (cadenas entre comillas), como por ejemplo: "Hola".lengthQ.

jueves, 19 de diciembre de 2013

Arrays tridimensionales

Los arrays bidimensionales de Java se crean de un modo muy similar al de C++ (con reserva dinámica de memoria). En Java una matriz es un vector de vectores fila, o más en concreto un vector de referencias a los vectores fila. Con este esquema, cada fila podría tener un número de elementos diferente. Una matriz se puede crear directamente en la forma,

int [] [] niat = new int[3][4];
o bien se puede crear de modo dinámico dando los siguientes pasos:
1.    Crear la referencia indicando con un doble corchete que es una referencia a matriz,
int[][] mat;
2.    Crear el vector de referencias a las filas.
mat = new int[nfilas][];
3.    Reservar memoria para los vectores correspondientes a las filas.
for (int i=0; icnfilas; i++);
mat [i] = new int[ncols];
A continuación se presentan algunos ejemplos de creación de arrays tridimensionales:
// crear una matriz 3x3
//       se inicializan a cero
double mat[][] = new double[3][3];
int [] [] b = {{1, 2, 3},
{4, 5, 6}, // esta coma es permitida
};
int c = new[3][]; // se crea el array de referencias a arrays
c[0] = new int[5];
c [ 1] = new int[4];
c[2] = new int[8];

En el caso de una matriz b. b.length es el número de filas y b[0].length es el número de columnas (de la fila 0). Por supuesto, los arrays bidimensionales pueden contener tipos primitivos de cualquier tipo u objetos de cualquier clase.

miércoles, 18 de diciembre de 2013

ARRAYS - II

Inicialización de arrays: 
1. Los arrays se pueden inicializar con valores entre llaves {...} separados por comas. 
2. También los arrays de objetos se pueden inicializar con varias llamadas a new dentro unas llaves {...}. 
3. Si se igualan dos referencias a un array no se copia el array, sino que se tiene un array dos nombres, apuntando al mismo y único objeto. 
4. Creación de una referencia a un array. Son posibles dos formas:

double[] x; // preferible
double x[];

5. Creación del array con el operador new.
x = new double[100];
6. Las dos etapas 4 y 5 se pueden unir en una sola:
double[] x = new double[100];
A continuación se presentan algunos ejemplos de creación de arrays:
// crear un array de 10 enteros, que por defecto se inicializan a cero
int v[] = new int[10];
// crear arrays inicializando con determinados valores
int v[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
String dias[] = {"lunes", "martes", "miercoles", "jueves",
"viernes", "sabado", "domingo"};
// array de 5 objetos
MiClase listaObj[] = new MiClase[5]; // de momento hay 5 referencias a nuil
for( i = 0 ; i < 5;i++)
ÜstaObj [i] = new MiClase (...);
// array anónimo
obj.método(new String[]={"uno", "dos"tres"});

martes, 17 de diciembre de 2013

ARRAYS - I

Los arrays de Java (vectores, matrices, hiper-matrices de más de dos dimensiones) se tratan como objetos de una clase predefinida. Los arrays son objetos, pero con algunas características propias. Los arrays pueden ser asignados a objetos de la clase Object y los métodos de Object pueden ser utilizados con arrays. Algunas de sus características más importantes de los arrays son las siguientes: 
  1. Los arrays se crean con el operador new seguido del tipo y número de elementos. 
  2. Se puede acceder al número de elementos de un array con la variable miembro implícita length (por ejemplo, vect.length). 
  3. Se accede a los elementos de un array con los corchetes [] y un índice que varía de 0 a length-1. 
  4. Se pueden crear arrays de objetos de cualquier tipo. En principio un array de objetos es un array de referencias que hay que completar llamando al operador new. 
  5. Los elementos de un array se inicializan al valor por defecto del tipo correspondiente (cero para valores numéricos, el carácter nulo para char. false para boolean. nuil para Strings y para referencias). 
  6. Como todos los objetos, los arrays se pasan como argumentos a los métodos por referencia. 
  7. Se pueden crear arrays anónimos (por ejemplo, crear un nuevo array como argumento actual en la llamada a un método).

domingo, 15 de diciembre de 2013

CLASES DE UTILIDAD

Programando en Java nunca se paite de cero: siempre se paite de la infraestructura definida por el API de Java, cuyos packages proporcionan una buena base para que el programador construya sus aplicaciones. En este Capítulo se describen algunas clases que serán de utilidad para muchos programadores.

sábado, 14 de diciembre de 2013

POLIMORFISMO - II

Conversión de objetos 

El polimorfismo visto previamente está basado en utilizar referencias de un tipo más "amplio"' que los objetos a los que apuntan. Las ventajas del polimorfismo son evidentes, pero hay una importante limitación: el tipo de la referencia (clase abstracta, clase base o interface) limita los métodos que se pueden utilizar y las variables miembro a las que se pueden acceder. Por ejemplo, un objeto puede tener una referencia cuyo tipo sea una interface. aunque sólo en el caso en que su clase o una de sus super-clases implemente dicha interface. Un objeto cuya referencia es un tipo interface sólo puede utilizar los métodos definidos en dicha interface. Dicho de otro modo, ese objeto no puede utilizar las variables y los métodos propios de su clase. 
De esta forma las referencias de tipo interface definen, limitan y unifican la fonna de utilizarse de objetos pertenecientes a clases muy distintas (que implementan dicha interface). Si se desea utilizar todos los métodos y acceder a todas las variables que la clase de un objeto permite, hay que utilizar un cast explícito. que convierta su referencia más general en la del tipo específico del objeto. De aquí una parte importante del interés del cast entre objetos (más bien entre referencias, habría que decir). 
Para la conversión entre objetos de distintas clases. Java exige que dichas clases estén relacionadas por herencia (una deberá ser sub-clase de la otra). Se realiza una conversión implícita o automática de una sub-clase a una super-clase siempre que se necesite, ya que el objeto de la sub-clase siempre tiene toda la información necesaria para ser utilizado en lugar de un objeto de la super-clase. No importa que la super-clase no sea capaz de contener toda la información de la sub- clase. La conversión en sentido contrario -utilizar luí objeto de una super-clase donde se espera encontrar uno de la sub-clase- debe hacerse de modo explícito y puede producir errores por falta de información o de métodos. Si falta información, se obtiene una ClassCastException.No se puede acceder a las variables exclusivas de la sub-clase a través de una referencia de la super-clase. Sólo se pueden utilizar los métodos definidos en la super-clase, aunque la definición utilizada para dichos métodos sea la de la sub-clase. 
Por ejemplo, supóngase que se crea un objeto de una sub-clase B y se referencia con un nombre de una super-clase A.
A a = new B() ;
en este caso el objeto creado dispone de más información de la que la referencia a le permite acceder (podría ser. por ejemplo, una nueva variable miembro j declarada en B). Para acceder a esta información adicional hay que hacer un cast explícito en la forma (B)a. Para imprimir esa variable j habría que escribir (los paréntesis son necesarios):
System.out.println( ((B)a).j );

Un cast de un objeto a la super-clase puede permitir utilizar variables -no métodos- de la super-clase. aunque estén redefinidos en la sub-clase. Considérese el siguiente ejemplo: La clase C deriva de B y B deriva de A. Las tres definen una variable x. En este caso, si desde el código de la sub-clase C se utiliza:

x            //se accede a la x de C
this.x       // se accede a la x de C
super.x      // se accede a la x de B. Sólo se puede subir un nivel
((B)this).x  // se accede a la x de B
((A)this).x  // se accede a la x de A

jueves, 12 de diciembre de 2013

POLIMORFISMO - I

Ya se vio en el ejemplo presentado en el Apartado 1.3.8 y en los comentarios incluidos en qué consistía el polimorfismo. El polimorfismo tiene que ver con la relación que se establece entre la llamada a un método y el código que efectivamente se asocia con dicha llamada. 
A esta relación se llama vinculación (binding). La vinculación puede ser temprana (en tiempo de compilación) o tardía (en tiempo de ejecución). Con funciones normales o sobrecargadas se utiliza vinculación temprana (es posible y es lo más eficiente). Con funciones redefinidas en Java se utiliza siempre vinculación tardía. excepto si el método es final. El polimorfismo es la opción por defecto en Java. 
La vinculación tardía hace posible que. con un método declarado en una clase base (o en una interface) y redefinido en las clases derivadas (o en clases que implementan esa interface), sea el tipo de objeto y no el tipo de la referencia lo que determine qué definición del método se va a utilizar. 
El tipo del objeto al que apunta una referencia sólo puede conocerse en tiempo de ejecución, y por eso el polimorfismo necesita evaluación tardía. 
El polimorfismo permite a los programadores separar las cosas que cambian de las que no cambian, y de esta manera hacer más fácil la ampliación, el mantenimiento y la reutilización de los programas. 
El polimorfismo puede hacerse con referencias de super-clases abstraer, super-clases normales e interfaces. Por su mayor flexibilidad y por su independencia de la jerarquía de clases estándar, las interfaces permiten ampliar muchísimo las posibilidades del polimorfismo.

miércoles, 11 de diciembre de 2013

Conversión de tipos primitivos

La conversión entre tipos primitivos es más sencilla. En Java se realizan de modo automático conversiones implícitas de un tipo a otro de más precisión. por ejemplo de int a long. de float a double. etc. Estas conversiones se hacen al mezclar variables de distintos tipos en expresiones matemáticas o al ejecutar sentencias de asignación en las que el miembro izquierdo tiene mi tipo distinto (más amplio) que el resultado de evaluar el miembro derecho. 
Las conversiones de mi tipo de mayor a otro de menor precisión requieren una orden explícita del programador, pues son conversiones inseguras que pueden dar lugar a errores (por ejemplo, para pasar a short un número almacenado como int. hay que estar seguro de que puede ser representado con el número de cifras binarias de short). A estas conversiones explícitas de tipo se les llama cast. El cast se hace poniendo el tipo al que se desea transformar entre paréntesis, como por ejemplo.

long result;
result = (long) (a/(b+c));


A diferencia de C/C++, en Java no se puede convertir un tipo numérico a boolean. La conversión de Strings (texto) a números se verá en el Apartado 4.3. en la página 69.

martes, 10 de diciembre de 2013

TRANSFORMACIONES DE TIPO: CASTING

En muchas ocasiones hay que transformar una variable de un tipo a otro, por ejemplo de int a double. o de float a long. En otras ocasiones la conversión debe hacerse entre objetos de clases diferentes, aunque relacionadas mediante la herencia. En este apartado se explican brevemente estas transformaciones de tipo.

lunes, 9 de diciembre de 2013

PERMISOS DE ACCESO EN JAVA - II

Accesibilidad de las variables y métodos miembros de una clase: 

Desde dentro de la propia clase: 
1. Todos los miembros de una clase son directamente accesibles (sin cualificar con ningún nombre o cualificando con la referencia this) desde dentro de la propia clase. Los métodos no necesitan que las variables miembro sean pasadas como argumento. 
2. Los miembros prívate de una clase sólo son accesibles para la propia clase. 
3. Si el constructor de una clase es prívate. sólo mi método static de la propia clase puede crear objetos. 

Desde una sub-clase: 

1. Las sub-clases heredan los miembros prívate de su super-clase. pero sólo pueden acceder a ellos a través de métodos public. protected o package de la super-clase. 

Desde otras clases del package: 

1. Desde una clase de un package se tiene acceso a todos los miembros que no sean prívate de las demás clases del package. 

Desde otras clases fuera del package: 

1. Los métodos y variables son accesibles si la clase es public y el miembro es public. 
2. También son accesibles si la clase que accede es una sub-clase y el miembro es protected. La Tabla 3.1 muestra un resumen de los permisos de acceso en Java.

domingo, 8 de diciembre de 2013

PERMISOS DE ACCESO EN JAVA - I

Una de las características de la Programación Orientada a Objetos es la encapsulación. que consiste básicamente en ocultar la información que no es pertinente o necesaria para realizar una determinada tarea. Los permisos de acceso de Java son una de las herramientas para conseguir esta finalidad. 

Accesibilidad de los packages 

El primer tipo de accesibilidad hace referencia a la conexión física de los ordenadores y a los permisos de acceso entre ellos y en sus directorios y ficheros. En este sentido, un package es accesible si sus directorios y ficheros son accesibles (si están en un ordenador accesible y se tiene permiso de lectura). Además de la propia conexión física, serán accesibles aquellos packages que se encuentren en la variable CLASSPATH del sistema. 

Accesibilidad (le clases o interfaces 

En principio, cualquier clase o interface de mi pac ka ge es accesible para todas las demás clases del package. tanto si es public como si no lo es. Una clase public es accesible para cualquier otra clase siempre que su package sea accesible. Recuérdese que las clases e interfaces sólo pueden ser public o package (la opción por defecto cuando no se pone ningún modificador).

sábado, 7 de diciembre de 2013

Clases anónimas - II

Para las clases anónimas compiladas el compilador produce ficheros con 1111 nombre del tipo ClaseContenedoraSl.class. asignando un número correlativo a cada una de las clases anónimas. Conviene ser muy cuidadoso respecto a los aspectos tipográficos de la definición de clases anónimas, pues al 110 tener nombre dichas clases suelen resultar difíciles de leer e interpretar. Se aconseja utilizar las siguientes normas tipográficas. 
  1. Se aconseja que la palabra new esté en la misma línea que el resto de la expresión. 
  2. Las llaves se abren en la misma línea que new. después del cieñe del paréntesis de los argumentos del constructor. 
  3. El cuerpo de la clase anónima se debe sangrar o indentar respecto a las líneas anteriores de código para que resulte claramente distinguible. 
  4. El cierre de las llaves va seguido por el resto de la expresión en la que se ha definido la clase anónima. Esto puede servir como indicación tipográfica del cieñe. Puede ser algo así como }; o }); A continuación se presenta un ejemplo de definición de clase anónima en relación con el AWT:

unObjeto.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent e) {
> 
)) ;

donde en negrita se señala la clase anónima, que deriva de Object e implementa la interface ActionListener. 
Las clases anónimas se utilizan en lugar de clases locales para clases con muy poco código, de las que sólo hace falta un objeto. No pueden tener constructores, pero sí inicializaclores static o de objeto. Además de las restricciones citadas, tienen restricciones similares a las clases locales.

viernes, 6 de diciembre de 2013

Clases anónimas - I

Las clases anónimas son muy similares a las clases internas locales, pero sin nombre. En las clases internas locales primero se define la clase y luego se crean uno o más objetos. En las clases anónimas se unen estos dos pasos: 
Como la clase 110 tiene nombre sólo se puede crear un único objeto, ya que las clases anónimas no pueden definir constructores. Las clases anónimas se utilizan con mucha frecuencia en el AWT para definir clases y objetos que gestionen los eventos de los distintos componentes de la interface de usuario. No hay interfaces anónimas. 
Formas de definir una clase anónima. 
  1. Las clases anónimas requieren una extensión de la palabra clave new. Se definen en una expresión de Java, incluida en una asignación o en la llamada a un método. Se incluye la palabra new seguida de la definición de la clase anónima, entre llaves {...}. 
  2. Otra forma de definirlas es mediante la palabra new seguida del nombre de la clase de la que hereda (sin extends) y la definición de la clase anónima entre llaves {...}. El nombre de la super-clase puede ir seguido de argumentos para su constructor (entre paréntesis, que con mucha frecuencia estarán vacíos pues se utilizará un constructor por defecto). 
  3. Una tercera forma de definirlas es con la palabra new seguida del nombre de la interface que implementa (sin implements) y la definición de la clase anónima entre llaves {...}. En este caso la clase anónima deriva de Object. El nombre de la interface va seguido por paréntesis vacíos, pues el constructor de Object no tiene argumentos.

jueves, 5 de diciembre de 2013

Clases internas locales - II

Restricciones en el uso de las clases internas locales: 
  1. No pueden tener el mismo nombre que ninguna de sus clases contenedoras. 
  2. No pueden definir variables, métodos y clases static. 
  3. No pueden ser declaradas public, protected. prívate o package. pues su visibilidad es siempre la de las variables locales, es decir, la del bloque en que han sido definidas.
Las clases internas locales se utilizan para definir clases Adapter en el AWT. A continuación se presenta un ejemplo de definición de clases internas locales:

// fichero ClasesIntLocales.java
// Este fichero demuestra cómo se crean clases locales
class A {
int i=-l; // variable miembro
// constructor
public A(int i) {this.i=i;}
// definición de un método de la clase A
public void getAi(final long k) { // argumento final
final double f=3.14;          // variable local final
// definición de una clase interna local
class BL {
int j=2;
public BL(int j) {this.j=j;} // constructor
public void printBLO {
System.out.println(" j="+j+" i="+i+" f="+f+" k="+k);
}
} // fin clase BL
// se crea un objeto de BL
BL bl = new BL(2*i);
// se imprimen los datos de ese objeto
bl.printBLO ;
} // fin getAi

} // fin clase contenedora A

class ClasesIntLocales {
public static void main(String [] arg) {
// se crea dos objetos de la clase contenedora
A al = new A(-10);
A a2 = new A(-ll);
// se llama al método getAi()
al.getAi(1000); // se crea y accede a un objeto de la clase local
a2.getAi(2000);
} // fin de main()
public static void println(String str) {System.out.println(str);}
} // fin clase ClasesIntLocales

miércoles, 4 de diciembre de 2013

Clases internas locales - I

Las clases internas locales o simplemente clases locales no se declaran dentro de otra clase al máximo nivel, sino dentro de un bloque de código. normalmente en un método. aunque también se pueden crear en un inicializador static o de objeto. Las principales características de las clases locales so las siguientes: 
  1.  Como las variables locales. las clases locales sólo son visibles y utilizables en el bloque de código en el que están definidas. Los objetos de la clase local deben ser creados en el mismo bloque en que dicha clase ha sido definida. De esta forma se puede acercar la definición al uso de la clase. 
  2. Las clases internas locales tienen acceso a todas las variables miembro y métodos de la clase contenedora. Pueden ver también los miembros heredados. tanto por la clase interna local como por la clase contenedora. 
  3. Las clases locales pueden utilizar las variables locales y argumentos de métodos risibles en ese bloque de código. pero sólo si son final* (en realidad la clase local trabaja con sus copias de las variables locales y por eso se exige que sean final y no puedan cambiar). 
  4. Un objeto de una clase interna local sólo puede existir en relación con mi objeto de la clase contenedora. que debe existir previamente. 
  5. La palabra this se puede utilizar en la misma forma que en las clases internas miembro, pero no las palabras new y super

martes, 3 de diciembre de 2013

Clases internas miembro (no static) - III

Las clases internas pueden derivar de otras clases diferentes de la clase contenedora. E11 este caso, conviene tener en cuenta las siguientes reglas:
  1. Las clases internas constituyen como una segunda jerarquía de clases en Java , por una parte están en la clases contenedora y ven sus variables: por otra pane pueden derivar de otra clase que 110 tenga nada que ver con la clase contenedora. Es muy importante evitar conflictos con los nombres. En caso de conflicto entre un nombre heredado y un nombre en la clase contenedora, el nombre heredado debe tener prioridad. 
  2. En caso de conflicto de nombres. Java obliga a utilizar la referencia this con un nuevo significado: para referirse a la variable o método miembro heredado se utiliza this.name, mientras que se utiliza NombreClaseCont.this.name para el miembro de la clase contenedora.. 
  3. Si una clase contenedora deriva de una super-clase que tiene una clase interna, la clase interna de la sub-clase puede a su vez derivar de la clase interna de la super-clase y reclefmir todos los métodos que necesite. La casuística se puede complicar todo lo que se desee, pero siempre hay que recomendar hacer las cosas lo más sencillas que sea posible.
El uso de las clases internas miembro tiene las siguientes restricciones: 
  1. Las clases internas no pueden tener el mismo nombre que la clase contenedora o package. 
  2. Tampoco pueden tener miembros static: variables, métodos o clases. 
A continuación se presenta un ejemplo completo de utilización de clases internas miembro:

// fichero Claseslnternas.java
// clase contenedora
class A {
int i=l;                 // variable miembro
public A(int i) {this.i=i;} // constructor
// los métoodos de la clase contenedora necesitan una
//      referencia a los objetos de la clase interna
public void printA (B unB) {
System.out.println("i="+i+" unB.j="+unB.j); // si acepta unB.j
> 
// la clase interna puede tener cualquier visibilidad. Con private da error
//      porque main() no puede acceder a la clase interna
protected class B {
int j=2;
public B(int j) {this.j=j;} // constructor
public void printB() {
System.out.println("1=" + i + " j=" + j); // si sabe qué es j
> 
} // fin clase B
} // fin clase contenedora A
class Claseslnternas {
public static void main(String [] arg) {
A al = new A(ll); A a2 = new A(12);
println("al.i=" + al.i + " a2.i=" + a2.i);
// forma de crear objetos de la clase interna
//         asociados a un objeto de la clase contenedora
A.B bl = al.new Bf-lO), ¿2 = al.new B(-20);
// referencia directa a los objetos bl y b2 (sin cualificar).
println("bl.j=" + bl.j + " b2.j=" + b2.j);
// los métodos de la clase interna pueden acceder directamente a
// las variables miembro del objeto de la clase contenedora
bl.printB(); // escribe: i=ll j=-10
b2.printB(); // escribe: i=ll j=-20
// los métodos de la clase contenedora deben recibir referencias
//         a los objetos de la clase interna, pera que puedan identificarlos
al.printA(bl); al.printA(b2);
A a3 = new A(13);
A.B b3 = a3.new B(-30);
println("b3.j=" + b3.j);
a3 - nuil; // se destruye la referencia al objeto de la clase contenedora
b3.printB(); // escribe: i=13 j=-30
a3 = new A(14); // se crea un nuevo objeto asociado a la referencia a3
// b3 sigue asociado an anterior objeto de la clase contenedora
b3.printB(); // escribe: i=13 j=-30
} // fin de main()
public static void println(String str) {System.out.println(str);}
} // fin clase Claseslnternas

lunes, 2 de diciembre de 2013

Clases internas miembro (no static) - II

Otras características de las clases internas son las siguientes: 
  1. Una clase interna miembro puede contener otra clase interna miembro, hasta el nivel que se desee (aunque no se considera buena técnica de programación utilizar muchos niveles). 
  2. En la clase interna, la palabra this se refiere al objeto de la propia clase interna. Para acceder al objeto de la clase contenedora se utiliza ClaseContenedora.tlíis. 
  3. Para crear un nuevo objeto de la clase interna se puede utilizar new. precedido por la refe- rencia al objeto de la dase contenedora que contendía el nuevo objeto: unObjCC.newQ. El tipo del objeto es el nombre de la clase contenedora seguido del nombre de la clase interna, como por ejemplo:

ClaseCont.Claselnt unObjClInt = unObjClaCont.new Claselnt (...);

4. Supóngase como ejemplo adicional que B es una clase interna de A y que C es una clase interna de B. La creación de objetos de las tres clases se puede hacer del siguiente modo:

A a = new A();        // se crea un objeto de la clase A
A.B b = a.new B();    // b es un objeto de la clase interna B dentro de a
A.B.C c = b.new C(); // c es un objeto de la clase interna C dentro de b

5. Nunca se puede crear un objeto de la clase interna sin una referencia a un objeto de la clase contenedora. Los constructores de la clase interna tienen como argumento oculto una referencia al objeto de la clase contenedora. 
6. El nuevo significado de la palabra super es un poco complicado: Si una clase deriva de una clase interna, su constructor 110 puede llamar a super() directamente. Ello hace que el compilador 110 pueda crear 1111 constructor por defecto. Al constructor hay que pasarle una referencia a la dase contenedora de la clase interna super-clase, y con esa referencia ref llamar a ref super ().

domingo, 1 de diciembre de 2013

Clases internas miembro (no static) - I

Las clases internas miembro o simplemente clases internas, son clases definidas al máximo nivel de la clase contenedora (directamente en el bloque de diminución de dicha clase), sin la palabra static. Se suelen llamar clases internas miembro o simplemente clases internas. 
No existen interfaces internas de este tipo. Las clases internas 110 pueden tener variables miembro static. Tienen una nueva sintaxis para las palabras this. new y super. que se verá 1111 poco más adelante. 
La característica principal de estas clases internas e que cada objeto de la clase interna existe siempre dentro de 1111 y sólo un objeto de la clase contenedora. Un objeto de la clase contenedora puede estar relacionado con uno o más objetos de la clase interna. Tener esto presente es muy importante para entender las características que se explican a continuación. Relación entre las clases interna y contenedora respecto al acceso a las variables miembro. 
  1. Debido a la relación uno a uno. los métodos de la clase interna ven dilectamente las variables miembro del objeto de la clase contenedora, sin necesidad de cualificarlos. 
  2. Sin embargo, los métodos de la clase contenedora no ven directamente las variables miembro de los objetos de la clase interna: necesitan cualificarlos con una referencia a los correspondientes objetos. Esto es consecuencia de la relación uno a varios que existe entre los objetos de la clase contenedora y los de la clase interna. 
  3. Otras clases diferentes de las clases contenedora e interna pueden utilizar directamente los objetos de la clase interna, sin cualificarlos con el objeto o el nombre de la clase contenedora. De hecho, se puede seguir accediendo a los objetos de la clase interna aunque se pierda la referencia al objeto de la clase contenedora con el que están asociados.
Respecto a los permisos de acceso:

  1. Las clases internas pueden también ser prívate y protected (las clases normales sólo pueden ser public y package). Esto permite nuevas posibilidades de encapsulación. 
  2. Los métodos de las clases internas acceden directamente a todos los miembros, incluso prívate, de la clase contenedora. 
  3. También la clase contenedora puede acceder -si dispone de una referencia- a todas las variables miembro (incluso prívate) de sus clases internas. 4. Una dase interna puede acceder también a los miembros (incluso prívate) de otras clases internas definidas en la misma clase contenedora.

sábado, 30 de noviembre de 2013

Clases e interfaces internas static

Se conocen también con el nombre de clases anidadas {nested class es). Las clases e interfaces internas static sólo pueden ser creadas dentro de otra clase al máximo nivel. es decir directamente en el bloque de definición de la clase contenedora y 110 en un bloque más interno. Es posible definir clases e interfaces internas static dentro de una interface contenedora. 
Este tipo de clases internas se definen utilizando la palabra static. Todas las interfaces internas son implícitamente static. E11 cierta forma, las clases internas static se comportan como clases normales en un package. Para utilizar su nombre desde fuera de la clase contenedora hay que precederlo por el nombre de la clase contenedora y el operador punto (.) 
Este tipo de relación entre clases se puede utilizar para agrupar varías clases dentro de una clase más general. Lo mismo puede decirse de las interfaces internas. Las clases internas static pueden ver y utilizar los miembros static de la clase contenedora. No se necesitan objetos de la clase contenedora para crear objetos de la dase interna static. 
Los métodos de la clase interna static 110 pueden acceder dilectamente a los objetos de la clase contenedora, caso de que los haya: deben disponer de una referencia a dichos objetos, como cualquier otra clase. La sentencia import puede utilizarse para importar una dase interna static. en la misma forma que si se tratara de importar una clase de un package (con el punto (.)). Por ejemplo, si la interface Linkable es interna a la clase List, para implementar dicha interface hay que escribir,

... implements List.Linkable
y para importarla hay que usar,
import List.*; // o bien
import List.Linkable;

Otras características importantes son las siguientes: 
1. Pueden definirse clases e interfaces internas dentro de interface y clases contenedoras, con las cuatro combinaciones posibles. 
2. Puede haber varios niveles. esto es una clase interna static puede ser clase contenedora de otra clase interna static. y así sucesivamente. 
3. Las clases e interfaces internas static pertenecen al package de la clase contenedora. 
4. Pueden utilizarse los calificadores final, public. prívate y protected. Esta es una forma más de controlar el acceso a ciertas clases. A continuación se presenta un ejemplo de clase interna static:

// fichero ClasesIntStatic.java
class A {
int i=l;              // variable miembro de objeto
static int is=-l; // variable miembro de clase
public A(int i) {this.i=i;} // constructor
// a los métodos de la clase contenedora hay que pasarles referencias
//          a los objetos de la clase interna static
public void printA(Bs unBs) {
System, out.println("i=,,+i+,, unBs. j="+unBs . j) ;
> 
// definición de una clase interna static
static class Bs {
int j=2;
public Bs(int j) {this.j=j;} // constructor
// los métodos de la clase interna static no pueden acceder a la i
//         pues es una variable de objeto.
Si pueden acceder a is
public void printBs() {
System.out.println(" j=" + j + " is=" + is) ;
> 
} // fin clase Bs
} // fin clase contenedora A
class ClasesIntStatic {
public static void main(String [] arg) {
A al = new A(ll), a2 = new A(12);
println("al.i=" + al.i + " a2.i=" + a2.i);
// dos formas de crear objetos de la clase interna static
A.Bs bl = new A.Bs(-lO); // necesario poner A.Bs
A.Bs b2 = al.new Bs(-ll); // b2 es independiente de al
// referencia directa a los objetos bl y b2
println("bl.j =" + bl.j + " b2.j=" + b2.j);
// los métodos de la clase interna acceden directamente a las variables
//         de la clase contenedora sólo si son static
bl.printBs(); // escribe: j=-10 is=-l
b2.printBs(); // escribe: j=-20 is=-l
// a los métodos de la clase contenedora hay que pasarles referencias
//         a los objetos de la clase interna, pera que puedan identificarlos
al.printA(bl); // escribe: i=ll unBs.j=-10
al.printA(b2); // escribe: i=ll unBs.j=-ll
} // fin de main()
public static void println(String str) {System.out.println(str);}
} // fin clase ClasesIntStatic

viernes, 29 de noviembre de 2013

Utilización de interfaces

Una clase interna es una clase definida dentro de otra clase, llamada clase contenedora, en alguna variante de la siguiente forma general:.

class ClaseContenedora {
class Claselnternja {
}
}

Las clases internas fueron introducidas en la versión Java 1.1. Además de su utilidad en sí. las clases internas se utilizan mucho en el nuevo modelo de eventos que se introdujo en dicha versión de Java. Hay cuatro tipos de clases internas: 
1. Clases internas static. 
2. Clases internas miembro.
3. Clases internas locales. 
4. Clases anónimas. 
En lo sucesivo se utilizará la terminología clase contenedora o clase global para hacer referencia a la clase que contiene a la clase interna. 
Hay que señalar que la JVM (Java Virtual Machine) no sabe nada de la existencia de clases internas. Por ello, el compilador convierte estas clases en clases globales. contenidas en ficheros *.class cuyo nombre es ClaseContenedoraSClaselnterna.class. Esta conversión inserta variables ocultas, métodos y argumentos en los constructores. De todas formas, lo que más afecta al programador de todo esto es lo referente al nombre de los ficheros que aparecen en el directorio donde se realiza la compilación, que pueden resultar sorprendentes si no se conoce su origen.

Utilización de interfaces

Las constantes definidas en una interface se pueden utilizar en cualquier clase (aunque no implemente la interface) precediéndolas del nombre de la interface. como por ejemplo (suponiendo que PI hubiera sido definida en Dibujable):

area = 2.0*Dibujable.PI*r;


Sin embargo, en las clases que implementan la interface las constantes se pueden utilizar directamente, como si fueran constantes de la clase. A veces se crean interfaces para agrupar constantes simbólicas relacionadas (en este sentido pueden en parte suplir las variables enuin de C/C++). 
De cara al polimorfismo, el nombre de una interface se puede utilizar como un nuevo tipo de referencia. En este sentido, el nombre de una interface puede ser utilizado en lugar del nombre de cualquier clase que la implemente. aunque su uso estará restringido a los métodos de la interface. Un objeto de ese tipo puede también ser utilizado como valor de retomo o como argumento de un método.

jueves, 28 de noviembre de 2013

Herencia en interfaces

Entre las interfaces existe una jerarquía (independiente de la de las clases) que permite herencia simple y múltiple. Cuando una interface deriva de otra, incluye todas sus constantes y declaraciones de métodos. Una interface puede derivar de varias interfaces. 
Para la herencia de interfaces se utiliza asimismo la palabra extends. seguida por el nombre de las interfaces de las que deriva, separadas por comas. 
Una interface puede ocultar una constante definida en una super-interface definiendo otra constante con el mismo nombre. De la misma forma puede ocultar, re-declarándolo de nuevo, la declaración de un método heredado de una super-interface.
Las interfaces 110 deberían ser modificadas más que en caso de extrema necesidad. Si se modifican, por ejemplo añadiendo alguna nueva declaración de un método, las clases que hayan implementado dicha interface dejarán de funcionar, a menos que implementen el nuevo método.

Definición de interfaces

Una interface se define de un modo muy similar a las clases. A modo de ejemplo se reproduce aquí la definición de la interface Dibujable dada en el Apartado

// fichero Dibujable.java
import java.awt.Graphics;
public interface Dibujable {
public void setPosicion(double x, double y);
public void dibujar(Graphics dw) ;
}

Cada interface public debe ser definida en un fichero *.java con el mismo nombre de la interface. Los nombres de las interfaces suelen comenzar también con mayúscula. Las interfaces no admiten más que los modificadores de acceso public y package. Si la interface no es public no será accesible desde fuera del package (tendrá la accesibilidad por defecto, que es package). Los métodos declarados en una interface son siempre public y abstract. de modo implícito.

miércoles, 27 de noviembre de 2013

INTERFACES

Concepto de interface 

Una interface es un conjunto de declaraciones de métodos (sin definición). También puede definir constantes, que son implícitamente public. static y final, y deben siempre inicializarse en la declaración. Estos métodos definen un tipo de conducta. Todas las clases que implementan una determinada interface están obligadas a proporcionar una definición de los métodos de la interface. y en ese sentido adquieren una conducta o modo de funcionamiento. 
Una clase puede implementar una o varias interfaces. Para indicar que una clase implementa una o más interfaces se ponen los nombres de las interfaces. separados por comas, detrás de la palabra implements, que a su vez va siempre a la derecha del nombre de la clase o del nombre de la super-clase en el caso de herencia. Por ejemplo.
public class CirculoGrafico extends Circulo
implements Dibujable, Cloneable {
}

¿Qué diferencia hay entre una interface y una clase abstract? Ambas tienen en común que pueden contener varias declaraciones de métodos (la clase abstract puede además definirlos). A pesar de esta semejanza, que hace que en algunas ocasiones se pueda sustituir una por otra, existen también algunas diferencias importantes: 
  1. Una clase no puede heredar de dos clases abstract. pero sí puede heredar de una clase abstract e implementar una interface. o bien implementar dos o más interfaces. 
  2. Una clase 110 puede heredar métodos -definidos- de una interface. aunque sí constantes. 
  3. Las interfaces permiten mucha más flexibilidad para conseguir que dos clases tengan el mismo comportamiento, inpendientemente de su situación en la jerarquía de clases de Java. 
  4. Las interfaces permiten "publicar" el comportamiento de una clase desvelando un mínimo de información. 
  5. Las interfaces tienen una jerarquía propia, independiente y más flexible que la de las clases, ya que tienen permitida la herencia múltiple. 
  6. De cara al polimorfismo (recordar el Apartado 1.3.8, a partir de la página 15). las referencias de un tipo interface se pueden utilizar de modo similar a las clases abstract.

martes, 26 de noviembre de 2013

CLASES Y MÉTODOS FINALES

Recuérdese que las variables declaradas como final 110 pueden cambiar su valor una vez que han sido inicializadas. En este apartado se van a presentar otros dos usos de la palabra final. Una clase declarada final 110 puede tener clases derivadas. Esto se puede hacer por motivos de seguridad y también por motivos de eficiencia, porque cuando el compilador sabe que los métodos 110 van a ser redefinidos puede hacer optimizaciones adicionales. Análogamente, un método declarado como final 110 puede ser redefinido por una clase que derive de su propia clase.

lunes, 25 de noviembre de 2013

Constructores en clases derivadas

Ya se comentó que un constructor de una clase puede llamar por medio de la palabra this a otro constructor previamente definido en la misma clase. En este contexto, la palabra this sólo puede aparecer en la primera sentencia de un constructor. 
De forma análoga el constructor de una clase derivada puede llamar al constructor de su super-clase por medio de la palabra super(). seguida entre paréntesis de los argumentos apropiados para uno de los constructores de la super-clase. De esta forma, un constructor sólo tiene que inicializar directamente las variables no heredadas. 
La llamada al constructor de la super-clase debe ser la primera sentencia del constructor4, excepto si se llama a otro constructor de la misma clase con this(). Si el programador 110 la incluye. Java incluye automáticamente una llamada al constructor por defecto de la super-clase. super(). Esta llamada en cadena a los constructores de las super-clases llega hasta el origen de la jerarquía de clases, esto es al constructor de Object. 
Como ya se ha dicho, si el programador 110 prepara un constructor por defecto, el compilador crea uno. inicializando las variables de los tipos primitivos a sus valores por defecto, y los Stríngs y demás referencias a objetos a nuil. Antes, incluirá una llamada al constructor de la super-clase.
En el proceso de finalización o de liberación de reclusos (diferentes de la memoria reservada con nen\ de la que se encarga el garbage collector), es importante llamar a los finalizadores de las distintas clases, normalmente en orden inverso al de llamada de los constructores. Esto hace que el finalizador de la sub-clase deba realizar todas sus tareas primero y luego llamar al finalizador de la super-clase en la forma super.finalize(). Los métodos finalize() deben ser al menos protected. ya que el método finalize() de Object lo es, y 110 está permitido reducir los permisos de acceso en la herencia.

domingo, 24 de noviembre de 2013

Clases y métodos abstractos

Una clase abstracta (abstract) es una clase de la que 110 se pueden crear objetos. Su utilidad es permitir que otras clases deriven de ella, proporcionándoles un marco o modelo que deben seguir y algunos métodos de utilidad general. Las clases abstractas se declaran anteponiéndoles la palabra abstract, como por ejemplo.

public abstract class Geometria { ... }


Una clase abstract puede tener métodos declarados como abstract. en cuyo caso 110 se da definición del método. Si una clase tiene algún método abstract es obligatorio que la clase sea abstract. E11 cualquier sub-clase este método deberá bien ser redefinido. bien volver a declararse como abstract (el método y la sub-clase). 
Una clase abstract puede tener métodos que 110 son abstract. Aunque 110 se puedan crear objetos de esta clase, sus sub-clases heredarán el método completamente a punto para ser utilizado. Como los métodos static no pueden ser redefinidos, un método abstract 110 puede ser static.

sábado, 23 de noviembre de 2013

Redefinición de métodos heredados

Una clase puede redefinir (volver a definir) cualquiera de los métodos heredados de su super-clase que 110 sean final. El nuevo método sustituye al heredado para todos los efectos en la clase que lo ha redefinido. Las métodos de la super-clase que han sido redefinidos pueden ser todavía accedidos por medio de la palabra super desde los métodos de la clase derivada, aunque con este sistema sólo se puede subir un nivel en la jerarquía de clases. Los métodos redefinidos pueden ampliar los derechos de acceso de la super-clase (por ejemplo ser public. en vez de protected o package). pero nunca restringirlos. 
Los métodos de clase o static 110 pueden ser redefinidos en las clases derivadas.

viernes, 22 de noviembre de 2013

La clase Object

Como ya se ha dicho, la clase Object es la raíz de toda la jerarquía de clases de Java. Todas las clases de Java derivan de Object. La clase Object tiene métodos interesantes para cualquier objeto que son heredados por cualquier clase. Entre ellos se pueden citar los siguientes:

1. Métodos que pueden ser redefinidos por el programador: 
clone () Crea un objeto a partir de otro objeto de la misma clase. El método original heredado de Object lanza una CloneNotSupportedException. Si se desea poder clonar una clase hay que implementar la interface Cloneable y redefinir el método 
clone (). Este método debe hacer una copia miembro a miembro del objeto original. No debería llamar al operador new ni a los constructores. 
equals() Indica si dos objetos son o no iguales. Devuelve trae si son iguales, tanto si son referencias al mismo objeto como si son objetos distintos con iguales valores de las variables miembro. 
toString() Devuelve un String que contiene una representación del objeto como cadena de caracteres, por ejemplo para imprimirlo o exportarlo. finalizeQ Este método ya se ha visto al hablar de los finalizadores.

2. Métodos que 110 pueden ser redefinidos (son métodos final):
getClass () Devuelve un objeto de la clase Class. al cual se le pueden aplicar métodos para determinar el nombre de la clase, su super-clase, las interfaces iniplementadas, etc. Se puede crear un objeto de la misma clase que otro sin saber de qué clase es.
notify (), notifyAllQ y wait() Son métodos relacionados con las threads

jueves, 21 de noviembre de 2013

HERENCIA

Concepto de herencia 

Se puede construir una clase a partir de otra mediante el mecanismo de la herencia. Para indicar que una clase deriva de otra se utiliza la palabra extends, como por ejemplo: 

class CirculoGrafico extends Circulo {...} 

Cuando una clase deriva de otra, hereda todas sus variables y métodos. Estas funciones y variables miembro pueden ser redefinidas (overridden) en la clase derivada, que puede también definir o añadir nuevas variables y métodos. En cierta forma es como si la sub-clase (la clase derivada) "contuviera" un objeto de la super-clase: en realidad lo "amplia" con nuevas variables y métodos. 
Java permite múltiples niveles de herencia, pero 110 permite que una clase derive de varias (no es posible la herencia múltiple). Se pueden crear tantas clases derivadas de una misma clase como se quiera. 
Todas las clases de Java creadas por el programador tienen una super-clase. Cuando 110 se indica explícitamente una super-clase con la palabra extends. la clase deriva de java.lang.Object. que es la clase raíz de toda la jerarquía de clases de Java. Como consecuencia, todas las clases tienen algunos métodos que han heredado de Object.
La composición (el que una clase contenga un objeto de otra clase como variable miembro) se diferencia de la herencia en que incorpora los datos del objeto miembro, pero no sus métodos o interface (si dicha variable miembro se hace prívate).

miércoles, 20 de noviembre de 2013

Cómo fimciouau los packages

Con la sentencia import packname; se puede evitar tener que utilizar nombres muy largos, al mismo tiempo que se evitan los conflictos entre nombres. Si a pesar de todo hay conflicto entre nombres de clases. Java da un error y obliga a utilizar los nombres de las clases cualificados con el nombre del package. El importar un package no hace que se carguen todas las clases del package: sólo se cargarán las clases public que se vayan a utilizar. 
Al importar un package no se importan los sub-packages. Estos deben ser importados explícitamente, pues en realidad son packages distintos. Por ejemplo, al importar java.awt no se importa java.awt.event. Es posible guardar en jerarquías de directorios diferentes los ficheros *.class y *.java. con objeto por ejemplo de no mostrar la situación del código fuente. Los packages hacen referencia a los ficheros compilados *.class. 
En un programa de Java, una clase puede ser referida con su nombre completo (el nombre del package más el de la clase, separados por un punto). También se pueden referir con el nombre completo las variables y los métodos de las clases. Esto se puede hacer siempre de modo opcional, pero es incómodo y hace más difícil el reutilizar el código y portarlo a otras máquinas. 
La sentencia import permite abreviar los nombres de las clases, variables y métodos, evitando el tener que escribir continuamente el nombre del package importado. Se importan por defecto el package javaJang y el package actual o por defecto (las clases del directorio actual). Existen dos formas de utilizar import: para una clase y para todo un package:

import es.ceit.jgjalón.infor2.ordenar.QuickSort.class;

import es.ceit.jgjalon.infor2.ordenar.*;
que deberían estar en el directorio:

classpath\es\ceit\jgjalon\infor2\ordenar

martes, 19 de noviembre de 2013

PACKAGES

Qué es un package 

Un package es una agrupación de clases. En la API de Java 1.1 había 22 packages: en Java 1.2 hay 59 packages. lo que da una idea del "crecimiento'' experimentado por el lenguaje. Además, el usuario puede crear sus propios packages. 
Para que una clase pase a formar paite de un package llamado pkgName. hay que introducir en ella la sentencia:
package pkgName;

que debe ser la primera sentencia del fichero sin contar comentarios y líneas en blanco. Los nombres de los packages se suelen escribir con minúsculas, para distinguirlos de las clases, que empiezan por mayúscula. El nombre de irn package puede constar de varios nombres unidos por puntos (los propios packages de Java siguen esta norma, como por ejemplo java.awt.event). 
Todas las clases que forman parte de un package deben estar en el mismo directorio. Los nombres compuestos de los packages están relacionados con la jerarquía de directorios en que se guardan las clases. Es recomendable que los nombres de las clases de Java sean únicos en Internet. Es el nombre del package lo que permite obtener esta característica. 
Una forma de conseguirlo es incluir el nombre del dominio (quitando quizás el país), como por ejemplo en el package siguiente:

es.ceit.jgj alón.infor2.ordenar

Las clases de un package se almacenan en un directorio con el mismo nombre largo (path) que el package. Por ejemplo, la clase. es.ceit.j gj alón.infor2.ordenar.QuickSort.class debería estar en el directorio,

CLASS?ATH\es\ceit\jgjalon\infor2\ordenar\QuickSort.class

donde CLASSPATH es una variable de entorno del PC que establece la posición absoluta de los directorios en los que hay clases de Java (clases del sistema o de usuario), en este caso la posición del directorio es en los discos locales del ordenador. Los packages se utilizan con las finalidades siguientes: 
  1. Para agrupar clases relacionadas. 
  2. Para evitar conflictos de nombres (se recuerda que el dominio de nombres de Java es la Internet). En caso de conflicto de nombres entre clases importadas, el compilador obliga a cualificar en el código los nombres de dichas clases con el nombre del package. 
  3. Para ayudar en el control de la accesibilidad de clases y miembros.

lunes, 18 de noviembre de 2013

Finalizadores

Los finalizadores son métodos que vienen a completar la labor del garbage collector. Un finalizador es un método que se llama automáticamente cuando se va a destruir un objeto (antes de que la memoria sea liberada de modo automático por el sistema). Se utilizan para ciertas operaciones de terminación distintas de liberar memoria (por ejemplo: cenar ficheros, cerrar conexiones de red. liberar memoria reservada por funciones nativas, etc.). 
Hay que tener en cuenta que el garbage collector sólo libera la memoria reservada con new. Si por ejemplo se ha reservado memoria con funciones nativas en C (por ejemplo, utilizando la función mallocQ), esta memoria hay que liberarla explícitamente utilizando el método finalizeQ. Un finalizador es un método de objeto (no static). sin valor de retomo (void). sin argumentos y que siempre se llama finalizeQ. Los finalizadores se llaman de modo automático siempre que hayan sido definidos por el programador de la clase. Para realizar su tarea correctamente, un finalizador debería terminar siempre llamando al finalizador de su super-clase. 
Tampoco se puede saber el momento preciso en que los finalizadores van a ser llamados. En muchas ocasiones será conveniente que el programador realice esas operaciones de finalización de modo explícito mediante otros métodos que él mismo llame. 
El método System.runFinalizationf) "sugiere*' a la JVM que ejecute los finalizadores de los objetos pendientes (que han perdido la referencia). Parece ser que para que este método se ejecute, en Java 1.1 hay que llamar primero a gc() y luego a runFin alizationf).

domingo, 17 de noviembre de 2013

Destrucción de objetos (liberación de memoria)

En Java no hay destructores como en C++. El sistema se ocupa automáticamente de liberar la memoria de los objetos que ya han perdido la referencia. esto es. objetos que ya no tienen ningún nombre que permita acceder a ellos, por ejemplo por haber llegado al final del bloque en el que habían sido definidos, porque a la referencia se le ha asignado el valor nuil o porque a la referencia se le ha asignado la dirección de otro objeto. A esta característica de Java se le llama garbage collection (recogida de basura). En Java es normal que varias variables de tipo referencia apunten al mismo objeto. Java lleva internamente un contador de cuántas referencias hay sobre cada objeto. El objeto podrá ser borrado cuando el número de referencias sea cero. Como ya se ha dicho, una forma de hacer que un objeto quede sin referencia es cambiar ésta a nuil, haciendo por ejemplo:

ObjetoRef = nuil;


En Java no se sabe exactamente cuándo se va a activar el garbage collector. Si no falta memoria es posible que no se llegue a activar en ningún momento. No es pues conveniente confiar en él para la realización de otras tareas más críticas. Se puede llamar explícitamente al garbage collector con el método System.gc(). aunque esto es considerado por el sistema sólo como una "sugerencia" a la JVM.