lunes, 2 de agosto de 2010

Manejo de Excepciones

Para manejar las excepciones y evitar que un programa termine por algun error se usa el bloque:

Try-catch

Las sentencias del bloque try, que se encuentran despues de la sentencia que causo la excepcion no se ejecutaran.

Try
{
Char x = (char)System.in.read();
}
Catch ( IOException ioe)
{
//cidigo para manejar el error
}
Catch ( Exception e)
{
//codigo para manejar excepciones
}

TIPOS DE EXCEPCIONES

Checked: Son las excepciones que revisa el compilador.

Unchecked: Son las excepciones que no revisa el compilador y se dan en tiempo de ejecución.

EXCEPCIONES EN JAVA

En todo programa existen errores inesperados en tiempo de ejecución, y también errores que no consideramos debido a nuestra propia inexperiencia como programadores. Unos de estos errores ocurren por ejemplo, al intentar acceder a un elemento del arreglo que está fuera del límite de nuestro arreglo, o cuando intentamos acceder a un archivo inexistente, entre otros. Normalmente estos errores interrumpen el flujo de ejecución de nuestros programas, hasta el extremo de provocar la terminación del programa en forma inmediata. Java hace uso de las excepciones1.1 para poder controlar los errores en tiempo de ejecución. En Java, casi todo los tipos de errores que puedan surgir en tiempo de ejecución lanzan excepciones, es decir, cuando ocurre un error dentro de un método de JAva, este método crea un objeto Exception, dicho objeto contiene información sobre la excepción, que incluye su tipo y el estado del programa cuando ocurrió el error. El sistema de ejecución es el responsable de buscar algún código para manejar el error. El manejo de excepciones en Java sigue una estructura como esta:


try {
//Codigo donde puede ocurrir un error
}
catch (ExcepcionA ex) { // Que se va a hacer en caso que
se lanze una Excepcion A }
...
catch (ExcepcionZ ex) { // Que se va a hacer en caso que
se lanze una Excepcion Z }



Dentro del bloque try{ } viene encerrado la parte del programa que se desea manejar sus excepciones. El código dentro de algún catch (TipoExcepcion e) se ejecuta en caso se que lanze una excepción TipoExcepcion o que pertenezca al grupo TipoExcepcion. El sistema de ejecución Java busca hacia atrás en la pila de llamadas para encontrar el método que esté interesado en manejar una excepción particular. Es decir si se lanza una excepción en el método $A$, pero si $A$ no está interesado en manejar dicha excepción, entonces el sistema de ejecución Java ve quién llamó a $A$ (supongamos que si existe, y es el método $B$), entonces se regresa a $B$ y ve si está interesado en dicha excepción, y así consecutivamente hasta llegar al método principal de nuestra aplicación. En caso de no encontrar alguien que quiera manejarlo, comunmente Java manda una lista de mensajes en nuestra ventana de consola, y en muchos casos se termina la ejecución de nuestro programa. Cuando manejamos excepciones, podemos manejar excepciones en forma específica (por ejemplo, usar un índice que está fuera de los límites de nuestro arreglo), o manejar una excepción de cierta categoría (por ejemplo, una excepción lanzada por mal uso de un arreglo de datos), o manejar todas las excepciones en su conjunto. Para el primer caso, es necesario este código catch(ArrayIndexOutOfBoundsException e){ }, para el segundo catch (ArrayException e){}1.2 y para el último catch (Exception e){ }. En la práctica no es recomendable hacer usar de manejadores de excepciones demasiado generales, como la del último caso. Las excepciones son parte de Java, y es muy común usarlos en las operaciones E/S, ya que es donde más probabilidad hay de que se lanze una. Conforme se vean los temas, se considerán muchos excepciones que son obligaciones de capturar por la propia sintaxis de java. Pero estos se considerarán conforme se vean los temas

lunes, 12 de julio de 2010

POLIMORFISMO

POLIMORFISMO:
el polimorfismo es un concepto de la programación orientada a objetos que nos permite programar en forma general, en lugar de hacerlo en forma específica. en general nos sirve para programar objetos con características comunes y que todos estos compartan la misma superclase en una jerarquía de clases, como si todas fueran objetos de la superclase. esto nos simplifica la programación.

CLASES ABSTRACTAS:
una de las características más útiles de cualquier lenguaje orientado a objetos es la posibilidad de declarar clases que definen como se utiliza solamente, sin tener que implementar métodos. esto es muy útil cuando la implementación es específica para cada usuario, pero todos los usuarios tienen que utilizar los mismos métodos

QUE ES UNA INTERFAZ.?
una interfaz define una serie de métodos que debe implementar una clase. es decir, una interfaz es una colección de métodos sin cuerpo, contiene únicamente lo que se denomina signatura del método.trabajar con interfaces permite abstraernos de la clase que la implementa.
una interfaz en java es una colección de métodos abstractos y propiedades. en ellas se especifica qué se debe hacer pero no su implementación. serán las clases que implementen estas interfaces las que describan la logica del comportamiento de los métodos.

LA CLASE BOOLEAN:
los valores //boolean// también tienen su tipo asociado //boolean//, aunque en este caso hay menos métodos implementados que para el resto de las clases numéricas.

==== //declaraciones// ====

la primera sentencia creará una variable boolean y la segunda un objeto boolean:
boolean b;
boolean b;

==== //valores de boolean// ====

boolean.true;
boolean.false;

==== //métodos de boolean// ====

boolean b.booleanvalue();
string b.tostring();
boolean b.equals( object obj );

LA CLASE CHARACTER:
al trabajar con caracteres se necesitan muchas funciones de comprobación y traslación. estas funciones están empleadas en la clase character. de esta clase sí que se pueden crear instancias, al contrario que sucede con la clase math.

==== //declaraciones// ====

la primera sentencia creará una variable carácter y la segunda un objeto character:

char c;
character c;

==== //comprobaciones booleanas// ====

character.islowercase( c )
character.isuppercase( c )
character.isdigit( c )
character.isspace( c )

en este caso, si tuviésemos un objeto character c, no se podría hacer //c.islowercase//, porque no se ha hecho un new de character. estas funciones son estáticas y no conocen al objeto, por eso hay que crealo antes.

==== //traslaciones de caracteres// ====

char c2 = character.tolowercase( c );
char c2 = character.touppercase( c );

==== //traslaciones de carácter/dígito// ====

int i = character.digit( c,base );
char c = character.fordigit( i,base );

==== //métodos de la clase character// ====

c = new character( 'j' );
char c = c.charvalue();
string s = c.tostring();


LA CLASE DOUBLE:
cada tipo numérico tiene su propia clase de objetos. así el tipo //double// tiene el objeto //double//. de la misma forma que con la clase character, se han codificado muchas funciones útiles dentro de los métodos de la clase double.

==== //declaraciones// ====

la primera sentencia creará una variable double y la segunda un objeto double:

double d;
double d;

==== //valores de double//====

double.positive_infinity
double.negative_infinity
double.nan
double.max_value
double.min_value

==== //métodos de double// ====

d.isnan();
double.isnan( d );
d.isinfinite();
double.isinfinite( d );
boolean d.equals();
string d.tostring();
int d.intvalue();
long d.longvalue();
float d.floatvalue();
double d.doublevalue();
int i = d.hashcode();
double v.valueof( string s );
long l = double.doubletolongbits( d );
double d = double.longbitstodouble( l );

LA CLASE FLOAT:
cada tipo numérico tiene su propia clase de objetos. así el tipo //float// tiene el objeto //float//. de la misma forma que con la clase character, se han codificado muchas funciones útiles dentro de los métodos de la clase float.

==== //declaraciones// ====

la primera sentencia creará una variable float y la segunda un objeto float:

float f;
float f;

==== //valores de float// ====

float.positive_infinity
float.negative_infinity
float.nan
float.max_value
float.min_value

==== //conversiones de clase/cadena// ====

string s = float.tostring( f );
f = float.valueof( "3.14" );

==== //comprobaciones// ====

boolean b = float.isnan( f );
boolean b = float.isinfinite( f );

la función //isnan()// comprueba si ##f## es un //no-número//. un ejemplo de no-número es raiz cuadrada de -2.

==== //conversiones de objetos// ====

float f = new float( float.pi );
string s = f.tostring();
int i = f.intvalue();
long l = f.longvalue();
float f = f.floatvalue();
double d = f.doublevalue();

==== //otros métodos// ====

int i = f.hashcode();
boolean b = f.equals( object obj );
int i = float.floattointbits( f );
float f = float.intbitstofloat( i );

LA CLASE INTEGER:
cada tipo numérico tiene su propia clase de objetos. así el tipo //int// tiene el objeto //integer//. de la misma forma que con la clase character, se han codificado muchas funciones útiles dentro de los métodos de la clase integer.

==== //declaraciones// ====

la primera sentencia creará una variable int y la segunda un objeto integer:

int i;
integer i;

==== //valores de integer// ====

integer.min_value;
integer.max_value;

==== //métodos de integer// ====

string integer.tostring( int i,int base );
string integer.tostring( int i );
int i.parseint( string s,int base );
int i.parseint( string s );
integer integer.valueof( string s,int base );
integer integer.valueof( string s );
int i.intvalue();
long i.longvalue();
float i.floatvalue();
double i.doublevalue();
string i.tostring();
int i.hashcode();
boolean i.equals( object obj );

en los métodos //tostring()//, //parseint()// y //valueof()// que no se especifica la base sobre la que se trabaja, se asume que es base 10.

LA CLASE LONG:
cada tipo numérico tiene su propia clase de objetos. así el tipo //long// tiene el objeto// long//. de la misma forma que con la clase character, se han codificado muchas funciones útiles dentro de los métodos de la clase long.

==== //declaraciones// ====

la primera sentencia creará una variable long y la segunda un objeto long:

long l;
long l;

==== //valores de long// ====

long.min_value;
long.max_value;

==== //métodos de long// ====

string long.tostring( long l,int base );
string long.tostring( long l );
long l.parselong( string s,int base );
long l.parselong( string s );
long long.valueof( string s,int base );
long long.valueof( string s );
int l.intvalue();
long l.longvalue();
float l.floatvalue();
double l.doublevalue();
string l.tostring();
int l.hashcode();
boolean l.equals( object obj );

en los métodos //tostring()//, //parseint()// y //valueof()// que no se especifica la base sobre la que se trabaja, se asume que es base 10.

LA CLASE STRING:
java posee gran capacidad para el manejo de cadenas dentro de sus clases string y stringbuffer. un objeto //string// representa una cadena alfanumérica de un valor constante que no puede ser cambiada después de haber sido creada. un objeto //stringbuffer// representa una cadena cuyo tamaño puede variar.

los strings son objetos constantes y por lo tanto muy baratos para el sistema. la mayoría de las funciones relacionadas con cadenas esperan valores string como argumentos y devuelven valores string.
hay que tener en cuenta que las funciones estáticas no consumen memoria del objeto, con lo cual es más conveniente usar character que char. no obstante, char se usa, por ejemplo, para leer ficheros que están escritos desde otro lenguaje.

existen muchos constructores para crear nuevas cadenas:

string();
string( string str );
string( char val[] );
string( char val[],int offset,int count );
string( byte val[],int hibyte );
string( byte val[],int hibyte,int offset,int count );

tal como uno puede imaginarse, las cadenas pueden ser muy complejas, existiendo muchas funciones muy útiles para trabajar con ellas y, afortunadamente, la mayoría están codificadas en la clase string.

==== //funciones básicas// ====

la primera devuelve la longitud de la cadena y la segunda devuelve el carácter que se encuentra en la posición que se indica en ##indice##:

int length();
char charat( int indice );

=== //funciones de comparación de strings// ===

boolean equals( object obj );
boolean equalsignorecase( object obj );

lo mismo que //equals()// pero no tiene en cuenta mayúsculas o minúsculas.

int compareto( string str2 );

devuelve un entero menor que cero si la cadena es léxicamente menor que ##str2##.

devuelve cero si las dos cadenas son léxicamente iguales y un entero mayor que cero si la cadena es léxicamente mayor que ##str2##.

=== //funciones de comparación de subcadenas// ===

boolean regionmatch( int thisoffset,string s2,int s2offset,int len );
boolean regionmatch( boolean ignorecase,int thisoffset,string s2,int s2offset,int 1 );

comprueba si una región de esta cadena es igual a una región de otra cadena.

boolean startswith( string prefix );
boolean startswith( string prefix,int offset );
boolean endswith( string suffix );

devuelve si esta cadena comienza o termina con un cierto prefijo o sufijo comenzando en un determinado desplazamiento.

int indexof( int ch );
int indexof( int ch,int fromindex );
int lastindexof( int ch );
int lastindexof( int ch,int fromindex );
int indexof( string str );
int indexof( string str,int fromindex );
int lastindexof( string str );
int lastindexof( string str,int fromindex );

devuelve el primer/último índice de un carácter/cadena empezando la búsqueda a partir de un determinado desplazamiento.

string substring( int beginindex );
string substring( int beginindex,int endindex );
string concat( string str );
string replace( char oldchar,char newchar );
string tolowercase();
string touppercase();
string trim();

ajusta los espacios en blanco al comienzo y al final de la cadena.

void getchars( int srcbegin,int srcend,char dst[],int dstbegin );
void getbytes( int srcbegin,int srcend,byte dst[],int dstbegin );
string tostring();char tochararray();int hashcode();

==== //funciones valueof// ====

la clase string posee numerosas funciones para transformar valores de otros tipos de datos a su representación como cadena. todas estas funciones tienen el nombre de //valueof//, estando el método sobrecargado para todos los tipos de datos básicos.

veamos un ejemplo de su utilización:

string uno = new string( "hola mundo" );
float f = 3.141592;

string pi = uno.valueof( f );
string pi = string.valueof( f );

// mucho más correcto=== //

funciones de conversión// ===

string valueof( boolean b );
string valueof( int i );
string valueof( long l );
string valueof( float f );
string valueof( double d );
string valueof( object obj );
string valueof( char data[] );
string valueof( char data[],int offset,int count );

usa arrays de caracteres para la cadena.

string copyvalueof( char data[] );
string copyvalueof( char data[],int offset,int count );

crea un nuevo array equivalente para la cadena.

PROGRAMAS CON LA CLASE STRING:

package string;
//import javax.swing.*;
/**
*
* @author lalo
*/
public class equals {

/**
* @param args the command line arguments
*/
public static void main(String[] args)
{
System.out.println("iguales");
System.out.println("edgar vs Edgar ="+"edgar".equals("Edgar"));
System.out.println("edgar vs EDGAR ="+"edgar".equals("EDGAR"));
System.out.println("EDGAR vs EDGAR ="+"EDGAR".equals("EDGAR"));
}

}
PROGRAMA CON CLASE STRING Y EL METODO CONCAT
package string3;

/**
*
* @author lalo
*/
public class concat {

/**
* @param args the command line arguments
*/
public static void main(String[] args)
{
String cade1 = "hola ";
String cade2 = "mundo";
System.out.println("cadena1="+cade1);
System.out.println("cadena2="+cade2);
String cade3=cade1.concat(cade2);
System.out.println("concatenacion= "+cade3);

}

}

lunes, 21 de junio de 2010

ARREGLOS CON OBJETOS:

Después de haber declarado la variable arreglo, el siguiente paso es crear un arreglo de objetos y asignarlo a esa variable. Las formas de hacerlo son:
• a través del operador new
• inicializando directamente el contenido del arreglo
Ejemplos:

String [ ] nombreJugadores = new String [10];
int [ ] temps = new int [99];

Todas las posiciones se inicializan automáticamente (0 para arreglos numéricos, false para booleanos, ‘\0’ para arreglos de carácter y null para objetos)

También se puede crear e inicializar un arreglo al mismo tiempo. Encierre los elementos del arreglo entre llaves, separándolos con comas:

String [ ] chiles = { “jalapeno”, “de árbol”, “serrano”, “habanero”};


Al crear elementos con valores iniciales, el arreglo es del mismo tamaño que la cantidad de elementos que ha incluido en las llaves.

package ejemplodearreglos;

/**
*
* @author Lalo
*/
public class ArregloNombres {
String[] nombres = { "Dennis", "Grace", "Bjarne", "James"};
String[] apellidos = new String[nombres.length];

void imprime()
{
int i = 0;
System.out.println(nombres[i] + " " + apellidos[i]);
i++;
System.out.println(nombres[i] + " " + apellidos[i]);
i++;
System.out.println(nombres[i] + " " + apellidos[i]);
i++;
System.out.println(nombres[i] + " " + apellidos[i]);
}
}



--------DENTRO DEL MAIN----------
public class Main {

/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here ArregloNombres a = new ArregloNombres();

ArregloNombres a = new ArregloNombres();
a.imprime();
System.out.println("-----");
a.apellidos[0] = "Ritchie";
a.apellidos[1] = "Hopper";
a.apellidos[2] = "Stroustrup";
a.apellidos[3] = "Gosling";
a.imprime();

}
}

COMO DECLARAR ARREGLOS EN JAVA..?

Un arreglo es una colección de objetos numerados del mismo tipo, en donde cada variable o celda en el arreglo tiene un índice. Las celdas están numeradas del 0 al N-1, donde N es el número de celdas del arreglo es decir su capacidad.
Los índices de un arreglo en Java deben estar dentro de los límites, 0 – N-1, de lo contrario se generará un error durante la ejecución.

Java implementa los arreglos como objetos que pueden ser tratados como cualquier otro objeto.

Para utilizar un arreglo en Java:
1. Declare una variable para que contenga el arreglo
2. Cree un nuevo arreglo de objeto y asígnelo a la variable de arreglo
3. Almacene información en ese arreglo
4. Realice operaciones de almacenamiento y recuperación con los elementos del arreglo
Declaración:

Se agrega un par de corchetes vacíos

[ ]

al objeto o tipo de datos, o al nombre de variable.
Ejemplos:
String palabrasDificiles [ ];
Point hits [ ];
int donaciones [ ];

O bien:

String [ ] palabrasDificiles;
Point [ ] hits;
int [ ] donaciones;
*******EJEMPLO


EJEMPLO:

package inic2arreglo;
import javax.swing.JOptionPane;
/**
*
* @author Alumnos
*/
public class Main {

/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here

final int LONGITUD_ARREGLO = 10; // constante
int arreglo[]; // referencia a un arreglo int

arreglo = new int[ LONGITUD_ARREGLO ]; // crear el arreglo

// calcular el valor para cada elemento del arreglo
for ( int contador = 0; contador < arreglo.length; contador++ )
arreglo[ contador ] = 2 + 2 * contador;

String salida = "Índice\tValor\n";

for ( int contador = 0; contador < arreglo.length; contador++ )
salida += contador + "\t" + arreglo[ contador ] + "\n";
JTextArea areaSalida = new JTextArea();
areaSalida.setText( salida );

JOptionPane.showMessageDialog( null, areaSalida,
"Inicialización con enteros pares del 2 al 20",
JOptionPane.INFORMATION_MESSAGE );

System.exit( 0 );

} // fin de main

}

miércoles, 2 de junio de 2010

HERENCIA

QUE ES HERENCIA.?

La herencia es el mecanismo fundamental para implemetar la reutilizacion y extensibilidad del software. Atravez de ella los diseñadores pueden construir nuevas clases partiendo de una jerarquia de claseses ya existentes, evitando con ello el rediseño, la remodificacion y verificacion de la parte ya implementada. La herencia facilita la creacion de objetos a partir de otros ya existentes obteniendo caracteristicas(metodos y atributos) similares a los ya existentes.

Caracteristica muy importante que permite definir una clase tomando como base a otra clase ya existente.
En java la herencia es especifica agregando la clausula extends despues del nombre de la clase(en la clausula extends indicaremos el nombre de la clase base de la cual queremos heredar).
Al heredar de una clase base, heredaremos tanto los atributos como los metodos, mientras que los constructores son utilizados, pero no heredados.

domingo, 16 de mayo de 2010

CONSTRUCTORES

Un Constructor es un método especial en Java empleado para inicializar valores en Instancias de Objetos, a través de este tipo de métodos es posible generar diversos tipos de instancias para la Clase en cuestión; la principal característica de este tipo de métodos es que llevan el mismo nombre de la clase.

El constructor de una clase es un método estándar para inicializar los objetos de esa clase
Se invoca automáticamente cuando new crea un objeto de esa clase.

  • Los constructores se declaran en el momento de definir la clase.

class A {
int x, y;
A() { x=0; y=0; } // el constructor
...
}
A a= new A();
a.Print(); // 0 0
  • El constructor puede tener parámetros. En este caso, se deben colocar los argumentos respectivos al crear el objeto:

class A {
int x, y;
A(int ix, int iy)
{ x=ix; y=iy; } // el constructor
...
}
A a= new A(1,2);
a.Print(); // 1 2
a= new A(); // error, hay que colocar
// los argumentos
a.A(1,2); // error, no se puede
// invocar el constructor

  • Se pueden colocar varios constructores. Durante la creación de un objeto, se invoca aquel que calza con los argumentos dados:

class A {
int x, y;
A() { x=0; y= 0; }
A(int ix, int iy)
{ x=ix; y=iy; }
A(A from)
{ x= from.x; y= from.y; }
...
}
A a1= new A();
a1.Print(); // 0 0
A a2= new A(1,2);
a2.Print(); // 1 2
A a3= new A(a2);
a3.Print(); // 1 2

  • Un destructor es un método que se invoca automáticamente cuando el objeto se destruye. Java no posee destructores, porque tiene recolección de basuras. C++ posee destructores.

domingo, 9 de mayo de 2010

TIPOS DE DATOS EN JAVA
ENTEROS: Estos tipos son byte, short, int y long, que guardan el signo valor, estos representan un número y no pueden representar elementos fraccionarios.
NÚMEROS EN COMA FLOTANTE: Estos son float y double y pueden almacenar números en coma flotante y con signo, esto quiere decir que nos permiten representar números decimales.Todos los literales de coma flotante son del tipo double salvo que se especifique lo contrario, por eso si se intenta asignar un literal en coma flotante a una variable de tipo float el compilador nos dará un error (tipos incompatibles).
EL TIPO CARACTER: Estos son de tipo char, que almacena la representación de los caracteres (letras o números), un carácter esta almacenado en 16 bits, y siguen un estándar que es el Unicoide.EL TIPO BOOLEANO: Este solo guarda dos valores: verdadero (true) o falso(false), y no como ocurre en otros lenguajes que toman los valores 0 y 1. Generalmente su utilización es muy frecuente para determinar el flujo de los programas.
LOS ARRAYS (MATRICES)Java dispone de un tipo de dato de posiciones secuenciales y que cuenta de unas comprobaciones exhaustivas para su correcta manipulación como puede ser la comprobación de no sobrepasar los limites permitidos en la definición del array.Los arrays permiten guardar grupos de datos similares, puesto que Java trata los arrays como un tipo de objeto y por lo tanto este se tendra que instanciar con el operador new.Para crear un array tenemos que especificar una variable que se utilizara como índice para acceder al array y el tipo de datos que este contendrá.
TIPOS DE DATOS STRING (LAS CADENAS)En realidad una variable de tipo string, más que un típo propio de Java es una clase tratada con todo rigor como un objeto más de Java.En Java el contenido de las cadenas no se pueden modificar aun que se vuelva a definir la variable String, si en un programa se necesita modificar el contenido de una cadena lo más correcto seria utilizar la clase StringBuffer, la cual posee muchos metodos para este cometido como append().
QUE ES POO:
La programación Orientada a objetos (POO) es una forma especial de programar, más cercana a como expresaríamos las cosas en la vida real que otros tipos de programación.
Con la POO tenemos que aprender a pensar las cosas de una manera distinta, para escribir nuestros programas en términos de objetos, propiedades, métodos y otras cosas que veremos rápidamente para aclarar conceptos y dar una pequeña base que permita soltarnos un poco con este tipo de programación.

CARACTERÍSTICAS DE POO:
ABSTRACCIÓN: Denota las características esenciales de un objeto, donde se capturan sus comportamientos. Cada objeto en el sistema sirve como modelo de un "agente" abstracto que puede realizar trabajo, informar y cambiar su estado, y "comunicarse" con otros objetos en el sistema sin revelar cómo se implementan estas características. Los procesos, las funciones o los métodos pueden también ser abstraídos y cuando lo están, una variedad de técnicas son requeridas para ampliar una abstracción.
ENCAPSULAMIENTO: Significa reunir a todos los elementos que pueden considerarse pertenecientes a una misma entidad, al mismo nivel de abstracción. Esto permite aumentar la cohesión de los componentes del sistema. Algunos autores confunden este concepto con el principio de ocultación, principalmente porque se suelen emplear conjuntamente.
PRINCIPIO DE OCULTACIÓN: Cada objeto está aislado del exterior, es un módulo natural, y cada tipo de objeto expone una interfaz a otros objetos que especifica cómo pueden interactuar con los objetos de la clase. El aislamiento protege a las propiedades de un objeto contra su modificación por quien no tenga derecho a acceder a ellas, solamente los propios métodos internos del objeto pueden acceder a su estado. Esto asegura que otros objetos no pueden cambiar el estado interno de un objeto de maneras inesperadas, eliminando efectos secundarios e interacciones inesperadas. Algunos lenguajes relajan esto, permitiendo un acceso directo a los datos internos del objeto de una manera controlada y limitando el grado de abstracción. La aplicación entera se reduce a un agregado o rompecabezas de objetos.
POLIMORFISMO: comportamientos diferentes, asociados a objetos distintos, pueden compartir el mismo nombre, al llamarlos por ese nombre se utilizará el comportamiento correspondiente al objeto que se esté usando. O dicho de otro modo, las referencias y las colecciones de objetos pueden contener objetos de diferentes tipos, y la invocación de un comportamiento en una referencia producirá el comportamiento correcto para el tipo real del objeto referenciado. Cuando esto ocurre en "tiempo de ejecución", esta última característica se llama asignación tardía o asignación dinámica. Algunos lenguajes proporcionan medios más estáticos (en "tiempo de compilación") de polimorfismo, tales como las plantillas y la sobrecarga de operadores de C++.
HERENCIA: las clases no están aisladas, sino que se relacionan entre sí, formando una jerarquía de clasificación. Los objetos heredan las propiedades y el comportamiento de todas las clases a las que pertenecen. La herencia organiza y facilita el polimorfismo y el encapsulamiento permitiendo a los objetos ser definidos y creados como tipos especializados de objetos preexistentes. Estos pueden compartir (y extender) su comportamiento sin tener que volver a implementarlo. Esto suele hacerse habitualmente agrupando los objetos en clases y estas en árboles o enrejados que reflejan un comportamiento común. Cuando un objeto hereda de más de una clase se dice que hay herencia múltiple.
RECOLECCIÓN DE BASURA: la Recolección de basura o Garbage Collector es la técnica por la cual el ambiente de Objetos se encarga de destruir automáticamente, y por tanto desasignar de la memoria, los Objetos que hayan quedado sin ninguna referencia a ellos. Esto significa que el programador no debe preocuparse por la asignación o liberación de memoria, ya que el entorno la asignará al crear un nuevo Objeto y la liberará cuando nadie lo esté usando. En la mayoría de los lenguajes híbridos que se extendieron para soportar el Paradigma de Programación Orientada a Objetos como C++ u Object Pascal, esta característica no existe y la memoria debe desasignarse manualmente.
CARACTERÍSTICAS DE JAVA
ES SIMPLE:
Java ofrece toda la funcionalidad de un lenguaje potente, pero sin las características menos usadas y más confusas de éstos. C++ es un lenguaje que adolece de falta de seguridad, pero C y C++ son lenguajes más difundidos, por ello Java se diseñó para ser parecido a C++ y así facilitar un rápido y fácil aprendizaje.
Java elimina muchas de las características de otros lenguajes como C++, para mantener reducidas las especificaciones del lenguaje y añadir características muy útiles como el garbage collector (reciclador de memoria dinámica). No es necesario preocuparse de liberar memoria, el reciclador se encarga de ello y como es un thread de baja prioridad, cuando entra en acción, permite liberar bloques de memoria muy grandes, lo que reduce la fragmentación de la memoria.
Java reduce en un 50% los errores más comunes de programación con lenguajes como C y C++ al eliminar muchas de las características de éstos, entre las que destacan:
· aritmética de punteros
· no existen referencias
· registros (struct)
· definición de tipos (typedef)
· macros (#define)
· necesidad de liberar memoria (free)
ES ORIENTADO A OBJETOS:
Java implementa la tecnología básica de C++ con algunas mejoras y elimina algunas cosas para mantener el objetivo de la simplicidad del lenguaje. Java trabaja con sus datos como objetos y con interfaces a esos objetos. Soporta las tres características propias del paradigma de la orientación a objetos: encapsulación, herencia y polimorfismo. Las plantillas de objetos son llamadas, como en C++, clases y sus copias, instancias . Estas instancias, como en C++, necesitan ser construidas y destruidas en espacios de memoria.
Java incorpora funcionalidades inexistentes en C++ como por ejemplo, la resolución dinámica de métodos. Esta característica deriva del lenguaje Objective C, propietario del sistema operativo Next. En C++ se suele trabajar con librerías dinámicas (DLLs) que obligan a recompilar la aplicación cuando se retocan las funciones que se encuentran en su interior. Este inconveniente es resuelto por Java mediante una interfaz específica llamada RTTI ( RunTime Type Identification ) que define la interacción entre objetos excluyendo variables de instancias o implementación de métodos. Las clases en Java tienen una representación en el runtime que permite a los programadores interrogar por el tipo de clase y enlazar dinámicamente la clase con el resultado de la búsqueda.
ES DISTRIBUIDO:
Java se ha construido con extensas capacidades de interconexión TCP/IP. Existen librerías de rutinas para acceder e interactuar con protocolos como http y ftp . Esto permite a los programadores acceder a la información a través de la red con tanta facilidad como a los ficheros locales.
La verdad es que Java en sí no es distribuido, sino que proporciona las librerías y herramientas para que los programas puedan ser distribuidos, es decir, que se corran en varias máquinas, interactuando.
ES ROBUSTO:
Java realiza verificaciones en busca de problemas tanto en tiempo de compilación como en tiempo de ejecución. La comprobación de tipos en Java ayuda a detectar errores, lo antes posible, en el ciclo de desarrollo. Java obliga a la declaración explícita de métodos, reduciendo así las posibilidades de error. Maneja la memoria para eliminar las preocupaciones por parte del programador de la liberación o corrupción de memoria. También implementa los arrays auténticos , en vez de listas enlazadas de punteros, con comprobación de límites, para evitar la posibilidad de sobreescribir o corromper memoria resultado de punteros que señalan a zonas equivocadas. Estas características reducen drásticamente el tiempo de desarrollo de aplicaciones en Java.
Además, para asegurar el funcionamiento de la aplicación, realiza una verificación de los byte-codes , que son el resultado de la compilación de un programa Java. Es un código de máquina virtual que es interpretado por el intérprete Java. No es el código máquina directamente entendible por el hardware, pero ya ha pasado todas las fases del compilador: análisis de instrucciones, orden de operadores, etc., y ya tiene generada la pila de ejecución de órdenes.
Java proporciona, pues:
· Comprobación de punteros
· Comprobación de límites de arrays
· Excepciones
· Verificación de byte-codes

ES DE ARQUITECTURA NEUTRAL:
Para establecer Java como parte integral de la red, el compilador Java compila su código a un fichero objeto de formato independiente de la arquitectura de la máquina en que se ejecutará. Cualquier máquina que tenga el sistema de ejecución ( run-time ) puede ejecutar ese código objeto, sin importar en modo alguno la máquina en que ha sido generado. Actualmente existen sistemas run-time para Solaris 2.x, SunOs 4.1.x, Windows 95, Windows NT, Linux, Irix, Aix, Mac, Apple y probablemente haya grupos de desarrollo trabajando en el porting a otras plataformas.
El código fuente Java se "compila" a un código de bytes de alto nivel independiente de la máquina. Este código (byte-codes) está diseñado para ejecutarse en una máquina hipotética que es implementada por un sistema run-time, que sí es dependiente de la máquina.
ES SEGURO:
La seguridad en Java tiene dos facetas. En el lenguaje, características como los punteros o el casting implícito que hacen los compiladores de C y C++ se eliminan para prevenir el acceso ilegal a la memoria. Cuando se usa Java para crear un navegador, se combinan las características del lenguaje con protecciones de sentido común aplicadas al propio navegador.
El lenguaje C, por ejemplo, tiene lagunas de seguridad importantes, como son los errores de alineación . Los programadores de C utilizan punteros en conjunción con operaciones aritméticas. Esto le permite al programador que un puntero referencie a un lugar conocido de la memoria y pueda sumar (o restar) algún valor, para referirse a otro lugar de la memoria. Si otros programadores conocen nuestras estructuras de datos pueden extraer información confidencial de nuestro sistema. Con un lenguaje como C, se pueden tomar números enteros aleatorios y convertirlos en punteros para luego acceder a la memoria:
printf( "Escribe un valor entero: " );
scanf( "%u",&puntero );
printf( "Cadena de memoria: %sn",puntero );
Otra laguna de seguridad u otro tipo de ataque, es el Caballo de Troya . Se presenta un programa como una utilidad, resultando tener una funcionalidad destructiva. Por ejemplo, en UNIX se visualiza el contenido de un directorio con el comando ls . Si un programador deja un comando destructivo bajo esta referencia, se puede correr el riesgo de ejecutar código malicioso, aunque el comando siga haciendo la funcionalidad que se le supone, después de lanzar su carga destructiva. Por ejemplo, después de que el caballo de Troya haya enviado por correo el /etc/shadow a su creador, ejecuta la funcionalidad de ls persentando el contenido del directorio. Se notará un retardo, pero nada inusual.
ES PORTABLE:
Más allá de la portabilidad básica por ser de arquitectura independiente, Java implementa otros estándares de portabilidad para facilitar el desarrollo. Los enteros son siempre enteros y además, enteros de 32 bits en complemento a 2. Además, Java construye sus interfaces de usuario a través de un sistema abstracto de ventanas de forma que las ventanas puedan ser implantadas en entornos Unix, Pc o Mac.


ES INTERPRETADO:
El intérprete Java (sistema run-time) puede ejecutar directamente el código objeto. Enlazar (linkar) un programa, normalmente, consume menos recursos que compilarlo, por lo que los desarrolladores con Java pasarán más tiempo desarrollando y menos esperando por el ordenador. No obstante, el compilador actual del JDK es bastante lento. Por ahora, que todavía no hay compiladores específicos de Java para las diversas plataformas, Java es más lento que otros lenguajes de programación, como C++, ya que debe ser interpretado y no ejecutado como sucede en cualquier programa tradicional.
Se dice que Java es de 10 a 30 veces más lento que C, y que tampoco existen en Java proyectos de gran envergadura como en otros lenguajes. La verdad es que ya hay comparaciones ventajosas entre Java y el resto de los lenguajes de programación, y una ingente cantidad de folletos electrónicos que supuran fanatismo en favor y en contra de los distintos lenguajes contendientes con Java. Lo que se suele dejar de lado en todo esto, es que primero habría que decidir hasta que punto Java, un lenguaje en pleno desarrollo y todavía sin definición definitiva, está maduro como lenguaje de programación para ser comparado con otros; como por ejemplo con Smalltalk, que lleva más de 20 años en cancha.
ES MULTITHREADED:
Al ser multithreaded (multihilvanado, en mala traducción), Java permite muchas actividades simultáneas en un programa. Los threads (a veces llamados, procesos ligeros), son básicamente pequeños procesos o piezas independientes de un gran proceso. Al estar los threads contruidos en el lenguaje, son más fáciles de usar y más robustos que sus homólogos en C o C++.
El beneficio de ser miltithreaded consiste en un mejor rendimiento interactivo y mejor comportamiento en tiempo real. Aunque el comportamiento en tiempo real está limitado a las capacidades del sistema operativo subyacente (Unix, Windows, etc.), aún supera a los entornos de flujo único de programa (single-threaded) tanto en facilidad de desarrollo como en rendimiento.
Cualquiera que haya utilizado la tecnología de navegación concurrente, sabe lo frustrante que puede ser esperar por una gran imagen que se está trayendo. En Java, las imágenes se pueden ir trayendo en un thread independiente, permitiendo que el usuario pueda acceder a la información en la página sin tener que esperar por el navegador.
LA MÁQUINA VIRTUAL JAVA:
La Máquina Virtual Java (JVM) es el entorno en el que se ejecutan los programas Java, su misión principal es la de garantizar la portabilidad de las aplicaciones Java. Define esencialmente un ordenador abstracto y especifica las instrucciones (bytecodes) que este ordenador puede ejecutar. El intérprete Java específico ejecuta las instrucciones que se guardan en los archivos cuya extensión es .class. Las tareas principales de la JVM son las siguientes:
Reservar espacio en memoria para los objetos creados
Liberar la memoria no usada (garbage collection).
Asignar variables a registros y pilas
Llamar al sistema huésped para ciertas funciones, como los accesos a los dispositivos
Vigilar el cumplimiento de las normas de seguridad de las aplicaciones Java
Esta última tarea, es una de las más importantes que realiza la JVM. Además, las propias especificaciones del lenguaje Java contribuyen extraordinariamente a este objetivo:
Las referencias a arrays son verificadas en el momento de la ejecución del programa
No hay manera de manipular de forma directa los punteros
La JVM gestiona automáticamente el uso de la memoria, de modo que no queden huecos.
No se permiten realizar ciertas conversiones (casting) entre distintos tipos de datos.