Módulo 2
Plan 111mil
Un objeto es una entidad concreta que existe en el espacio y en el tiempo . Ocupa una cierta cantidad de espacio (memoria o en el mundo físico).
Un objeto es una instancia de una clase. Los objetos que comparten estructura y comportamiento similares pueden agruparse en una clase. En el paradigma orientado a objetos, los objetos pertenecen siempre a una clase, de la que toman su estructura y comportamiento.
Un objeto representa un elemento, unidad o entidad individual e identificable, ya sea real o abstracta, con un rol bien definido en el dominio del problema.
Un objeto tiene un estado, comportamiento e identidad; la estructura y comportamiento de objetos similares están definidos en su clase común; los términos instancia y objeto son intercambiables.
Una propiedad es una característica inherente o distintiva, un rasgo o cualidad que contribuye a hacer que ese objeto sea ese objeto y no otro.
Todas las propiedades tienen un valor. Este valor puede ser una mera cantidad o puede denotar a otro objeto.
Objetos: existen en el tiempo, son modificables, tienen estado, son instanciados y pueden crearse, destruirse y compartirse.
Valores simples: son atemporales, inmutables y no instanciados.
Todos los objetos de un sistema encapsulan (protegen) algún estado, y que todo estado de un sistema está encapsulado en un objeto.
El objeto CAJA DE AHORRO tiene los atributos número, titular y saldo que constituyen su estado interno. Estas son las propiedades estáticas. Por otro lado, el contenido actual de cada atributo (por ejemplo 2345/13, Pedro y 1200,87) representan el valor dinámico de sus propiedades y son afectados por el comportamiento del objeto.
Ningún objeto existe en forma aislada, en vez de eso, los objetos reciben acciones, y ellos mismos actúan sobre otros objetos.
El comportamiento es cómo actúa y reacciona un objeto, en términos de sus cambios de estado y paso de mensajes.
Una operación es una acción que un objeto efectúa sobre otro con el fin de provocar una reacción. Las operaciones que los objetos cliente pueden realizar sobre un objeto, suelen declararse como métodos y forman parte de la declaración de la clase a la que pertenece ese objeto.
El comportamiento del objeto CAJA DE AHORRO está compuesto por las acciones saldo, extraer, depositar, etc.
Una operación denota un servicio que un objeto que pertenece a una clase ofrece. Los tres tipos más comunes de operaciones son los siguientes:
Hay otros dos tipos de operaciones habituales: representan la infraestructura necesaria para crear y destruir instancias de una clase, son:
Las responsabilidades de de un objeto se implementan mediante métodos, los cuales describen el comportamiento de un objeto.
La identidad es aquella propiedad de un objeto que lo distingue de todos los demás objetos
Un objeto CAJA DE AHORRO es distinto de otro objeto caja de ahorro. Pueden tener o no el mismo número, titular o saldo. El primero puede tener como titular Pepe y el segundo Juan.
El tiempo de vida de un objeto se extiende desde el momento en que se crea por primera vez (y consume espacio por primera vez) hasta que se destruye. Para crear un objeto hay que declararlo o bien asignarle memoria dinámicamente; generalmente esto se realiza con la ayuda de los métodos constructores y destructores mencionados anteriormente.
La declaración e inicialización de objetos consume memoria RAM, por lo que su administración es de suma importancia para garantizar el correcto funcionamiento del programa. Dependiendo del lenguaje de programación que utilicemos es posible que, para liberar memoria, una vez que un objeto deja de ser necesario, debamos destruirlo de forma explícita. En cambio, otros lenguajes de programación están provistos de herramientas que se encargan automáticamente de esta tarea, liberándonos de la responsabilidad de destruir los objetos.
En total existen tres tipos básicos de relaciones entre clases:
HERENCIA : Generalización/Especificación -> denota un tipo de relación “es un” o mejor aún, “se comporta
como”.
AGREGACIÓN: Todo/Parte -> denota una relación “parte de”.
ASOCIACIÓN: que denota alguna dependencia semántica entre clases de otro modo
independientes, muchas veces referenciada como hermano-hermano.
Las clases que heredan de otras clases heredan su comportamiento. Si una clase puede usar algo o todo el código que hereda, no necesita re-implementar esos métodos.
Una subclase puede redefinir un método de una superclase simplemente definiendo un método con el mismo nombre. El método en la subclase redefine y reemplaza al método de la superclase. Hay varias razones por la que puede ser útil redefinir un método la más común es: para especificar un comportamiento que depende de la subclase.
Toda redefinición debe conservar cantidad y tipo de parámetros y tipo de valor devuelto.
Se pueden redefinir métodos y valores por defecto para los atributos.
Ejemplo: polígono y rectángulo.
Son aspectos de una misma idea de herencia y frecuentemente son utilizados indistintamente.
A medida que la jerarquía de herencia evoluciona los atributos y métodos comunes tienden a migrar hacia las superclases comunes.
El nombre de un método puede implicar comportamientos diferentes, conforme esté especificado en clases diferentes, en tanto y en cuanto estas clases estén relacionadas por una superclase común.
Polimorfismo es la habilidad de dos o más objetos de responder a mensajes con igual nombre, cada uno de su propia forma.
El polimorfismo es la propiedad que potencia el uso de la herencia y para poder utilizarla, las clases deben especificar los comportamientos con los mismos protocolos.
Una asociación denota una dependencia semántica y puede establecer o no, la dirección de esta dependencia, conocida como navegabilidad. Si se establece la dirección de la dependencia o navegabilidad, debe nombrarse el rol que desempeña la clase en relación con la otra. Esto es suficiente durante el análisis de un problema, donde sólo es necesario identificar esas dependencias.
Multiplicidad: existen tres tipos habituales de multiplicidad en una asociación:
Uno a uno
Uno a muchos
Muchos a muchos
Contención por referencia: es un tipo menos directo de agregación, en este caso se pueden crear y destruir instancias de cada objeto en forma independiente.
No hay un estilo de programación que sea el mejor para todo tipo de aplicaciones.
Cada uno de estos estilos de programación se basa en su propio marco de referencia conceptual.
El modelo de objetos es el marco de referencia conceptual para evaluar si se respeta el paradigma orientado a objetos.
Hay cuatro elementos fundamentales en el modelo de objetos:
Abstracción
Encapsulamiento
Modularidad
Jerarquía
Al decir fundamentales, quiere decirse que un modelo que carezca de cualquiera de estos elementos no es orientado a objetos.
Por secundarios quiere decirse que cada uno de ellos es una parte útil del modelo de objetos, pero no esencial.
Una abstracción denota las características esenciales de un objeto, que lo distingue de todos los demás y proporciona así fronteras conceptuales nítidamente definidas respecto a la perspectiva del observador.
Una abstracción se centra en la visión externa de un objeto por lo tanto sirve para separar el comportamiento esencial de un objeto de su implementación. La decisión sobre el conjunto adecuado de abstracciones para determinado dominio es el problema central del diseño orientado a objetos.
El encapsulamiento oculta los detalles de implementación de un objeto.
El encapsulamiento es el proceso de almacenar en un mismo compartimento los elementos de una abstracción, que constituyen su estructura y su comportamiento; sirve para separar la interfaz contractual de una abstracción y su implementación.
Se llama a esos elementos encapsulados secretos de una abstracción.
El objetivo de fondo de la modularización es la reducción del costo del software al permitir que los módulos se diseñen y revisen independientemente. La estructura de un módulo debería:
Ser lo bastante simple como para ser comprendida en su totalidad
Ser posible cambiar la implantación de los módulos sin saber nada de los otros módulos y sin afectar su comportamiento.
Y la facilidad de realizar un cambio debería guardar una relación razonable con la probabilidad de que ese cambio fuese necesario.
Las dos jerarquías más importantes en un sistema complejo son
Su estructura de clases (la jerarquía <<de clases>>). Herencia.
Su estructura de partes (la jerarquía <<de partes>>). Agregación.
Los tipos son la puesta en vigor de la clase de objetos, de modo que los objetos de tipos distintos no pueden intercambiarse o, como mucho, pueden intercambiarse sólo de formas muy restringidas.
Un tipo es una caracterización precisa de propiedades estructurales o de comportamiento que comparten una serie de entidades.
La idea de congruencia es central a la noción de tipos. (ej. Las unidades de medida en física: al dividir distancia con tiempo, se espera algún valor que denote velocidad, no peso). Este es ejemplo de comprobación estricta de tipos, en los que las reglas del dominio dictan y refuerzan ciertas combinaciones correctas entre las abstracciones.
Existen varios beneficios importantes que se derivan del uso de lenguajes de tipos estrictos:
Sin la comprobación de tipos un lenguaje puede “estallar” de forma misteriosa en ejecución en la mayoría de los lenguajes.
En la mayoría de los sistemas, el ciclo editar-compilar-depurar es tan tedioso que la detección temprana de errores es indispensable.
La declaración de tipos ayuda a documentar programas.
La mayoría de los compiladores pueden generar código más eficiente si se han declarado los tipos.
Los lenguajes sin tipos ofrecen mayor flexibilidad, pero la seguridad que ofrecen los lenguajes con tipos estrictos suele compensar la flexibilidad que se pierde.
Un sistema automatizado puede tener que manejar muchos eventos diferentes simultáneamente. Para esos casos es útil considerar utilizar un conjunto de procesadores o procesadores que soporten la multitarea. Un solo proceso denominado hilo de control es la raíz a partir de la cual se realizan acciones dinámicas independientes dentro del sistema. Todo programa tiene al menos un hilo de control, pero un sistema que implique concurrencia puede tener muchos hilos: algunos son transitorios y otros permanentes.
Mientras que la Programación Orientada a Objetos (POO) se centra en la abstracción de datos, encapsulamiento y herencia, la concurrencia se centra en la abstracción de procesos y la sincronización. Cada objeto puede representar un hilo separado de control (una abstracción de un proceso). Tales objetos se llaman activos. En un sistema basado en diseño orientado a objetos, se puede conceptualizar al mundo con un conjunto de objetos cooperativos, algunos de los cuales son activos y sirven, así como centros de actividad independiente.
Hay que considerar como los objetos activos sincronizan sus actividades con otros
La persistencia es la propiedad de un objeto por la que su existencia trasciende el tiempo (es decir, el objeto continúa existiendo después de que su creador deja de existir) y/o el espacio (es decir, la posición del objeto varía con respecto al espacio de direcciones en el que fue creado).
Un objeto de software ocupa una cierta cantidad de espacio en memoria y existe durante cierta cantidad de tiempo. Este espectro de persistencia de objetos abarca lo siguiente:
Resultados transitorios en la evaluación de expresiones.
Variables locales en la activación de procedimientos.
Variables propias, variables locales y elementos del montículo cuya duración difiere de su
ámbito.
Datos que existen entre ejecuciones de un programa.
Datos que existen entre varias versiones de un programa.
Datos que sobreviven al programa.
Los lenguajes de programación tradicionales suelen tratar los tres primeros tipos de persistencia de objetos; la persistencia de los tres últimos tipos pertenece al dominio de la tecnología de bases de datos
Los lenguajes de programación son todos los símbolos,caracteres y reglas de uso que permiten a las personas "comunicarse" con las computadoras
Programación
Se diseña
Se codifica
Se escribe
Se prueba
Se depura
Código
Código Fuente
1957-1959
1970
1972
1983
1987
1991
1993
1995
Fortran,LISP,COBOL
PASCAL
C
C++, Objective-C
PERL
PYTHON
RUBY
JAVA - PHP - JavaScript
Tipos de lenguajes de programación
Nivel de Abstraccion del Procesador
El paradigma de Programación
Forma de Ejecución
Bajo nivel
Medio Nivel
Alto Nivel
Compilados
Interpretados
Imperativo
Declarativo
Estructurado
Orientado a objetos
Funcional
Lógico
1991 Lenguaje de programación de electrodomésticos
1995 Lenguaje de programación de computadoras
Orientado a objetos
Independiente de la plataforma
Compilado e Interpretado
Robusto
Gestiona la memoria automáticamente
No permite el uso de técnicas de programación inadecuada
Multihilos
Cliente-servidor
Con mecanismos de seguridad incorporados
Con herramientas de documentación incorporada
Case Sensitive: hay diferencia entre mayúscula y minúsculas
Cada instrucción termina con ;
Una instrucción puede abarcar mas de una línea
Se pueden dejar espacios y tabuladores
Se marcan bloques de código agrupado con "{}"
Es un algoritmo escrito en algún lenguaje de programación de computadoras.
Pasos para la construcción de un programa
DEFINICIÓN DEL PROBLEMA
ANÁLISIS DEL PROBLEMA
DISEÑO DEL ALGORITMO
CODIFICACIÓN
PRUEBA Y DEPURACIÓN
Los primeros lenguajes de programación no usaban objetos, solo variables. Una variable podríamos decir que es un espacio de la memoria RAM a la que asignamos un contenido.
Se puede almacenar distintos tipos de datos.
En base al tipo de datos seleccionado serán las operaciones que podamos realizar con esa variable, por ejemplo: si tenemos la variable edad deberíamos seleccionar un tipo de datos como integer (número entero) ya que las operaciones relacionadas serán de comparación, sumas o restas y no es necesario tener una profundidad de decimales.
Se declaran utilizando la palabra "final".
Si no se las declara static, ocupan lugar en memoria por cada instancia de la clase.
No se puede modificar su valor.
Por convención se las suele declarar en mayúscula.
Se inicia en el mismo momento de declararla.
La palabra final también puede aplicarse a clases, lo que indica que esa clase no puede ser heredada.
Entidades elementales: un número, un carácter, un valor verdadero o falso.
Un tipo primitivo es un dato elemental.
Tipo de Datos |
Significado |
Ejemplo Uso |
|---|---|---|
Byte |
Número entero de 8 bits. Con signo |
Temperatura de una habitación en grados Celsius |
Short |
Número entero de 16 bits. Con signo |
Edad de una Persona |
Int |
Número entero de 32 bits. Con signo |
Distancia entre localidades medida en metros |
Long |
Número entero de 64 bits. Con signo |
Producto entre dos distancias almacenadas en variables tipo int como la anterior |
Float |
Número Real de 32 bits |
Altura de algún objeto |
Double |
Número Real de 64 bits. |
Proporción entre dos magnitudes |
Boolean |
Valor lógico: true (verdadero) o false (falso) |
Almacenar si el usuario ha aprobado un examen o no |
Los objetos son entidades complejas que pueden estar formadas por la agrupación de muchas variables y métodos.
|
Tipos de la biblioteca estándar de Java |
String (cadenas de texto) Muchos otros (p.ej. Scanner, TreeSet, ArrayList…) |
|
Tipos definidos por el programador |
Cualquiera que se nos ocurra, por ejemplo Taxi, Autobus, Tranvia |
|
arrays |
Serie de elementos o formación tipo vector o matriz. |
|
Tipos envoltorio o wrapper (Equivalentes a los tipos primitivos pero como objetos.) |
Byte, Short, Integer, Long, Float, Double, Boolean |
|
|
Un objeto es una cosa distinta a un tipo primitivo, aunque “porten” la misma información. Tener siempre presente que los objetos en Java tienen un tipo de tratamiento y los tipos primitivos, otro. Que en un momento dado contengan la misma información no significa en ningún caso que sean lo mismo. El tipo primitivo es algo elemental y el objeto algo complejo.
Un tipo primitivo es un dato elemental y carece de métodos, mientras que un objeto es una entidad compleja y dispone de métodos.
Los nombres de tipos primitivos y envoltorio se parecen mucho.
Una cadena de caracteres es un objeto. El tipo String en Java nos permite crear objetos que contienen texto (palabras, frases, etc.). El texto debe ir siempre entre comillas.
Serie de elementos, cada uno de los cuales lleva asociado un índice numérico 0, 1, 2, 3, … , n-1
En java los arrays son objetos, instancias de la clase Array, la cual dispone de algunos métodos útiles.
Un array puede estar compuesto por datos primitivos o objetos.
int arrayDeEnteros[] = null;
Integer arrayDeEnteros2[] = null;Creación
Recorrido
Inicialización
Longitud
arrayDeEnteros = new int[100];
arrayDeEnteros2 = new Integer[100];for(int i = 0; i < 100; i++)
arrayDeEnteros[i] = i;int arrayDeEnteros[] = {1,2,3,4,5};
Integer arrayDeEnteros2 = {new Integer(10)};int arrayDeEnteros[] = {1,2,3,4,5};
int tamanio = arrayDeEnteros.length; //5Los programas de computadoras se apoyan esencialmente en la realización de numerosas operaciones aritméticas y matemáticas de diferente complejidad.
Los operadores son símbolos especiales que sirven para ejecutar una determinada operación, devolviendo el resultado de la misma.
Para comprender lo que es un operador, debemos primero introducir el concepto de Expresión. Una expresión es, normalmente, una ecuación matemática, tal como 3 + 5. En esta expresión, el símbolo más (+) es el operador de suma, y los números 3 y 5 se llaman operandos. En síntesis, una expresión es una secuencia de operaciones y operandos que especifica un cálculo.
Es el operador más simple que existe, se utiliza para asignar un valor a una variable o a una constante. El signo que representa la asignación es el = y este operador indica que el valor a la derecha del = será asignado a lo que está a la izquierda del mismo.
Ejemplo en pseudocódigo:
Entero edad = 20
Decimal precio = 25.45
Son operadores binarios (requieren siempre dos operandos) que realizan las operaciones aritméticas habituales:
Operador |
Significado |
|---|---|
+ |
Suma |
- |
Resta |
* |
Producto |
/ |
División |
% |
Resto de la División entera |
Los operadores unitarios requieren sólo un operando; que llevan a cabo diversas operaciones, tales como incrementar/decrementar un valor de a uno, negar una expresión, o invertir el valor de un booleano.
++ operador de incremento; incrementa un valor de a 1
int suma=20;
suma++;
suma=21
-- operador de decremento; Reduce un valor de a 1
int resta=20;
resta--;
resta=19
! operador de complemento lógico; invierte el valor de un valor booleano
boolean a=true;
boolean b= !a;
b=false
Son aquellos operadores que sirven para comparar valores. Siempre devuelven valores booleanos: TRUE O FALSE. Pueden ser Relacionales o Lógicos.
Relacionales
Lógicos
Los operadores relacionales sirven para realizar comparaciones de igualdad, desigualdad y relación de menor o mayor.
Operador |
Significado |
|---|---|
== |
Igual a |
!= |
No igual a |
> |
Mayor que |
>= |
Mayor o igual que |
< |
Menor que |
Los operadores lógicos (AND, OR y NOT), sirven para evaluar condiciones complejas
Expresión |
Operador |
Resultado |
|---|---|---|
a && b |
AND |
true: si a y b son verdaderos. |
a || b |
OR |
true: si a es verdadero, o si b es verdadero, o si a y b son verdaderos. |
Conocido como el if de una línea.
Permite devolver un valor u otro según el valor de la expresión analizada.
Expresión lógica ? valor si es verdadero : valor si es falso
Ej: valorPrecioLista = aplicaDescuento == true ? 123 : 234
Mostrar el texto "Hola Mundo" por la consola. Para ello utilizaremos la clase estática System.out. Esta clase nos permite acceder a la salida de la consola. En concreto usaremos el método println(texto).
https://docs.oracle.com/javase/8/docs/api/index.html
public class HolaMundo {
public static void main(String[] args) {
System.out.println("Hola Mundo");
}
}Vamos a crear un programa elemental para pedir datos por consola (entrada de teclado del usuario) y para ello vamos a basarnos en una clase del API de Java: la clase Scanner.
https://docs.oracle.com/javase/8/docs/api/index.html
import java.util.Scanner; //Importación del código de la clase Scanner desde la biblioteca Java
//Código de nuestra clase principal ejemplo aprenderaprogramar.com
public class TestPrograma1 {
public static void main (String [ ] args) {
System.out.println ("Empezamos el programa");
System.out.println ("Por favor introduzca una cadena por teclado:");
String entradaTeclado = "";
Scanner entradaEscaner = new Scanner (System.in); //Creación de un objeto Scanner
entradaTeclado = entradaEscaner.nextLine (); //Invocamos un método sobre un objeto Scanner
System.out.println ("Entrada recibida por teclado es: \"" + entradaTeclado +"\"");
} //Cierre del main
} //Cierre de la claseEl constructor que hemos utilizado dentro de los varios disponibles en la clase Scanner es el que tiene la signatura Scanner (InputStreamsource). Le pasamos como parámetro System.in.
Cuando sobre el objeto Scanner se invoca el método nextLine(), se obtiene un String que se corresponde con el texto que haya introducido el usuario mediante el teclado.
Este resultado del método lo almacenamos en la variable entradaTeclado. Finalmente, mostramos por pantalla cuál ha sido el contenido del texto recibido por teclado.
En la sentencia en que imprimimos el mensaje por pantalla hemos usado el carácter \. Este carácter, una barra invertida o backslash, no se muestra en pantalla y es interpretado por Java como indicación de que el siguiente carácter forma parte del texto. Esta es la forma que tenemos para incluir unas comillas en un texto que queramos mostrar por pantalla. Sin este escape, cualquier comilla se interpretaría como delimitadora de una cadena.
Otra aplicación del backslash es la de forzar un salto de línea. Hasta ahora hemos trabajado invocando el método println del objeto System.out para imprimir una línea en la ventana de consola. Cabe citar que otro método disponible para System.out es print, con el resultado de que tras un print no se inserta un cambio de línea y retorno de carro como ocurre con los println, por lo que los textos aparecen “uno a continuación de otro”.
Un programa puede ser escrito utilizando tres tipos de estructuras de control:
a) secuenciales
b) condicionales
c) repetitivas
Las Estructuras de Control determinan el orden en que deben ejecutarse las instrucciones de un algoritmo: si serán recorridas una luego de la otra, si habrá que tomar decisiones sobre si ejecutar o no alguna acción o si habrá repeticiones.
Es la estructura en donde una acción (instrucción) sigue a otra de manera secuencial. Las tareas se dan de tal forma que la salida de una es la entrada de la que sigue y así en lo sucesivo hasta cumplir con todo el proceso
Operación 1
Operación 2
Este es el caso cuando existe un número de posibles alternativas que resultan de la evaluación de una determinada condición.
En estas estructuras, se realiza una evaluación de una condición y de acuerdo al resultado, el algoritmo realiza una determinada acción. Las condiciones son especificadas utilizando expresiones lógicas.
Las estructuras selectivas/alternativas pueden ser:
● Bifurcación
● Selección múltiple
La estructura alternativa simple si-entonces (en inglés if-then) lleva a cabo una acción al cumplirse una determinada condición.
La selección si-entonces evalúa la condición y:
● Si la condición es verdadera, ejecuta la acción
● Si la condición es falsa, no ejecuta nada
if (condicion)
{
instruccion1();
instruccion2();
// etc
} else {
instruccion1();
instruccion2();
// etc
}
if (condificion) {
bloqueDeInstrucciones(); }if (condificion) {
bloqueDeInstrucciones();
}
else {
if(condicion2){
bloqueDeInstrucciones();
} else {
bloqueDeInstrucciones();
}
}Cada cláusula else corresponde al último if inmediato anterior que se haya ejecutado, es por eso que debemos tener especial consideración de encerrar correctamente entre llaves los bloques para determinar exactamente a qué cláusula corresponde. En este caso, es de especial utilidad indentar nuestro código utilizando espacios o tabulaciones como se muestra en el ejemplo anterior.
final int totalMaterias = 4;
int materiasAprobadas = 2;
if (materiasAprobadas == totalMaterias) {
otorgarCertificado();
}
else {
continuarCapacitacion();
}La condición debe ser una variable o expresión booleana.
Si sólo existe una instrucción en el bloque, las llaves no son necesarias.
No es necesario que exista un bloque else.
Se utiliza cuando existen más de dos alternativas para elegir. Esto podría solucionarse por medio de estructuras alternativas simples o dobles, anidadas o en cascada. Sin embargo, se pueden plantear serios problemas de escritura del algoritmo, de comprensión y de legibilidad, si el número de alternativas es grande.
En esta estructura, se evalúa una condición o expresión que puede tomar n valores. Según el valor que la expresión tenga en cada momento se ejecutan las acciones correspondientes al valor.
switch (expresion){
case valor1:
instrucciones();
break;
case valor2:
instrucciones();
break;
default:
instrucciones();
}La expresión ha de ser una variable de tipo int o una expresión que devuelva un valor entero.
Cuando se encuentra coincidencia con un case se ejecutan las instrucciones a él asociadas hasta encontrar el primer break.
Si no se encuentra ninguna coincidencia se ejecutan las instrucciones del bloque default, la cual es opcional.
El break no es exigido en la sintaxis y entonces si no se pone, el código se ejecuta atravesando todos los cases hasta que encuentra uno.
Es muy común, encontrarse con que una operación o conjunto de operaciones deben repetirse muchas veces.
Las estructuras que repiten una secuencia de instrucciones un número determinado de veces se denominan BUCLES. Y cada repetición del bucle se llama iteración.
Todo bucle tiene que llevar asociada una condición, que es la que va a determinar cuándo se repite el bucle y cuando deja de repetirse.
Bucles infinitos: cuando la condición de finalización del bucle no se llega a cumplir nunca. Se trata de un fallo muy típico, habitual.
Hay distintos tipos de bucles:
● Mientras, en inglés: While
● Hacer Mientras, en inglés: Do While.
● Para, en inglés: For
Esta estructura repetitiva “mientras”, es en la que el cuerpo del bucle se repite siempre que se cumpla una determinada condición
while(condicion){
accion();
}Esta estructura es muy similar a la anterior, sólo que a diferencia del while el contenido del bucle se ejecuta siempre al menos una vez, ya que la evaluación de la condición se encuentra al final. De esta forma garantizamos que las acciones dentro de este bucle sean llevadas a cabo, aunque sea una vez independientemente del valor de la condición
do {
acciones();
} while (condicion);
La estructura for es un poco más compleja que las anteriores y nos permite ejecutar un conjunto de acciones para cada elemento de una lista, o para cada paso de un conjunto de elementos. Su implementación depende del lenguaje de programación, pero en términos generales podemos identificar tres componentes: la inicialización, la condición de corte y el incremento.
for (inicio; condicion; incremento) {
accion();
}
Break: es válida tanto para las bifurcaciones como para los bucles. Hace que se salga inmediatamente del bucle o bloque que se está ejecutando sin finalizar el resto de las sentencias.
Continue: se utiliza en los bucles (no en bifurcaciones). Finaliza la iteración que en ese momento se está́ ejecutando (no ejecuta el resto de sentencias que hubiera hasta el final del cuerpo del bucle). Vuelve al comienzo del bucle y comienza la siguiente iteración si existiera.
public: accesibles desde cualquier clase.
private: sólo son accesibles por la clase actual.
protected: sólo por la clase actual, sus descendientes y clases de nuestro paquete.
<si no indicamos nada> sólo son accesibles por clases de nuestro paquete.
final, static y abstract
Toda variable tiene un ámbito. Esto es la parte del código en la que una variable se puede utilizar. De hecho, las variables tienen un ciclo de vida:
1. En la declaración se reserva el espacio necesario para que se puedan comenzar a utilizar (digamos que se avisa de su futura existencia).
2. Se la asigna su primer valor (la variable nace/inicialización).
3. Se la utiliza en diversas sentencias.
4. Cuando finaliza el bloque en el que fue declarada, la variable muere. Es decir, se libera el espacio que ocupa esa variable en memoria. No se la podrá volver a utilizar.
Una vez que la variable ha sido eliminada, no se puede utilizar. Dicho de otro modo, no se puede utilizar una variable más allá del bloque en el que ha sido definida.
El ámbito de las variables está determinado por el bloque de código donde se declaran y todos los bloques que estén anidados por debajo de este. Presta atención al siguiente fragmento de código:
{
// Aquí tengo el bloque externo
int entero = 1;
Punto unPunto = new Punto();
{
// Y aquı́ tengo el bloque interno
int entero = 2; // Error ya está declarada
unPunto = new Punto(1.0f, 1.0f); // Correcto
}
}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 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 matemat́ icas o al ejecutar sentencias de asignación en las que el miembro izquierdo tiene un tipo distinto que el resultado de evaluar el miembro derecho.
int a = 5;
float b = 1.5;
float c = a * b; // producto de distintos tipos de datos primitivos convertidos automáticamenteLas conversiones de un 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
long result;
result = (long) (a/(b+c));
Las rutinas son uno de los recursos más valiosos cuando se trabaja en programación ya que permiten que los programas sean más simples, debido a que el programa principal se compone de diferentes rutinas donde cada una de ellas realiza una tarea determinada.
Se la puede llamar desde cualquier parte del programa principal. Además, una rutina puede opcionalmente tener un valor de retorno y parámetros. El valor de retorno puede entenderse como el resultado de las instrucciones llevadas a cabo por la rutina
rutina: sumar(a, b)
valor de retorno: suma de los números a y b.
datos de entrada de la rutina : a y b
A estos datos de entrada los denominamos parámetros y a las rutinas que reciben parámetros las denominamos funciones, procedimientos o métodos, dependiendo del lenguaje de programación.
tipo_acceso public tipo_dinamico_o_no static tipo_dato void nombre_metodo calcularDescuento (tipo_parametro parametro) (float precio)
Un método es una estructura del lenguaje Java que nos sirve para encapsular cierta funcionalidad,
la cual podamos llamar desde diferentes sitios y así no tener que repetir el código.
Para la creación de un método en Java debemos conocer la estructura del mismo:
tipo_acceso
Un método generalmente usa toda esa estructura solo exceptuando la declaración de si es dinámico u estático. La primera parte de creación de un método se refiere a el tipo de acceso que puede ser:
tipo_dinamico_o_no
La segunda parte se refiere a el uso del método Java, si es estático lo cual significa que el método seria accesible desde fuera de la clase sin
necesidad de instanciar la clase.
static, el acceso al método es estático.
tipo_dato
El tipo de dato es dependiente de lo que se desea como resultado del método como puede ser por ejemplo void si nuestro método no tiene salida alguna, o un tipo de dato especifico como puede ser double o int si es una salida de tipo numérico.
El nombre de metodo de preferencia debe ser escrito en notacion camelCase por ejm: (la notación camel case detalla que se debe usar en los métodos con nombres compuestos siempre la primera letra de cada palabra en mayúscula)
Para la creación del método no en todos los casos es necesario argumentos pero si deseamos usar algún argumento, cada argumento deberá tener su tipo de dato y nombre de argumento.
[public] [final | abstract] class NombreDeLaClase [extends ClaseMadre] [implements Interfase1 [, Interfase2 ]...] Donde las porciones encerradas entre corchetes son opcionales a optar entre las posibilidades separadas por la barra vertical.
Como se ve, lo único obligatorio es la palabra reservada class y el nombre que queramos asignar a la clase. Las interfaces son un caso de tipo particular que veremos más adelante.
De esta forma una instancia (objeto) de la clase Perro puede declararse utilizando el operador new de la siguiente forma, ocupando un espacio en memoria que luego podrá ser accedido mediante el nombre miPerro.
public class Alumno {
//código
}Alumno alumno1 = new Alumno();Encapsulamiento: Las clases pueden ser declaradas como públicas (public) y como paquete (default) (accesibles sólo para otras clases del mismo paquete). Las variables miembros y los métodos pueden ser public, private, protected o default. De esta forma se puede controlar el acceso entre objetos y evitar un uso inadecuado.
Herencia: Una clase puede derivar de otra (extends), y en ese caso hereda todas sus variables y métodos. Una clase derivada puede añadir nuevas variables y métodos y/o redefinir las variables y métodos heredados.
Polimorfismo: Los objetos de distintas clases pertenecientes a una misma jerarquía o que implementan una misma interface, pueden responder de forma indistinta a un mismo método. Esto, como se ha visto anteriormente, facilita la programación y el mantenimiento del código.
Una clase es una agrupación de datos (variables o campos) y de funciones (métodos) que operan sobre esos datos. Todos los métodos y variables deben ser definidos dentro del bloque {...} de la clase.
Un objeto (en inglés instance) es un ejemplar concreto de una clase. Las clases son como tipos de variables, mientras que los objetos son como variables concretas de un tipo determinado.
NombreDeLaClase unObjeto;
NombreDeLaClase otroObjeto;Objeto: entidad que dispone de unas propiedades (atributos) y comportamiento (métodos).
Clase: define un tipo de objeto concreto.
Todas las variables y métodos de Java deben pertenecer a una clase. No hay variables y funciones globales.
Si una clase deriva de otra (extends), hereda todas sus variables y métodos.
Toda clase definida por el programador es heredada de la clase Object definida por el lenguaje de programación.
Una clase sólo puede heredar de una única clase (en Java no hay herencia múltiple). Si al definir una clase no se especifica de qué clase deriva, por defecto la clase deriva de Object.
En un archivo de código fuente se pueden definir varias clases, pero en un mismo archivo no puede haber más que una clase definida como public. Este archivo se debe llamar como la clase public que debe tener extensión .java.
8. Los métodos y variables de una clase pueden referirse de modo global a un objeto de esa clase a la que se aplican por medio de la referencia this. Al utilizar la palabra reservada 'this' para referirse tanto a métodos como atributos se restringe el ámbito al objeto que hace la declaración.
9. Las clases se pueden agrupar en packages que significa paquetes, introduciendo una línea al comienzo del fichero (package packageName;). Esta agrupación en packages está relacionada con la jerarquía de carpetas y archivos en la que se guardan las clases.
En la práctica usamos paquetes para agrupar clases con un mismo propósito usando jerarquía de paquetes; esta decisión es muy importante a la hora de diseñar la estructura de nuestro programa.
Atributos: (o campos/propiedades) Almacenan algún tipo de información del objeto. Definen su estado.
Constructor(es): Método que se utiliza para inicializar un objeto.
Métodos: Son utilizados para modificar o consultar el estado de un objeto. Equivalentes a las funciones o procedimientos de otros lenguajes.
Cada objeto, es decir cada instancia concreta de una clase, tiene su propia copia de las variables miembro. Las variables miembros de una clase (también llamadas atributos) pueden ser de tipos primitivos (boolean, int, long, double, ...) o referencias a objetos de otra clase (agregación y composición).
Visibilidad: indican la visibilidad, es decir, si se puede tener acceso sólo desde la clase (private), desde la clase y las clases que heredan de ella (protected) y desde cualquier clase definida en el mismo paquete o desde cualquier clase (public).
Modificador:
Atributo Estático: no existe una copia de este atributo en cada instancia de la clase, si no que existe uno único común a todas las instancias. A los atributos static también se les llama atributos de clase.
Atributo Final: no se puede cambiar su valor una vez definido.
Tipo de dato: este puede ser un tipo primitivo o de tipo objeto
public static final float E = 2.8182f;
[visibilidad] [modificadores] <tipo> <atributo> [= valor];
Se declaran utilizando la palabra static.
Son las "variables de clase". Pertenece a una clase y no a ningún objeto en particular.
Ocupan un solo lugar en memoria por más que se generen muchas instancias.
Deben declararse en la cabecera de la clase.
Aún cuando no existieran instancias de esa clase en memoria, el campo static estaría presente.
La palabra static no puede aplicarse a una clase.
Se suelen utilizar para definir constantes comunes para todos los objetos de la clase (por ejemplo, PI en la clase Circulo) o variables que sólo tienen sentido para toda la clase (por ejemplo, un contador de objetos creados como numCirculos en la clase Circulo)
Para llamarlas se suele utilizar el nombre de la clase (no es imprescindible, pues se puede utilizar también el nombre de cualquier objeto), porque de esta forma su sentido queda más claro. Por ejemplo, Circulo.numCirculos.
Se declaran utilizando la palabra "final".
Si no se las declara static, ocupan lugar en memoria por cada instancia de la clase.
No se puede modificar su valor.
Por convención se las suele declarar en mayúscula.
Se inicia en el mismo momento de declararla.
La palabra final también puede aplicarse a clases, lo que indica que esa clase no puede ser heredada.
Los métodos especifican el comportamiento de la clase y sus instancias. Los modificadores de acceso y su significado son los mismos que al operar sobre atributos:
Método estático: implica que es un método de la clase, y por lo tanto no es necesario crear ninguna instancia de la clase para poder llamarlo.
Método final: implica que no se puede redefinir en ninguna clase que herede de esta, pero es importante destacar que el cuerpo de un método definido como final no podrá ser modificado por ninguna clase hijo.
En el momento de la declaración hay que indicar cuál es el tipo del parámetro que devolverá́ el método o void en caso de que no devuelva nada. En otros lenguajes, estos tipos de métodos o funciones se denominan procedimientos.
Los métodos tienen visibilidad directa de sus atributos; es decir, pueden acceder a ellos sin cualificarlas con un nombre de objeto y el operador punto (.). De todas formas, también se puede acceder a ellas mediante la referencia this.
Los métodos pueden definir variables locales. Su visibilidad llega desde la definición al final del bloque en el que han sido definidas. No hace falta inicializar las variables locales en el punto en que se definen, pero el compilador no permite utilizarlas sin haberles dado un valor. A diferencia de los atributos, las variables locales no se inicializan por defecto.
Hay que especificar el tipo y nombre de cada uno de los argumentos del método entre paréntesis. Si un método no tiene argumentos el paréntesis queda vacío, no es necesario escribir void. El tipo y número de estos argumentos identifican al método, ya que varios métodos pueden tener el mismo nombre, con independencia del tipo devuelto, y se distinguirán entre sí por el número y tipo de sus argumentos.
Clase Alumno con dos atributos de tipo cadena de texto: nombre y apellido. Es importante destacar que estos atributos son definidos como privados para poder respetar el principio de encapsulamiento del paradigma orientado a objetos y lo tomaremos como una buena práctica: los atributos de un objeto deberían ser accesibles sólo a través de métodos públicos.
Además hemos definido el método público getNombreCompleto() que no recibe parámetros y devuelve una cadena de texto formada por el nombre y el apellido del alumno separados por un espacio.
Es importante destacar que para acceder a los atributos de la instancia de esta clase puede usarse o no la palabra reservada this ya que en el cuerpo del método no existe otra variable local con el mismo nombre que pueda resultar en ambigüedad.
public class Alumno {
private String nombre;
private String apellido;
public String getNombreCompleto () {
return nombre + “ ” + this.apellido;
}
}Tipos primitivos: se pasan siempre por valor. El método recibe una copia del argumento actual; si se modifica esta copia, el argumento original que se incluyó́ en la llamada no queda modificado. Para modificar un argumento de un tipo primitivo dentro del cuerpo del método puede incluirse como variable miembro o ser retornado para luego realizar la asignación en el momento de la llamada.
Tipos de dato objeto: se pasan también por valor, pero a través de ellas se pueden modificar los objetos referenciados.
Da lugar al inicio del programa y será llamado por la máquina virtual al momento de la ejecución.
El método main() no es el elemento principal del programa. El objetivo de este método normalmente es iniciar el programa delegar el comportamiento a los distintos los objetos correspondientes.
Este método debe pertenecer a una clase pública y su definición es la siguiente:
public static void main(String[] args) {
// cuerpo de nuestro programa }
Es estático ya que no depende de una instancia en particular de la clase en la que se declara y no tiene ningún valor de retorno.
Recibe un array de parámetros de tipo String que representan los argumentos pasados a la hora de ejecutar el programa. En el caso de realizar la ejecución mediante la línea de comando, cada elemento del array será una cada cadena de texto luego de la llamada a nuestro programa, separadas por espacios.
Para poder respetar el principio de encapsulamiento de la orientación a objetos, cada atributo de la clase debería ser definido como privado y existir métodos get y set para poder obtener y modificar sus valores.
public TipoDeDatos getAtributo () {
return this.atributo;
}public void setAtributo (TipoDeDatos nuevoValor) {
this.atributo = nuevoValor;
}Donde TipoDeDatos puede ser tanto un tipo primitivo como una clase o interfaz si estamos referenciando a otros objetos. Otro punto importante es que por convención el nombre del método luego del prefijo get o set normalmente se escribe en CamelCase como mencionamos en el módulo anterior a la hora de nombrar variables.
Se puede modificar la implementación interna sin afectar ningún código, salvo el de los métodos de clase.
Ejemplo: si el almacenamiento de nombre pasa a ser nombrePila y apellido, entonces en el método getNombre se puede modificar para que proporcione nombrePila+" "+apellido.
Los métodos de set pueden efectuar una comprobación de errores, mientras que los de get no sería necesario.
Si un campo es public y el valor es incorrecto, el culpable de estropear el valor podría haber estado en cualquier lugar. Con private, solamente sería necesario depurar ese método.
Ver: http://programmers.stackexchange.com/questions/143736/why-do-we-need-private-variables
public class Alumno {
private String nombre; private String apellido;
public String getNombre () {
return this.nombre;
}
public void setNombre (String nombre) {
this.nombre = nombre;
}
public String getApellido () {
return this.apellido;
}
public void setApellido (String apellido) {
this.apellido = apellido;
}
public String getNombreCompleto () {
return this.nombre + “ ” + this.apellido;
}
}Alumno alumno1 = new Alumno();
alumno1.setNombre(“Pablo”);
alumno1.setApellido(“Filippo”);
Alumno alumno2 = new Alumno();
alumno2.setNombre(“Florencia”);
alumno2.setApellido(“Venne”);
System.out.println(“Nombre del alumno 1: ” + alumno1.getNombreCompleto());
System.out.println(“Nombre del alumno 2: ” + alumno2.getNombreCompleto());Java permite métodos sobrecargados (overloaded), es decir métodos distintos con el mismo nombre que se diferencian por el número y/o tipo de datos de los argumentos.
A la hora de llamar a un método sobrecargado, Java sigue unas reglas para determinar el método concreto que debe llamar:
Si existe el método cuyos argumentos se ajustan exactamente al tipo de los argumentos de la llamada (argumentos actuales), se llama ese método.
Si no existe un método que se ajuste exactamente, se intenta promover los argumentos actuales al tipo inmediatamente superior (por ejemplo char a int, int a long, float a double, etc.) y se llama el método correspondiente.
El valor de retorno no influye en la elección del método sobrecargado. En realidad, es imposible saber desde el propio método lo que se va a hacer con él. No es posible crear dos métodos sobrecargados, es decir con el mismo nombre, que sólo difieran en el valor de retorno.
public class Alumno
{
private String nombre;
private String apellido;
// se omiten los métodos get y set por simplicidad
public String getNombreCompleto (String titulo) {
return titulo + “ ” + this.nombre + “ ” + this.apellido;
}
public String getNombreCompleto () {
return this.getNombreCompleto(“Sr/a.”);
// usamos un título por defecto para cuando no se especifica por parámetros
}
}System.out.println(“Nombre del alumno 1: ” + alumno1.getNombreCompleto());
// muestra en pantalla “Sr/a. Pablo Filippo”
System.out.println(“Nombre del alumno 2: ” + alumno2.getNombreCompleto(“Contadora.”));
// muestra en pantalla “Contadora. Paula Filippi”Una clase puede redefinir (override) un método heredado de una superclase. Redefinir un método es dar una nueva definición. En este caso el método debe tener exactamente los mismos argumentos en tipo y número que el método redefinido.
Los métodos que tienen el mismo nombre que la clase tienen un comportamiento especial, sirven para crear las instancias de la clase y se les denomina constructores. Un constructor es un operador que se llama automáticamente cada vez que se crea un objeto de una clase. La principal misión del constructor es reservar memoria e inicializar los atributos de la clase.
Se ejecuta cuando se instancian objetos de la clase.
Los constructores siempre se invocan mediante el operador new.
Los constructores no tienen valor de retorno (ni siquiera void) y su nombre es el mismo que el de la clase.
Su argumento implícito es el objeto que se está creando.
Si no se define explícitamente un constructor, Java lo hará por nosotros ya que siempre es necesario que exista. Se creará un constructor sin argumentos.
Una clase puede tener varios constructores, que se diferencian por el tipo y número de sus argumentos (los constructores justamente son un ejemplo típico de métodos sobrecargados
que vimos anteriormente).
Si es necesario que un constructor llame a otro constructor lo debe hacer antes que cualquier otra cosa.
Se llama constructor por defecto al constructor que no tiene argumentos. El programador debe proporcionar en el código, valores iniciales adecuados para todas las variables miembro.
En caso de que sólo definamos un constructor con parámetros el constructor por defecto no será creado por Java, por lo que deberemos definirlo explícitamente en caso de ser necesario.
Al igual que los demás métodos de una clase, los constructores pueden tener también los modificadores de acceso public, private, protected y default. Si un constructor es private, ninguna otra clase puede crear un objeto de esa clase. En este caso, puede haber métodos public y static (factory methods) que llamen al constructor y devuelvan un objeto de esa clase.
Dentro de una clase, los constructores sólo pueden ser llamados por otros constructores o por métodos static. No pueden ser llamados por los métodos de objeto de la clase.
public class Alumno
{
private String nombre;
private String apellido;
public Alumno (){}
public Alumno (String nombre, String apellido) {
this.nombre = nombre; this.apellido = apellido;
}
// se omiten los métodos get y set por simplicidad
}Alumno alumno1 = new Alumno(“Pablo”, “Filippo”);
Alumno alumno2 = new Alumno(“Florencia”, “Venne”);Un package es una agrupación de clases que sirve para establecer una jerarquía lógica en la organización de las clases.
Además, tiene una relación directa con la organización física de nuestro código ya que también se representa en la estructura de archivos y carpetas que conforman nuestro programa.
Todas las clases dentro de un mismo paquete tienen acceso al resto de clases declaradas como públicas.
Para poder acceder a una clase de otro paquete se ha de importar anteriormente mediante la sentencia import.
Para que una clase pase a formar parte de un package llamado nombreDelPaquete, hay que introducir en ella la sentencia:
package nombreDePaquete;
Debe ser la primera sentencia del archivo 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 un 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 la misma carpeta.
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). 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 java.lang 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 poo.cine.Actor;
import poo.cine.*;
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. Éstos deben ser importados explícitamente, pues en realidad son packages distintos. Por ejemplo, al importar java.awt no se importa java.awt.event.
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 (se acabó si scope), porque a la referencia se le ha asignado el valor null 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). Para que estos objetos “desreferenciados” no ocupen memoria, un recolector de basura se encarga de «destruirlos» y liberar la memoria que estaban ocupando. Por lo tanto, para «destruir» un objeto basta con asignar a su variable de referencia el valor null.
Punto unPunto = new Punto(1.0f, 2.0f);
Punto otroPunto = new Punto(1.0f, -1.0f);
unPunto = new Punto(2.0, 2.0f); // El punto (1.0f, 2.0f) se pierde
otroPunto = null; // El punto (1.0f, -1.0f) se pierde
Los usuarios esperan que los programas se comporten de forma sensata cuando se producen errores. Si no es posible terminar una operación por causa de error el programa debería:
volver a un estado seguro y permitir al usuario que ejecute otras órdenes o bien
permitir al usuario guardar su trabajo y salir ordenadamente del programa.
Errores debidos a entradas de usuario
Errores de dispositivos
Limitaciones físicas
Errores en el código
La jerarquía se divide en dos ramas: Error y Exception
Error: describe errores internos y el agotamiento de recursos dentro del sistema de ejecución de java. Nosotros no debemos lanzar objetos de este tipo.
Exception: se divide en dos ramas
RuntimeException: se producen porque hemos cometido un error de programación.
Otras: se producen porque a nuestro programa, que es correcto, le ha ocurrido algo malo, como un error de E/S.

Ejemplos de causas de RuntimeException:
Casteos incorrectos
Accesos a índices matriciales fuera de límites.
Accesos a punteros null.
Ejemplos de causas de excepciones que no heredan de RuntimeException:
Intentar abrir un archivo que no existe.
Intentar abrir una URL mal formada.
Excepciones no comprobadas: todas las que derivan de la clase Error o de la clase RuntimeException.
Excepciones comprobadas: todas las demás.
El compilador verifica que nosotros proporcionemos manejadores de excepciones para todas las excepciones comprobadas.
Cualquier método que lance una excepción comprobada es una trampa en potencia. Si no hay ningún manejador que capture la excepción, el hilo de ejecución actual llegará a su fin.
No es necesario manejar los errores internos de java, esto es las excepciones que se deriven de Error.
No se deben manejar las excepciones sin comprobación que se deriven de RuntimeException. Estos errores están totalmente bajo nuestro control. Deberíamos dedicar tiempo suficiente a corregirlos y no lanzar una excepción.
Los métodos deben declarar todas las excepciones comprobadas. Si nuestro método no declara todas las excepciones comprobadas, el compilador emitirá un mensaje de error.
Las excepciones no comprobadas están fuera de nuestro control o bien son el resultado de situaciones que no deberíamos haber permitido desde un principio.
Para capturar una excepción, se configura un bloque del tipo try/catch. La forma más sencilla del bloque try es la siguiente:
try
{
...
}
catch (TipoDeExcepcion e)
{
// manejador para este tipo de excepcion
}Si cualquier parte del código situado dentro del bloque try lanza una excepción de la clase especificada en el catch entonces:
El programa salta el resto del código que haya en el bloque try.
El programa ejecuta el código del manejador situado dentro de la clase catch.
Si no hay parte del código situado dentro del bloque try que lance una excepción, entonces el programa salta la cláusula catch.
Si alguna parte del código lanza una excepción de tipo distinto a la mencionada en el catch este método finaliza inmediatamente.
public void read(String nombrefichero)
{
try
{
InputStream in = new FileInputStream(nombrefichero);
int b:
while ((b = in.read()) !+ -1)
{
//procesar entrada
}
}
catch(IOException e)
{
e.printStackTrace();
}
}Con frecuencia, la mejor opción consiste en no hacer nada y limitarse a pasar la excepción a quien hiciera la llamada. Si se produce este error que se ocupe quien hizo la llamada al método.
public void read(String nombrefichero) throws IOException
{
InputStream in = new FileInputStream(nombrefichero);
int b:
while ((b = in.read()) !+ -1)
{
//procesar entrada
}
}Debemos capturar las excepciones que debemos manejar y notificar la existencia (pasar la excepción) de aquellas que no sepamos manejar.
Cuando se notifica la existencia de una excepción es preciso añadir el throws.
Las excepciones solo deben utilizarse para situaciones excepcionales.
if(!s.empty()) s.pop();try
{
s.pop();
}
catch(EmptyStackException e)
{
}OutputStream out;
Stack s;
for(i=0; i<100;i++)
{
try
{
n=s.pop();
}
catch (EmptyStackException s)
{
//la pila esta vacía
}
try
{
out.writeInt(n);
}
catch(IOException e)
{
//hay un problema al escribir el archivo
}
}OutputStream out;
Stack s;
try
{
for(i=0; i<100;i++)
{
n=s.pop();
out.writeInt(n);
}
}
catch (EmptyStackException s)
{
//la pila esta vacía
}
catch(IOException e)
{
//hay un problema al escribir el archivo
}public Image cargarImagen(String s)
{
try
{
//código que amenaza con lanzar excepciones comprobadas
}
catch(Exception e)
{
}//y arreglado ?????
}Los métodos de nivel superior suelen estar mejor equipados para notificar al usuario la existencia de errores o para abandonar órdenes que no han tenido éxito.
public void readStuff(String nombreFichero) throws IOException //esto es válido
{
InputStream in = new FileInputStream(nombreFichero);
...
}La Herencia define relaciones del tipo “es un” como, por ejemplo “un Alumno es una Persona” por lo que comparte tanto sus atributos como nombre, apellido, dni y su comportamiento, así como tiene sus propios atributos como las materias a las que está inscripto, cuáles ha rendido, entre otras.
Mediante el uso de la herencia las clases pueden extender el comportamiento de otra clase permitiendo con ello un gran aprovechamiento del código.
Una clase se dice que hereda o extiende a otra clase antecesora. La palabra reservada extends sirve para indicar que una clase extiende a otra. La clase que extiende a otra, hereda todos los atributos y métodos de la clase antecesora, los atributos y métodos privados no tienen visibilidad. La clase antecesora puede extender a su vez otra clase.
Todas las clases de Java creadas por el programador tienen una superclase. Cuando no se indica explícitamente una superclase 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.
Se utiliza la palabra reservada extends.
Una clase puede extender de una clase concreta o una clase abstracta.
Una clase solo puede heredar una superclase. Java no admite herencia múltiple.
Java permite múltiples niveles de herencia
Al extender una clase
se heredan todas las operaciones del padre
se puede añadir nuevas operaciones
La nueva clase puede elegir para las operaciones heredadas:
redefinir la operación: se vuelve a escribir
la nueva operación puede usar la del padre y hacer más cosas (super)
puede ser totalmente diferente
dejarla como está: no hacer nada
Persona.java
public class Persona {
private String nombre; private String apellido; private String dni;
public String getNombreCompleto () {
return this.nombre + “ ” + this.apellido;
}
// ...
}
Alumno.java
public class Alumno extends Persona {
private int legajo;
private Materia[] materiasInscriptas; private Materia[] materiasRendidas;
// ...
}Una clase puede redefinir (volver a definir) cualquiera de los métodos heredados de su superclase que no sean final. El nuevo método sustituye al heredado para todos los efectos en la clase que lo ha redefinido.
Una clase que extiende a otra puede declarar atributos con el mismo nombre que algún atributo de la clase a la que extiende; se dice que el atributo se ha sobrescrito u ocultado.
Los 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.
Un método declarado static en una clase antecesora puede sobrescribirse en una clase que la extienda, pero también se debe declarar static; de lo contrario se producirá́ un error en tiempo de compilación.
public class Alumno extends Persona { private int legajo;
private Materia[] materiasInscriptas;
private Materia[] materiasRendidas;
public String getNombreCompleto () {
return this.legajo + “: ” + super.getNombreCompleto();
}
// ...
}Otro ejemplo puede ser el de las Cuentas Bancarias, donde nuestra clase CuentaBancaria es heredada por CuentaCorriente y CajaDeAhorro. De esta forma la clase heredad contiene el atributo saldo que es común a ambos tipos de cuenta y define ciertos métodos también comunes como depositar() y extraer() que reciben un monto como parámetros. Al ser conocida por nosotros la interfaz de la clase CuentaBancaria podríamos acceder a estos métodos comunes sin conocer explícitamente la clase que la hereda, esto se conoce como Polimorfismo.
CuentaBancaria miCuenta = new CajaDeAhorros();
// realizamos una extracción usando el objeto miCuenta
// cuyo tipo de datos fue definido como CuentaBancaria
miCuenta.extraer(100);
CuentaBancaria miOtraCuenta = new CuentaCorriente();
// realizamos una extracción usando el objeto miOtraCuenta
// cuyo tipo de datos fue definido como CuentaBancaria
// aunque es una instancia de CuentaCorriente
miOtraCuenta.extraer(100);Las clases abstract funcionan como plantillas para la creación de otras clases, son clases de las que no 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 { ... }
No se puede instanciar.
Puede contenter métodos abstractos y métodos concretos.
Se utiliza cuando no es necesario instanciar objetos de una clase. Por ejemplo: si tenemos dos clases ProfesorInterino y ProfesorTitular, ambas heredan de Profesor. Pero si todas las instancias de Profesor corresponderán a uno de los dos tipos, no sería necesario nunca instanciar Profesor.
Un método se puede declarar como abstract. Un método declarado de esta manera no implementa nada. Si una clase contiene uno o más métodos declarados como abstract, ella a su vez debe ser declarada como abstract. Las clases que la extiendan deben obligatoriamente sobrescribir los métodos declarados como abstract o la clase también debe declararse abstract.
No tiene cuerpo, solo se declaran.
La signatura termina con ; .
Solo pueden existir en una clase abstracta.
Deben estar obligatoriamente sobreescritos en la subclase. Si no se sobreescriben, la subclase tendría un método abstracto por lo tanto seriía una clase abstracta.
El polimorfismo en Java consiste en dos propiedades:
Empleado e;
e = new Empleado(...);
e = new Administrador(...);
Empleado e1;
e1 = new Secretaria(...);e.calcularSueldo();
e1.calcularSueldo();Así como la Herencia representa relaciones del tipo “es un”, las interfaces nos permiten representar relaciones “se comporta como un”.
El concepto de la implementación de interfaces garantiza que objetos de una Clase que implemente esa interfaz tendrán disponibles ciertos métodos definidos. Es en este punto que entra el concepto de Polimorfismo, ya que cualquier objeto independientemente de su clase que implemente una interfaz determinada podrá responder ante la llamada a esos métodos definidos.
Las interfaces permiten “publicar” el comportamiento de una clase develando un mínimo de información.
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 retorno o como argumento de un método.
En la interface no se implementa el comportamiento, únicamente se especifica cuál va a ser, es decir, se definirán los métodos, pero no se implementan. No se pueden crear instancias de una interface. Todos los métodos declarados en una interface son públicos, así́ como sus atributos y la misma interface.
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 superclase en el caso de herencia.
Se utilizan las palabras reservadas interface y implements.
Conjunto de directrices, las cuales las clases que la implentan deben cumplir.
Si una clase cumple con las especificaciones de una interfaz la puede implementar.
No se instancian.
Solo tienen métodos public y abstract. Si no se aclara se toman por defecto public.
Ejemplo: interfaz List -> la implementan ArrayList, LinkedList, Stack, etc.
public interface DiagramadorDeTorneo {
public List<Partidos> diagramar (List<Equipos> equipos, Date fechaInicio);
}
public class TodosContraTodos implements DiagramadorDeTorneo {
public List<Partidos> diagramar (List<Equipos> equipos, Date fechaInicio) {
// acá irá el código que genera los partidos con la combinación de todos los equipos
}
}
public class PorEliminatorias implements DiagramadorDeTorneo {
public List<Partidos> diagramar (List<Equipos> equipos, Date fechaInicio) {
// acá irá el código que genera los partidos con llaves de eliminatorias
}
}Pueden crecer o acortarse según se lo requiera.
Existen varias formas de implementar una lista en Java.
Una lista es una secuencia de elementos dispuesto en un cierto orden, en la que cada elemento tiene como mucho un predecesor y un sucesor.
El número de elementos de la lista no suele estar fijado, ni suele estar limitado por anticipado.
La estructura de datos deberá permitirnos determinar cuál es el primer elemento y el último de la estructura, cuál es su predecesor y su sucesor (si existen de cualquier elemento dado).
Cada uno de los elementos de información suele denominarse nodo.
List<Jugador> jugadores;
De esta forma la lista jugadores sólo podrá estar compuesta por elementos que sean instancias de la clase Jugador.
A continuación, veremos las siguientes clases que implementan esta interfaz:
● ArrayList
● Stack
public class Jugador {
private String nombre;
private String apellido;
private int edad;
public Jugador (nombre, apellido, edad) {
this.nombre = nombre;
this.apellido = apellido;
this.edad = edad;
}
}// creamos los jugadores con sus edades
Jugador j1 = new Jugador(“Miguel”, “Houllebecq”, 21);
Jugador j2 = new Jugador(“Pablo”, “Auster”, 19);
Jugador j3 = new Jugador(“Aldo”, “Huxley”, 23);
Jugador j4 = new Jugador(“Alejandro”, “Baricco”, 21);
// inicializamos la variable acumuladora de promedios
float promedio = 0;
// inicializamos la lista de jugadores
// se especifica el tipo de datos de elementos de la lista
// entre (< y >) para evitar insertar otro de datos
List<Jugador> jugadores = new ArrayList<Jugador>();
// agregamos un elemento a la lista con el método add()
jugadores.add (j1);
jugadores.add (j2);
jugadores.add (j3);
jugadores.add (j4);
// obtenemos un objeto Iterador que nos permita recorrer la lista
Iterator<Jugador> iter = jugadores.iterator();
// mientras exista un elemento siguiente por recorrer
while (iter.hasNext()) {
// obtenemos el Jugador siendo recorrido
Jugador j = iter.next();
// acumulamos su edad promedio sobre el total de jugadores
// que obtenemos con el método size() de la lista
promedio += j.getEdad() / jugadores.size();
}
// mostramos el resultado en pantalla
System.out.println(“Promedio: ” + promedio);|
|
|
boolean add(E e) void add(int index, E element) boolean addAll(Collection<? extends E> c) boolean addAll(int index, Collection<? extends E> c) void clear() boolean contains(Object o)
|
|
void ensureCapacity(int minCapacity) E get(int index) int indexOf(Object o) boolean isEmpty() Iterator<E> iterator() E remove(int index) Elimina el elemento de la posición especificada boolean remove(Object o)
|
E set(int index, E element)
Reemplaza el elemento en la posición especificada
int size()
Devuelve el tamaño de la lista
// creamos los jugadores con sus edades
Jugador j1 = new Jugador(“Miguel”, “Houllebecq”, 21);
Jugador j2 = new Jugador(“Pablo”, “Auster”, 19);
Jugador j3 = new Jugador(“Aldo”, “Huxley”, 23);
Jugador j4 = new Jugador(“Alejandro”, “Baricco”, 21);
// inicializamos la pila de jugadores
Stack<Jugador> pila = new Stack<Jugador>();
// agregamos un elemento a la lista con el método push()
pila.push (j1);
pila.push (j2);
pila.push (j3);
pila.push (j4);
// mientras existan elementos por extraer
while (!pila.empty()) {
// mostramos el nombre del jugador en pantalla
System.out.println (pila.pop().getNombreCompleto());
}boolean empty()
Devuelve true si la pila está vacía
E peek()
Consultamos el primer elemento de la pila sin extraerlo
E pop()
Extraemos el primer elemento de la pila
E push(E item)
Colocamos un elemento en el tope de la pila
int search(Object o)
Devuelve la posición del elemento en la pila (basado en 1)
UML son las siglas para Unified Modeling Language, que en castellano quiere decir: Lenguaje de Modelado Unificado. Es un lenguaje de modelado, de propósito general, usado para la visualización, especificación, construcción y documentación de sistemas Orientados a Objetos.
Lenguaje: el UML es, precisamente, un lenguaje, lo que implica que éste cuenta con una sintaxis y una semántica. Por lo tanto, al modelar un concepto en UML, existen reglas sobre cómo deben agruparse los elementos del lenguaje y el significado de esta agrupación.
Modelado: el UML es visual. Mediante su sintaxis se modelan distintos aspectos del mundo real, que permiten una mejor interpretación y entendimiento de éste.
Unificado: unifica varias técnicas de modelado en una única.
Las raíces del UML provienen de tres métodos distintos: el método de Grady Booch, la Técnica de Modelado de Objetos de James Rumbaugh y “Objetory”, de Ivar Jacobson. Estas tres personalidades son conocidas como “los tres amigos”
En 1994 Booch, Rumbaugh y Jacobson dieron forma a la primera versión del UML y en 1997 fue aceptado por la OMG, fecha en la que fue lanzada la versión v1.1 del UML. Desde entonces, UML atravesó varias revisiones y refinamientos hasta llegar a la versión actual: UML 2.0.
La OMG (Object Management Group) es una asociación sin fines de lucro formada por grandes corporaciones, muchas de ellas de la industria del software, como, por ejemplo: IBM, Apple Computer, Oracle y Hewlett-Packard. Esta asociación se encarga de la definición y mantenimiento de estándares para aplicaciones de la industria de la computación
UML cuenta con varios tipos de diagramas, los cuales muestran diferentes aspectos de los sistemas que se modelan.