Programacion II
Programacion II
Programacion II
Programación II
Primera Edición
Fondo Editorial
Maracaibo - Venezuela
Año 2022
Ing. Ángel Pérez
Programación II
Primera Edición
ISBN: 978-980-414-068-6
Depósito Legal: ZU2019000161
Fondo Editorial
2022
DEDICATORIA
OBJETIVO GENERAL
OBJETIVOS ESPECÍFICOS
DEDICATORIA...................................................................................5
RECONOCIMIENTOS.......................................................................7
INTRODUCCIÓN GENERAL..................................................................9
OBJETIVOS DEL PROGRAMA.............................................................11
OBJETIVO GENERAL.........................................................................11
OBJETIVOS ESPECÍFICOS..................................................................11
1. DEFINICIONES BÁSICAS................................................................21
1.1. CLASES Y OBJETOS ................................................................21
1.2. EL LENGUAJE JAVA ................................................................22
2. ORIGEN DE JAVA Y OBJETIVO PRINCIPAL DE SU TECNOLOGÍA ....23
2.1. ORIGEN DE JAVA...................................................................23
2.2. OBJETIVO PRINCIPAL DE SU TECNOLOGÍA ............................25
3. ESTRUCTURA DE UN PROGRAMA EN JAVA....................................26
4. DECLARACIÓN DE CLASES Y ATRIBUTOS.......................................29
4.1. DECLARACIÓN DE CLASES......................................................29
4.2. DECLARACIÓN DE ATRIBUTOS................................................31
5. TIPOS DE DATOS E INICIALIZACIÓN DE VARIABLES.......................34
5.1. TIPOS DE DATOS...................................................................34
5.2. TIPOS DE DATOS PRIMITIVOS...............................................35
5.3. DECLARAR (CREAR) VARIABLES.............................................36
5.4. DECLARACIÓN DE VARIABLE TIPO INT.................................37
5.5. OTRAS FORMAS DE DECLARACIÓN DE VARIABLES................38
5.6. DATOS NO PRIMITIVOS: ARREGLOS.....................................38
5.7. ACCESO A LOS ELEMENTOS DE UN ARREGLO..................39
5.8. CAMBIAR UN ELEMENTO DEL ARREGLO..............................39
5.9. LONGITUD DE UN ARREGLO...............................................40
5.10. RECORRIDO DE UN ARREGLO...............................................40
5.11. RECORRIDO DE UN ARREGLO USANDO FOR-EACH................41
5.12. SINTAXIS DE LA INSTRUCCIÓN............................................41
5.13. ARREGLOS MULTIDIMENSIONALES.......................................42
5.14. DEFINICIÓN DE UN ARREGLO BIDIMENSIONAL....................43
5.15. RECORRIDO DE UN ARREGLO BIDIMENSIONAL...................44
6. OPERADORES (ARITMÉTICOS, RELACIONALES Y LÓGICOS) Y
EXPRESIONES ...................................................................................45
6.1. OPERADORES ARITMÉTICOS................................................45
6.2. OPERADORES RELACIONALES..............................................47
6.3. OPERADORES LÓGICOS.......................................................49
6.4. OPERADORES DE ASIGNACIÓN..........................................50
7. SENTENCIAS DE DECISIÓN Y DE CICLO..........................................52
7.1. INSTRUCCIONES DE DECISIÓN...............................................52
7.2. INSTRUCCIÓN IF-ELSE............................................................53
7.3. INSTRUCCIÓN ELSE-IF............................................................54
7.4 INSTRUCCIÓN IF-ELSE ABREVIADO (OPERADOR TERNARIO)...55
7.5. INSTRUCCIÓN SWITCH (SEGÚN SEA)......................................55
7.6. CICLO – REPETICIÓN – ITERACIÓN..........................................57
7.6.1. INSTRUCCIÓN WHILE.......................................................57
7.6.2. INSTRUCCIÓN DO-WHILE.................................................58
7.6.3. INSTRUCCIÓN FOR...........................................................59
7.6.4. INSTRUCCIÓN FOR-EACH..................................................60
8. MANEJO DE STRING......................................................................61
9. COMPILACIÓN DE PROGRAMAS....................................................63
9.1. EDICIÓN................................................................................64
9.2. COMPILACIÓN........................................................................64
9.3. CARGA DEL PROGRAMA EN MEMORIA.......................................65
9.4. VERIFICACIÓN Y EJECUCIÓN DEL CÓDIGO BINARIO..................65
ACTIVIDADES DE AUTOEVALUACION...............................................67
1. DEFINICIÓN................................................................................102
2. MÉTODOS RECURSIVOS..............................................................104
3. RECURSIVIDAD VS. ITERACIÓN..................................................106
4. RESOLUCIÓN DE PROBLEMAS CON RECURSIÓN.........................107
4.1. RECORRIDO EN PREORDEN...................................................108
4.2. RECORRIDO EN INORDEN.....................................................108
4.3. RECORRIDO EN POSORDEN..................................................108
5. MÉTODOS DE ORDENACIÓN RECURSIVOS...................................110
5.1. ORDENACIÓN POR MEZCLA...................................................111
5.2. ORDENACIÓN RÁPIDA (QUICKSORT).....................................113
ACTIVIDADES DE AUTOEVALUACION...............................................117
1. FLUJOS.......................................................................................120
1.1. DEFINICIÓN.........................................................................120
1.2. FLUJOS. JERARQUÍA DE CLASES.............................................121
1.2.1. LECTURA DE LA CONSOLA DE ENTRADA...........................125
1.2.2. LECTURA DE CARACTERES...............................................126
1.2.3. LECTURA DE CADENAS....................................................128
1.2.4. LA CLASE PRINTWRITER.................................................129
1.2.5. LA CLASE SCANNER........................................................130
1.3. CLASES FILEINPUTSTREAM Y FILEOUTPUTSTREAM.................132
1.4. CLASES BYTEARRAYINPUTSTREAM Y BYTEARRAYOUTPUTSTREAM
.................................................................................................134
1.5. FILTROS...............................................................................136
1.6. CLASES DATAINPUTSTREAM Y DATAOUTPUTSTREAM...............137
1.7. CLASE PRINTSTREAM............................................................139
2. ARCHIVOS..............................................................................142
2.1. DEFINICIÓN.........................................................................142
2.2. CLASE FILE...........................................................................143
2.3. TIPOS DE ARCHIVOS.............................................................151
2.3.1. POR EL TIPO DE ACCESO A LOS REGISTROS DE DATOS........151
2.3.2. POR EL TIPO DE DATO ALMACENADO................................152
2.3.3. POR LA OPERACIÓN.........................................................153
2.4. ARCHIVO FUENTE.................................................................153
2.5. ARCHIVOS DE ENTRADA........................................................154
2.6. ARCHIVOS DE SALIDA............................................................156
ACTIVIDADES DE AUTOEVALUACION...............................................159
REFERENCIAS BIBLIOGRÁFICAS.......................................................161
UNIDAD I
PROGRAMACIÓN ORIENTADA A
OBJETOS Y JAVA
Programación II 21
UNIDAD I
PROGRAMACIÓN ORIENTADA A OBJETOS Y JAVA
1. DEFINICIONES BÁSICAS
La programación orientada a objetos es un modelo que presenta una
teoría que conviene estudiar para ampliar los conocimientos. Considerando
lo expuesto anteriormente, se busca que el estudiante reoriente su manera
de pensar, adquiriendo el lenguaje específico a aplicar en los procedimientos
planificados con Java. En este punto, se muestra brevemente los conceptos
básicos de la programación orientada a objetos desde un punto de vista
global, como por ejemplo, los términos clase y objeto y lenguaje Java.
Cuadro 1
Evolución del lenguaje Java
/********************************************************
Ejemplo de una clase en Java.
Este ejemplo muestra una plantilla de programa para aplicaciones Java
sencillas.
Con esta plantilla se puede codificar, compilar, ejecutar y depurar
cualquier
aplicación Java, en cualquier plataforma.
********************************************************/
System.out.println(“¡Hola Mundo!”);
/*
Valida que saldoInicial sea mayor que 0.0; si no lo es,
la variable saldo se inicializa con el valor predeterminado 0.0
*/
System.out.println(“Nombre: “ + objPersona.nombre + “ “ +
objPersona.apellido);
System.out.println(“Edad: “ + objPersona.edad); //Impresión del
atributo edad de objPersona
}
}
Cuadro 2
Donde tipo es uno de los tipos de datos (como int o String), y variable
es el nombre de la variable (como x o nombre). El signo igual se utiliza
Programación II 37
int Num;
Num = 15;
System.out.println(Num);
int Num = 5;
float FloatNum = 5.99f;
char Letra = ‘D’;
boolean Booleano = true;
String Texto = “Hello”;
System.out.println(carros[0]);
}
}
Sintaxis:
Dónde:
Tipo: es uno de los tipos de datos (como int o String o el nombre de
una clase)
int [ ] [ ] notas = new int[10][10]; //El arreglo notas tiene 100 elementos
tipo int
int num = 10;
Cuadro 3
Operadores aritméticos
int a = 1 + 1;
int b = a * 3;
Programación II 47
int c = b / 4;
int d = c - a;
int e = -d;
System.out.println(“a = ” + a);
System.out.println(“b = ” + b);
System.out.println(“c = ” + c);
System.out.println(“d = ” + d);
System.out.println(“e = ” + e);
}
}
El ejemplo anterior, involucra la creación de expresiones aritméticas,
cuyo resultado es numérico (tipo entero, en todos los casos arriba
mostrados). El operador módulo, %, retorna el resto de la división. Puede
ser aplicado a datos tipo punto flotante, también como a los datos de tipo
entero, como se muestra en el siguiente ejemplo.
class Modulo {
public static void main(String[] args) {
//Manejo del operador %
int x = 42;
double y = 42.25;
System.out.println(“x mod 10 = ” + x % 10);
System.out.println(“y mod 10 = ” + y % 10);
}
}
De esto, el mismo autor referido con anterioridad, acota que todos los
operadores relacionales comparten lo siguiente: son binarios (involucran
dos operandos, que pueden ser numéricos, caracteres, texto o cadena),
tienen el mismo nivel de precedencia y se asocian de izquierda a derecha.
Los operadores relacionales determinan la relación que un operando tiene
con el otro. Específicamente, determinan la igualdad y el orden (mayor que,
menor que…). Los operadores relacionales se muestran a continuación:
Cuadro 4
Operadores Relacionales
boolean c = a < b;
En este caso, el resultado de a < b (el cual es falso) se almacena en c.
Cuadro 5
Operadores lógicos
Cuadro 6
Operadores de asignación
int a = 1;
int b = 2;
int c = 3;
a += 5;
b *= 4;
c += a * b;
c %= 6;
System.out.println(“a = ” + a);
System.out.println(“b = ” + b);
System.out.println(“c = ” + c);
}
}
int x = 20;
int y = 18;
if (x > y) {
System.out.println(“x es mayor que y”);
}
Sintaxis:
if (condición) {
// Bloque de código a ser ejecutado si la condición es verdadera
} else {
// Bloque de código a ser ejecutado si la condición es falsa
}
if (condición1) {
// Bloque de código a ser ejecutado si la condición1 es verdadera
} else if (condición2) {
// Bloque de código a ser ejecutado si la condición1 es falsa y
condición2 es verdadera
} else {
// Bloque de código a ser ejecutado si la condición1 es falsa y
condición2 es falsa
}
En vez de escribir:
switch(expresión) {
case x:
// Bloque de código
break;
case y:
// Bloque de código
break;
default:
// Bloque de código
}
La expresión <según sea> se evalúa y el valor de la misma se compara
con el valor de cada uno de los casos. Si hay coincidencia, se ejecuta
el bloque de código asociado. La instrucción break sirve para salir de
la instrucción switch, una vez se ha ejecutado dicho código. Si no hay
coincidencia, se ejecuta el bloque de código asociado a default.
El siguiente ejemplo muestra la selección de un día de la semana,
basado en el valor contenido en la variable día.
int dia = 4;
switch (dia) {
case 1: System.out.println(“Lunes”);
break;
case 2: System.out.println(“Martes”);
break;
case 3: System.out.println(“Miércoles”);
Programación II 57
break;
case 4: System.out.println(“Jueves”);
break;
case 5: System.out.println(“Viernes”);
break;
case 6: System.out.println(“Sábado”);
break;
case 7: System.out.println(“Domingo”);
break;
}
// Imprime “Jueves” (día 4)
while (condición) {
// Bloque de código
}
58 Ángel Pérez
do {
// Bloque de código
}
while (condición);
8. MANEJO DE STRING
Como indica Eck (2019), un dato de tipo String es una secuencia de
caracteres, por ejemplo: “¡Hola Mundo!”. Las comillas dobles son parte del
dato (o literal); tienen que ser tecleadas en el programa. Sin embargo, no
son parte del valor real de la cadena, que consiste sólo en caracteres entre
las comillas. Una cadena puede contener cualquier número de caracteres,
incluso ninguno. Una cadena sin caracteres se llama la cadena vacía y se
representa por “” (un par de comillas dobles sin nada entre ellas). Las
comillas simples se usan para los caracteres y las comillas dobles para las
cadenas.
es equivalente a:
System.out.println(“abc”);
String cde = “cde”;
System.out.println(“abc” + cde); //Produce como salida “abccde”.
Mayúscula y minúscula:
int x = 10;
int y = 20;
int z = x + y; // z será igual a 30 (un número entero)
String x = “10”;
String y = “20”;
String z = x + y; // z será igual a 1020 (una cadena)
String x = “10”;
int y = 20;
String z = x + y; // z será igual a 1020 (una cadena)
9. COMPILACIÓN DE PROGRAMAS
Según Aguirre (2020), en la compilación de programas se analiza todo
el programa fuente, se crea el programa objeto y luego va a permitir la
64 Ángel Pérez
9.1. Edición
Al respecto, Deitel y Deitel (2012), mencionan que esta fase corresponde
a la escritura y grabado del programa en sí. Como herramienta, se puede
usar algo tan sencillo como Notepad (de Windows), pasando por editores
más elaborados como TextPad, Eclipse, NetBeans, entre otros (también
conocidos como ambiente integrado de desarrollo, o AID, capaces de llevar
a cabo las fases aquí descritas desde un solo sitio, algunas de manera
transparente). El resultado, conocido como programa fuente, debe ser
guardado en un archivo con extensión .java, como muestra el siguiente
ejemplo de programa:
/*
Este es un ejemplo de programa en Java.
Se debe guardar en disco como “Ejemplo.java”.
*/
class Ejemplo {
// El programa comienza con una llamada al método main().
public static void main() {
System.out.println(“Este es un muy simple programa en
Java.”)
}
}
9.2. Compilación
Para Deitel y Deitel (2012), en esta fase se realiza una revisión del
código fuente desarrollado en la fase anterior y, en caso que no hayan
errores de sintaxis, dicho código es traducido a código binario (bytecode,
en inglés) y se genera un archivo que lleva el mismo nombre que el archivo
Programación II 65
Nombre: _______________________________
UNIVERSIDAD
Privada
DR. RAFAEL BELLOSO CHACÍN Cédula: __________________ Sección: ______
4. Sea texto una variable tipo cadena (o string), que contiene la frase
“Hola Maracaibo”. Escriba las instrucciones necesarias para:
/*
Este es un ejemplo de programa en Java.
Se debe guardar en disco como “Ejemplo.java”.
/
clase Ejemplo {
El programa comienza con una llamada al método main().
public void main() {
System.println(“Este es un muy simple programa en Java.”
}
}
8. Sea y una variable tipa decimal flotante (float) con valor igual a
7.0 Si dicha variable pertenece a una clase llamada MiClase, elabore un
programa que
UNIDAD II
CLASES, MÉTODOS Y HERENCIA
70 Ángel Pérez
UNIDAD II
CLASES, MÉTODOS Y HERENCIA
1.1. Abstracción
Para Lewis y Chase (2006), un objeto es una abstracción, lo que quiere
decir que los detalles precisos de cómo funciona el objeto son irrelevantes
desde el punto de vista del usuario del objeto. Un elemento esencial de
la programación orientada a objetos es la abstracción, ya que permite
el manejo de la complejidad. Por ejemplo, la gente no piensa en un
vehículo como un conjunto de miles de piezas individuales, que actúan de
manera sincronizada, sino que es un objeto bien definido con su propio
comportamiento único.
Aunado a lo anterior, esta abstracción permite a la gente usar un
vehículo para movilizarse a cualquier parte, sin sentirse abrumada por la
complejidad de las piezas individuales. Pueden ignorar los detalles de cómo
funcionan el motor, la transmisión y los sistemas de frenado. En cambio,
son libres de utilizar el vehículo (objeto) como un todo.
Una manera poderosa de manejar la abstracción, es a través del uso de
clasificaciones jerárquicas. Esto permite poner en capas la semántica de
sistemas complejos, dividiéndolos en piezas manejables. Desde el exterior,
el vehículo es un solo objeto. Una vez dentro, se ve que el vehículo consta
de varios subsistemas: dirección, frenos, sistema de sonido, cinturones de
seguridad, calefacción, teléfono móvil, entre otros.
A su vez, cada uno de estos subsistemas se compone de unidades
más especializadas. Por ejemplo, el sistema de sonido puede consistir en
Programación II 71
1.2. Encapsulación
Como se indicó en el punto 4, todo en Java está asociado a clases y
objetos, junto con sus atributos y métodos. Los atributos (o variables de
instancia) guardan los datos, mientras que los métodos permiten realizar
operaciones sobre dichos datos (como actualizar el valor de una variable,
por ejemplo). Es importante establecer, por protección de los datos, que
sólo el objeto pueda modificar sus variables, a través de sus propios
métodos. En palabras de Lewis y Chase (2006), un objeto debe ser auto-
gobernado; es decir, el objeto debe estar encapsulado dentro del sistema.
La encapsulación se logra a través del uso de modificadores de
visibilidad: public y private. Las variables de instancia se definen private,
con lo que se limita su visibilidad a los miembros (métodos) que se
encuentran dentro de la clase. La visibilidad de los métodos dependerá
del propósito de los mismos; los que permitan el acceso a los datos deben
ser declarados public. El siguiente ejemplo muestra el modificador private
aplicado al atributo de la clase Persona (nombre) y los métodos requeridos
para el manejo del mencionado atributo (conocidos con los prefijos get y
set), los cuales han sido definidos como public.
}
// Método Set; permite fijar el valor a guardar por la variable nombre
public void setNombre(String nuevoNombre) {
this.nombre = nuevoNombre;//El valor de nuevoNombre se asigna
a nombre
}
}
1.3. Polimorfismo
Polimorfismo (“muchas formas”), en opinión de Jaime (2002), es la
capacidad de un elemento para adoptar diferentes formas en tiempo de
ejecución, y ocurre cuando se tienen varias clases que se relacionan entre
sí por herencia. Esta permite a una clase obtener atributos y métodos de
otra clase. El polimorfismo utiliza estos métodos para realizar diferentes
tareas. Esto permite realizar una sola acción de diferentes maneras.
Para ilustrar lo dicho anteriormente, se tienen las clases: Animal, Cerdo
y Perro, en donde las dos últimas pertenecen (o heredan) a la primera.
Esto establece una relación de herencia, en donde Animal es la superclase
(o clase base) y Cerdo y Perro son subclases (o clases derivadas). Cada
animal emite su propio sonido, que queda registrado en el método llamado
sonidoAnimal(), presente en todas las clases.
// Esta clase define una pila de números enteros que puede almacenar
diez valores
class Stack {
int pila [ ] = new int[10];//Define un arreglo para ser usado como pila
int tope;//Controla la cantidad de elementos que hay en la pila.
// Inicializa el tope de la pila
Stack() {
tope = -1;//No hay elementos en la pila
}
}
// Inserta un valor en la pila
void inserta(int ítem) {
if(tope==9)
System.out.println(“La pila está llena.”);
else
pila[++tope] = ítem;//La variable tope se incrementa en 1
}
76 Ángel Pérez
public int i;
private double j;
private int miMetodo(int a, char b){ // …
// Esta clase define una pila de números enteros que puede almacenar
diez valores
class Stack {
/* Ahora, los atributos pilan y tope son privados (private). Esto
significa que no pueden
ser alterados, accidental o maliciosamente.
*/
private int pila[] = new int[10];
private int tope;
// Inicializa el tope de la pila
Stack() {
tope = -1;
}
}
// Inserta un valor en la pila
void inserta(int ítem) {
if(tope==9)
System.out.println(“La pila está llena.”);
else
pila[++tope] = ítem;
78 Ángel Pérez
}
// Extrae un valor de la pila
int extrae() {
if(tope < 0) {
System.out.println(“La pila no tiene elementos. “);
return 0;
}
else
return pila [tope--];
}
En el ejemplo, se observa que los atributos pila y tope (el índice que
señala la posición o tope de la pila) fueron especificados como private.
Esto significa que no pueden ser accesados o alterados, excepto a través
de inserta() y extrae().
La siguiente clase permite probar los cambios realizados a la clase
Stack:
class PruebaStack{
public static void main (String args [ ] ) {
Stack pila1 = new Stack(); //Primer objeto tipo Stack
Stack pila2 = new Stack();//Segundo objeto tipo Stack
// Se insertan valores en ambas pilas (10 valores en cada caso)
for (int i = 0; i<10; i++) pila1.inserta(i);
for (int i = 0; i<10; i++) pila2.inserta(i);
// Se extraen los valores insertados en cada pila
System.out.println(“Elementos en la pila1:”);
for (int i = 0; i<10; i++) System.out.println(pila1.extrae());
System.out.println(“Elementos en la pila2:”);
for (int i = 0; i<10; i++) System.out.println(pila2.extrae());
// Las siguientes instrucciones no son válidas
Programación II 79
// pila1.tope = -2;
// pila2.pila[3] = 100;
} //Fin del método main()
} // Fin de la clase
El ejemplo anterior debe ser ejecutado dos veces: la primera, tal como
se muestra el código y en la segunda, se deben eliminar las barras de
comentarios de las dos últimas instrucciones:
// pila1.tope = -2;
// pila2.pila[3] = 100;
4. RETORNO DE OBJETOS
Para Schildt (2017), un método puede devolver cualquier tipo de
datos, incluidos los de tipo clase que cree (es decir, objetos). Por ejemplo,
en el siguiente programa, el método sumaDiez() devuelve un objeto en el
que el valor de la variable a se incrementa en diez, comparado al objeto
que invoca.
82 Ángel Pérez
Por separado, cada ejemplo muestra el uso del método max(), según
el tipo de datos de los valores numéricos de entrada. Para ilustrar la
sobrecarga en métodos, los ejemplos anteriores se pueden resumir en uno
solo como sigue a continuación:
class Caja {
double ancho;
double alto;
double profundidad;
// Constructor de la clase
Caja (double n, double l, double p) {
ancho = n;
alto = l;
profundidad = p;
}
// Calcular y retornar el volumen
double volumen () {
return ancho * alto * profundidad;
}
}
}
// Constructor de la clase a usar cuando se especifican las dimensiones
de un cubo
Caja (double longitud) {
ancho = alto = profundidad = longitud;
}
6. DESCRIPCIÓN DE HERENCIA
La herencia es el proceso de derivar una nueva clase a partir de otra
clase existente, en opinión de Lewis y Chase (2006), este proceso va a
permitir que la nueva clase contenga, de manera automática, las variables
y métodos de la clase original. En este punto, la clase derivada puede ser
modificada para añadir nuevas variables y métodos. Utilizando la herencia,
se puede crear una clase general que defina los rasgos comunes a un
conjunto de elementos relacionados. Los rasgos de esta clase pueden,
entonces, ser heredados por otras clases más específicas, cada una de las
cuales añade los atributos que las hacen únicas.
En este orden, la clase que se hereda puede ser considerada como una
clase original. La que recibe la herencia es una clase derivada. Por lo tanto,
una clase derivada es una versión especializada de una clase general. La
clase derivada heredará todos los miembros definidos por la clase general
y añadirá sus propios elementos únicos.
En Java, es posible heredar, no solo atributos, sino también métodos
de una clase a otra. Para heredar de una clase, se usa la palabra clave
extends. Si Carro y Vehiculo son dos clases, en donde la primera hereda
los rasgos de la segunda, entonces se aplica, en la definición de la clase
Carro la siguiente cláusula:
class Vehiculo {
protected String marca = “Ford”; // Atributo de la clase Vehiculo
public void corneta() { // Método de la clase Vehiculo
System.out.println(“Tuut, tuut!”);
}
}
Este tipo de relación significa que la clase derivada es una versión más
específica que la original. Si se aplica esto al caso anterior, se tiene que la
clase Carro es-un Vehiculo, pero no se cumple lo inverso (todo Vehiculo
es-un Carro).
7. VENTAJAS DE LA HERENCIA
Al respecto, Deitel y Deitel (2012), acotan que con la herencia se puede
ahorrar tiempo durante el desarrollo de un programa, basando las nuevas
clases en software ya probado y depurado. Esto también aumenta la
probabilidad de que un sistema sea implementado y mantenido eficazmente,
porque al crear una clase, en lugar de declarar miembros completamente
nuevos, se puede designar que la nueva clase debe heredar los miembros
de una clase existente. Luego, la herencia es útil para la reutilización de
código: permite aprovechar código (atributos y métodos) de una clase
existente cuando se crea una nueva clase.
Como se vió en la sección anterior, a través del uso de la palabra clave
“extends”, las nuevas clases pueden heredar los miembros de una clase ya
existente, lo cual incluye las clases pertenecientes a las bibliotecas de Java,
como se muestra en el siguiente ejemplo:
// Dibuja la cara
g.setColor( Color.YELLOW );
g.fillOval( 10, 10, 200, 200 );
// Dibuja la boca
g.fillOval( 50, 110, 120, 60 );
8. SUPERCLASES Y SUBCLASES
En cuanto a las explicaciones de las dos secciones anteriores, en Java,
el “concepto de herencia” requiere, como mínimo, dos tipos de clases:
Programación II 93
Figura 2.
this.nombre = nuevoNombre;
}
public void setEdad(int edad) {
this.edad = edad;
}
public float getAltura() {
return altura;
}
}
Nombre: _______________________________
UNIVERSIDAD
Privada
DR. RAFAEL BELLOSO CHACÍN Cédula: __________________ Sección: ______
UNIDAD III
RECURSIVIDAD
1. DEFINICIÓN
Para Aguirre (2020), la recursividad es la característica en la
programación que permite hacer un llamado a un método desde el mismo
método, esta simplifica el desarrollo y equivale a una iteración en una
estructura de repetición como while o for. En este orden, al aplicar esta
definición, el método necesariamente debe retomar un valor, recibir por
parámetro al menos un valor, implementando una condición de ruptura
del proceso recursivo aplicando una función del mismo proceso recursivo.
Ante esto, los programas vistos en las unidades precedentes de este
libro están estructurados en métodos que deben ser invocados (o llamados)
para ser usados, ya sea de manera directa o a través de otro método,
como muestran los ejemplos siguientes:
System.out.println(“Buen dia.”);
System.out.println(txt.toUpperCase());
int num = entrada.nextInt();
f0 = 0; f1 = 1 y
fn = fn-1 + fn-2 para n>=2
función Fibonacci(n)
si n < 2 entonces devolver n
sino devolver Fibonacci(n-1) + Fibonacci(n-2)
En este orden, los enfoques de resolución de problemas recursivos
tienen varios elementos en común. Cuando se llama a un método recursivo
para resolver un problema, éste en realidad es capaz de resolver sólo
los casos más simples o los casos base (n < 2, en el caso anterior). Si el
método se llama con un caso base, devuelve un resultado (0 o 1, en el
caso anterior).
Si el método se llama con un problema más complejo, devuelve una
o más llamadas al método (Fibonacci(n-1) + Fibonacci(n-2), según el
valor de n). Debido a que este nuevo problema se parece al problema
original, el método llama a una nueva copia de sí mismo para trabajar en
el problema más pequeño – esto se conoce como una llamada recursiva y
104 Ángel Pérez
2. MÉTODOS RECURSIVOS
En lo que se refiere a la programación en Java, la recursión es el atributo
que permite que un método se llame a sí mismo, de acuerdo a lo indicado
por Downey y Mayfield (2016). Se dice que un método que se llama a sí
mismo es recursivo. Un ejemplo de recursividad es el cálculo del factorial
de un número entero, que se presenta a continuación:
0! = 1
n! = n (n – 1)!
// Cálculo del factorial en forma recursiva
class Factorial {
//Comienzo del método recursivo
int fact(int n) {
int result;
Programación II 105
Tabla 1
Llamada Resultado
1*(fact(0)) 1
2*(fact(1)) 1
3*(fact(2)) 2*1
(fact(3)) 3*2
factorial = 1;
for ( int contador = numero; contador >= 1; contador-- )
factorial *= contador;
Cuadro 7
Comparación entre recursividad e iteración
Recursividad Iteración
Basada en una instrucción de Basada en una instrucción de
control o selección (if, if-else o control o repetición (for, while o
switch) do- while)
El proceso involucra repetición El proceso involucra repetición de
llamadas sucesivas al método manera explícita
El proceso termina cuando se El proceso termina cuando se
alcanza el caso base. alcanza la condición final.
El proceso se mantiene produciendo El proceso se mantiene modificando
versiones más pequeñas del un contador, hasta que éste
problema original, hasta que un alcanza un valor que hace que la
caso base es alcanzado. continuación del lazo falla.
Se puede generar un lazo infinito Se puede generar un lazo infinito si
si el proceso no logra alcanzar un la condición final no se alcanza en
caso base. ningún momento.
• Visitar la raíz
• Recorrer el subárbol izquierdo en preorden
• Recorrer el subárbol derecho en preorden
r.visitar();
}
}
void visitar( ) {
System.out.print(dato + “ “);
}
Una vez que el pivote ha sido elegido, se utiliza para ordenar el resto de
la lista en dos sublistas: una tiene todas las claves menores que el pivote
y la otra el resto. Estas dos listas parciales se ordenan recursivamente. La
lista final ordenada se consigue concatenando la primera sublista, el pivote
y la segunda sublista, en ese orden, en una única lista. La primera etapa
del algoritmo es la división o particionamiento recursivo de la lista, hasta
que todas las sublistas constan de un elemento.
La implementación del algoritmo se realiza de manera recursiva; el
método quicksort() con el parámetro a[ ], llama al método privado del
mismo nombre, con los argumentos a[ ], los índices inferior y superior del
arreglo, como se muestra a continuación.
if (i <= j)
{
intercambiar(a, i, j);
Programación II 115
i++;
j--;
}
}while (i <= j);
if (primero < j)
quicksort(a, primero, j); // mismo proceso con sublista izquierda
if (i < ultimo)
quicksort(a, i, ultimo); // mismo proceso con sublista derecha
}
Nombre: _______________________________
UNIVERSIDAD
Privada
DR. RAFAEL BELLOSO CHACÍN Cédula: __________________ Sección: ______
1. Un método es recursivo si
a. Presenta un caso base y una instrucción if para determinar si se ha
llegado al mismo o no
b. Presenta una llamada a sí mismo
c. Presenta un caso base y una llamada a sí mismo
d. Todas las anteriores
e. Ninguna de las anteriores
UNIDAD IV
FLUJOS Y ARCHIVOS
1. FLUJOS
En las anteriores unidades de este libro, los ejemplos de código
presentados han manejado los datos a través de variables de tipo
primitivo (int, float, por ejemplo), cadenas (tipo String) o a través de
conjuntos homogéneos de elementos (arreglos). Todos ellos tienen como
característica que se almacenan en la memoria principal del computador,
durante la ejecución del programa, lo cual significa que, al terminar la
ejecución, dichos datos se pierden.
Ante esta situación, Joyanes, y Zahonero, (2008), indican que los
archivos tienen como finalidad guardar datos de forma permanente; una
vez que termina la aplicación o programa, los datos siguen disponibles para
que otra aplicación pueda recuperarlos para su consulta o modificación. El
proceso de archivos en Java se hace mediante flujos (streams) o canales,
los cuales conducen los datos entre el programa y los dispositivos externos
(disco duro, disco compacto, memoria portátil o pendrive, entre otros) y
viceversa.
De lo indicado anteriormente, se pueden identificar, como operaciones
básicas, la escritura de datos (para realizar el almacenamiento de datos) y
la lectura (para realizar consultas). Estas operaciones son conocidas como
Entrada/Salida (Input/Output) y se abrevian como E/S (I/O).
1.1. Definición
Para Joyanes y Zahonero (2008), un flujo (stream) es una abstracción
que se refiere a un flujo o corriente de datos que circulan entre un origen
o fuente (productor) y un destino o sumidero (consumidor). Entre el origen
y el destino debe existir una conexión o canal (pipe) por la que corran
los datos. La apertura de un archivo supone establecer la conexión del
programa con el dispositivo que contiene al archivo; por el canal que
comunica al archivo con el programa van a fluir las secuencias de datos.
Abrir un archivo, supone crear un objeto que queda asociado a un flujo. Al
comenzar la ejecución de un programa en Java, se crean automáticamente
tres objetos flujo, por los que pueden circular datos, de entrada, o de
salida. Estos son objetos definidos en la clase System:
datos por pantalla.
0 1 2 ... n-1
... Fin de archivo
Figura
Figura 3.3.Vista
Vista dearchivo
de un un archivo
de n bytesde n bytes en Java
en Java
Fuente: Deitel, P. y Deitel, H. (2012)
Fuente: Deitel y Deitel (2012)
Cuadro 8
Flujos de Bytes
Cuadro 9
Flujos de caracteres
BufferedReader(Reader lectorEntrada)
InputStreamReader(InputStream flujoEntrada);
Cada vez que el método read() es invocado, lee un caracter del flujo
de entrada y lo retorna como un valor de tipo entero. Este método retorna
–1 cuando se intenta leer más allá del final del flujo. Como se muestra en
la definición del método read(), éste maneja (lanza) excepciones del tipo
IOException.
El siguiente ejemplo de código muestra el uso del método read()
leyendo caracteres suministrados por el usuario, hasta que se ingresa el
caracter “q.” En el ejemplo, se observa que cualquier excepción de E/S que
pueda generarse es simplemente lanzada desde main().
import java.io;
public class LeeCaracter {
public static void main(String[] args) throws IOException {
Programación II 127
char c;
BufferedReader entrada = new BufferedReader (new
InputStreamReader (System.in));
System.out.println(“Ingrese una secuencia de caracteres y ‘q’ para
finalizar”);
//Lectura de caracteres ingresados
do {
c = (char) entrada.read();
System.out.println(c);
} while(c!= ‘q’);
}
}
import java.io;
public class LecturaLinea {
public static void main(String[] args) throws IOException {
String cadena;
BufferedReader entrada = new BufferedReader (new
InputStreamReader (System.in));
System.out.println(“Ingrese líneas de texto”);
System.out.println(“Ingrese ‘termina’ para finalizar”);
//Lectura de caracteres ingresados
do {
cadena = entrada.readLine();
System.out.println(cadena);
} while(!cadena.equals(“termina”));
}
}
Programación II 129
import java.io;
public class EjemploPrintWriter {
public static void main(String[] args) throws IOException {
PrintWriter salida = new PrintWriter (System.out, true);
salida.println(“Esta es una cadena”);
130 Ángel Pérez
int i = -7;
salida.println(i);
double d = 4.5e-7;
salida.println(d);
}
}
FileInputStream(String ruta)
FileInputStream(File archivo)
System.out.print((char) entrada.read());
longitud = entrada.available( );
FileOutputStream(String ruta)
FileOutputStream(File archivo)
FileOutputStream(String ruta, boolean agrega)
FileOutputStream(File archivo, boolean agrega)
un objeto tipo File que describe al archivo de salida. Los dos constructores
finales permiten agregar bytes a un archivo existente, por lo que incorporan
una variable (agrega) de tipo boolean. Si el archivo especificado no existe,
se genera una excepción del tipo FileNotFoundException. La creación de
objetos es similar al caso anterior, para lo cual se presentan dos ejemplos:
ByteArrayInputStream(byte arreglo [ ])
ByteArrayInputStream(byte arreglo [ ], int inicio, int numBytes)
ByteArrayOutputStream()
ByteArrayOutputStream(int numBytes)
Un ejemplo de aplicación de esta clase:
ByteArrayOutputStream f = new ByteArrayOutputStream();
f.write(buf);
1.5. Filtros
Los flujos vistos en las secciones anteriores se caracterizan por el manejo
(lectura o escritura) de bytes (o de un arreglo de bytes). Un flujo tipo filtro
proporciona una funcionalidad adicional, como la agregación de los bytes
de datos en unidades de tipo primitivo significativas (números, letras, etc.),
según lo señalan Deitel y Deitel (2012). En esta categoría, se encuentran
la clase FilterInputStream, la cual, filtra un objeto tipo InputStream, y
FilterOutputStream, que filtra un objeto tipo OutputStream.
Para Schildt (2017), los flujos tipo filtro son simplemente envoltorios
alrededor de los flujos de entrada o salida subyacentes, que proporcionan
de forma transparente un nivel de funcionalidad ampliada. Se suele
acceder a estos flujos mediante métodos que esperan un flujo genérico,
que es una superclase de los flujos filtrados. Las extensiones típicas son
el almacenamiento en memoria intermedia, la traducción de caracteres y
la traducción de datos en bruto. Los constructores correspondientes se
muestran a continuación:
FilterOutputStream(OutputStream os)
FilterInputStream(InputStream is)
Programación II 137
{
double real = entrada.readDouble( ); //Lee un valor tipo double
int entero = entrada.readInt( ); // Lee un valor tipo int
boolean logico = entrada.readBoolean( ); // Lee un valor lógico o
booleano
}
2. ARCHIVOS
En esta parte se hablará de la relevancia de los archivos o ficheros en
programación Java, ya que estos contienen un código fuente, lo cual, está
representado en secuencias de caracteres, organizados en líneas de igual
o diferente longitud, donde el programador los representa de forma lógica
y ordenada.
2.1. Definición
Un archivo es un contenedor para guardar datos e información en
un sistema informático. Los datos guardados en archivos son datos
persistentes (se encuentran disponibles, aunque la ejecución del programa
haya terminado). De manera más formal, Joyanes, y Zahonero, (2008),
definen un archivo como una colección de registros relacionados entre
sí, con aspectos en común y organizados para un propósito específico.
Por ejemplo, un archivo escolar contiene un conjunto de registros de los
estudiantes de una clase en particular (identificación, apellidos, nombres,
entre otros datos).
En un archivo, los datos deben estar organizados de tal modo que
puedan ser recuperados fácilmente, actualizados o borrados y almacenados
de nuevo en el archivo con todos los cambios realizados. Hay diferentes
tipos de archivos como archivos de texto, archivos de datos, archivos de
directorio, archivos binarios y gráficos, y estos diferentes tipos de archivos
almacenan diferentes tipos de información.
Por otra parte, en un computador, los archivos pueden almacenarse en
unidades de discos duros, memorias portátiles u otros tipos de dispositivos
de almacenamiento. Los datos contenidos en los archivos pueden variar
desde información generada por el sistema hasta información especificada
por el usuario. Las operaciones básicas que se pueden realizar en un
archivo son:
• Creación de un nuevo archivo
• Modificación de datos o atributos de archivos
• Lectura de datos del archivo
Programación II 143
Cuadro 10
nombre.getName(), “ existe”,
( nombre.isFile() ? “es un archivo” : “no es un archivo” ),
( nombre.isDirectory() ? “es un directorio” : “no es un directorio”
),
( nombre.isAbsolute() ? “es ruta absoluta” : “no es ruta
absoluta” ),
“Ultima modificacion: “, nombre.lastModified(),
“Tamanio: “, nombre.length(),
“Ruta: “, nombre.getPath(),
“Ruta absoluta: “, nombre.getAbsolutePath(),
“Padre: “, nombre.getParent() );
if ( nombre.isDirectory() ) // muestra el listado del directorio {
String[] directorio = nombre.list();
System.out.println( “\n\nContenido del directorio:\n” );
for ( String nombreDirectorio : directorio )
System.out.printf( “%s\n”, nombreDirectorio );
} // Fin de if
} // Fin de if exterior
else // no es archivo o directorio, muestra mensaje de error
{
System.out.printf( “%s %s”, ruta, “no existe.” );
} // Fin de else
} // Fin del método analizarRuta
} // Fin de la clase DemostracionFile
Esta clase puede ser combinada con las clases disponibles en la API
(Application Program Interface, o Interfaz de Programas de Aplicación)
de Java que pueden utilizarse para leer y escribir archivos: FileReader,
BufferedReader, Scanner, FileInputStream, FileWriter, BufferedWriter,
FileOutputStream, entre otros, para desarrollar aplicaciones que manejen
bytes, caracteres o agregados de los anteriores, según sea el caso.
En algunos de los ejemplos anteriores, se ha hecho uso de las siguientes
palabras reservadas: try, catch. Las mismas sirven para efectuar el manejo
de las excepciones. Según Eck (2019), una excepción es una anomalía en el
flujo normal de control del programa. El término se utiliza con preferencia a
Programación II 149
try {
< instrucciones-1 > //Grupo de instrucciones
}
catch ( < nombre-de-excepción > <nombre-de-variable> ) {
< instrucciones-2 >//Grupo de instrucciones
}
try {
File objArch = new File(“archivo.txt”);
if (objArch.createNewFile()) {
System.out.println(“Archivo creado: “ + objArch.getName());
System.out.println(“Ruta absoluta: “ + objArch.getAbsolutePath());
} else {
System.out.println(“Archivo ya existe.”);
}
}
catch (IOException e) {
System.out.println(“Ocurrio un error.”);
e.printStackTrace();
}
Programación II 151
En esta parte del ejemplo, se espera que ocurra una excepción del
tipo IOException y el nombre del objeto es e. Si ocurre una excepción de
este tipo, se presenta un mensaje que indica la ocurrencia de un error y, a
través de la variable e, se imprime el contenido de la pila (stack), mediante
el método printStackTrace().
Si la excepción que se genera es distinta de IOException, el programa
terminará su ejecución. En este caso, se puede tomar nota de la excepción
generada e incluir otro bloque catch, a continuación del especificado
anteriormente, para abarcar esta nueva situación; de esta manera, se
pueden cubrir las posibles excepciones que se puedan presentar y, de esta
manera, hacer que el programa sea más robusto.
• Acceso secuencial
• Acceso directo
• Secuencial indexado
152 Ángel Pérez
Luego, los archivos pueden ser clasificados, según el tipo de flujo usado
en:
• Binario
• exto
• Entrada
• Salida
objLector.close();
• Apertura
• Lectura de datos
• Cierre
156 Ángel Pérez
• Apertura/ creación
• Escritura de datos
• Cierre
Nombre: _______________________________
UNIVERSIDAD
Privada
DR. RAFAEL BELLOSO CHACÍN Cédula: __________________ Sección: ______
REVISTA ELECTRÓNICA