- Curso Java desde 0. Leccion #1 Introduccion.
- Curso Java desde 0. Leccion #3 Constantes, Operadores y tipos de errores
1. Compilación y ejecución del código.
Para que un programa Java pueda ejecutarse, debe pasar las etapas de compilación y ejecución.
La compilación es un proceso que transforma el código fuente de Java en bytecode, este bytecode es un lenguaje intermedio
Este bytecode es un conjunto de instrucciones diseñadas para ser ejecutadas por la Máquina Virtual de Java (JVM). A diferencia del código fuente, que está escrito en un lenguaje comprensible para los programadores, el bytecode está en un formato que la JVM puede entender. Esto hace que el bytecode sea independiente de la plataforma, lo que significa que puede ser ejecutado en cualquier sistema que tenga instalada una implementación de la JVM, sin importar el sistema operativo o la arquitectura de hardware. Por lo tanto, el bytecode actúa como un lenguaje intermedio entre el código fuente Java y la ejecución del programa, permitiendo la portabilidad y la interoperabilidad de las aplicaciones Java.
El bytecode no es binario, con lo cual no es ejecutable directamente por la máquina, para ejecutarlo utilizamos la herramienta java
disponible en el JDK y en el JRE, esta herramienta tiene la función de iniciar la JVM que carga el bytecode y lo compila sobre la marcha (compilación JIT - Just In Time) para obtener un binario ejecutable directamente en la máquina.
2. Variables en Java y tipos de datos.
Una variable es un nombre que se asocia a un espacio en la memoria del ordenador y nos permite almacenar en memoria valores útiles para el funcionamiento de nuestro programa, podemos entender las variables como una “caja” con un nombre en la memoria de nuestro ordenador, en la cual podemos almacenar algún dato.
Todas las variables deben declararse antes de ser usadas, la declaración consiste en una sentencia en la que figura el tipo de dato y el nombre que asignamos a la variable.
[modificador] tipo nombreDeLaVariable;
Después de posibles modificadores, una variable se declara definiendo su tipo seguido de su nombre, la declaración termina siempre con ;
. Por ejemplo vamos a declarar una variable edad con el valor 23:
int edad = 23;
En este ejemplo el tipo de la variable es int
(entero). Los tipos de datos se explican a continuación.
En la variable edad
del ejemplo, hemos inicializado la variable, la inicialización es el paso por el cual se le suministra un primer valor a una variable y como en el ejemplo está puede llevarse a cabo al mismo tiempo que su declaración.
//Declaracion e inicialización al mismo tiempo.
[modificador] tipo nombreDeLaVariable = valor;
La inicialización puede llevarse a cabo después de la declaración de la variable:
[modificador] tipo nombreDeLaVariable;
nombreDeLaVariable = valor;
Por ejemplo, vamos a declarar una variable edad y la vamos a inicializar en otra linea con el valor 18:
int edad;
edad = 18;
En estos ejemplos no estamos utilizando [modificador]
pero como veremos más adelante debemos saber que podemos añadir el mismo.
Para inicializar variables utilizamos el operador de asignación =
valor
puede tomar diferentes formas:
- Un valor literal:
int edad = 18;
- Otra variable:
int edadPrimerHijo = 18;
int edadSegundoHijo = edadPrimerHijo;
En este ejemplo estamos asignando el valor de la variable edadPrimerHijo
(18) a la variable edadSegundoHijo
, con lo cual esta también tendrá el valor 18, pero si a lo largo de nuestro programa cambia la edadPrimerHijo
, también cambiara el valor de edadSegundoHijo
.
La ilustración de este ejemplo en memoria es:
En Java todas las variables tienen un tipo:
double sueldo = 153.26;
int diasDeVacaciones = 30;
long poblacion = 173526842748L;
boolean hecho = true;
Podemos declarar variables en una misma linea:
int edad,sueldo,id;
También podemos declararlas e inicializarlas en una misma linea:
int edad = 18, sueldo = 1800, id = 65343;
1. Tipos de datos en Java.
Durante la explicación de las variables, ha aparecido en numerosas ocasiones el concepto de tipo de dato, mostrando incluso ejemplos con el tipo de dato int
¿Pero que son los tipos de datos?
Los tipos de datos son categorías o clasificaciones que determinan qué tipo de valores pueden almacenarse y manipularse en un programa. Definen el tipo de información que puede ser representada y procesada por el programa
Java es un lenguaje de verificación estricta de tipos, es decir todas las variables tienen que tener un tipo declarado.
En Java disponemos de ocho tipos primitivos de datos:
Enteros
Coma Flotante
Tipo Char
Tipo Boolean
** a. Los tipos numéricos enteros.**
Los tipos de datos enteros se utilizan para valores numéricos que no tienen parte fraccionaria. Permite negativos, java cuenta con:
Tipo | Valor mínimo | Valor máximo | Espacio en memoria |
---|---|---|---|
byte |
-128 | 127 | 8 bits |
short |
-32768 | 32767 | 16 bits |
int |
-2147483648 | 2147483647 | 32 bits |
long |
-9223372036854775808 | 9223372036854775807 | 64 bits |
Cuando elegimos un tipo para las variables enteras, debemos tener en cuenta los valores mínimos y máximos que vamos a almacenar en ella con el fin de optimizar la memoria. Por ejemplo, es inútil almacenar en una variable de tipo long
una variable cuyo valor no superará a lo largo del programa el valor 50, en este caso una variable de tipo byte
, sería mas correcta, ya que optimizaríamos la memoria.
b. Los tipos numéricos decimales (Coma flotante).
Los tipos con coma flotante son los números con parte fraccionaria. En Java existen dos tipos:
Tipo | Valor mínimo | Valor máximo | Espacio en memoria |
---|---|---|---|
float |
-3.4028235E+38 | 3.4028235E+38 | 32 bytes |
double |
-1.7976931348623157E+308 | 1.7976931348623157E+308 | 64 bytes |
El tipo de dato double
hace referencia a que tiene el doble de precisión que los de tipo float
.
Todos los tipos decimales están firmados y por lo tanto pueden contener valores positivos o negativos.
El tipo float
registra un máximo de ocho dígitos significativos, y el tipo double
de 17 dígitos significativos.
c. Tipo char.
En Java el tipo char
sirve para representar caracteres, realmente describe una unidad de código con la codificación UTF-16.
Se recomienda no utilizar el tipo char
en los programas salvo que se vaya a manipular unidades de código UTF-16. Se recomienda siempre utilizar cadenas.
d. Tipo boolean.
El tipo boolean
tiene dos posibles valores, true/false
. Se utiliza para evaluar condiciones lógicas.
No se pueden hacer conversiones entre valores enteros y boolean
Esta es la teoría básica sobre el funcionamiento de las variables y los datos en Java, pero hay algunos conceptos extra, que de momento no estamos en condiciones de entender plenamente, estos conceptos se aclararan cuando veamos la Programación Orientada a Objetos y los tipos por referencia, estos conceptos son necesario conocerlos para cuando sea el momento poder comprenderos. De momento es importante quedarse con el concepto principal de variable y los distintos tipos. Lee detalladamente la explicación completa, pero no te preocupes si de momento no entiendes algunos apartados, cuando llegue el momento siempre puedes regresar a esta explicación para afianzar el conocimiento.
2. Las ubicaciones de las variables.
Las variables en Java se pueden declarar en cualquier parte del programa. No hay espacios reservados para ello.
Se debe declarar obligatoriamente una variable antes de poder utilizarla en el código. Según la ubicación de la declaración de la variable, esta pertenecerá a una de las siguientes categorías:
- Variable declarada en el interior de una clase: La variable es una variable de instancia. Solo existirá si una instancia de la clase está disponible (un objeto). Cada instancia u objeto de clase tendrá su propio ejemplar de la variable.
- Declarada en el interior de una clase con la palabra reservada
static
: La variable es una variable de clase. Se puede acceder a ella directamente por el nombre de la clase y existe en un único ejemplar, independientemente del número de objetos creados a partir de esta clase. - Declarada en el interior de un método: La variable es una variable local. Solo existe durante la ejecución del método y solo se puede acceder a ella desde el código de esta.
- Los parámetros de los métodos se pueden considerar como variables locales. La única diferencia reside en la inicialización de la variable efectuada durante la llamada a esta. La estructura del programa permite visualizar la ubicación de sus diferentes categorías de variables:
public class UbicacionDeLasVariables{
//Variables de Instancia
//Variables de clase static
...unMetodo(/*PARAMETROS*/){
//variables Locales
}
}
3. El nombre de las variables.
El nombre que asignamos a nuestras variables debe respetar algunas reglas:
- El nombre de una variable SIEMPRE empieza por una letra.
- Puede tener letras, cifras o el carácter
_
- Puede contener un número cualquiera de caracteres, pero por razones prácticas, es mejor limitarse a un tamaño razonable.
- Se hace distinción entre minúsculas y MAYÚSCULAS.
- No se pueden utilizar como nombre de variables las palabras reservadas del lenguaje.
- Por convenio, el nombre la variable se escribe con letras minúsculas, salvo la primera letra de cada palabra (a partir de la 2º palabra)
edadDelCapitan
.
4. Los tipos por valor y referencia.
Al determinar un tipo para una variable, indicamos que tipo de información vamos a almacenar en dicha variable, y en consecuencia, las operaciones que podremos realizar con ella.
Java dispone de dos categorías de tipos de variables:
- Los tipos por valor: la variable contiene realmente la información.
- Los tipos por referencia: la variable contiene la dirección de memoria donde se encuentra la información.
La variable variableTipoReferencia
está asociada con un espacio de memoria que contiene una dirección de otro espacio de memoria. Esta dirección se indica con @
. En esta dirección hay un espacio de memoria que contiene dos datos:
- Una
variable1
de tipo por valor. - Una
variable2
de tipo por referencia.
Detrás de este mecanismo encontramos los punteros, utilizados en lenguajes como C o C++. Es la representación clásica de un objeto.
a. Los tipos por valor.
Los tipos por valor representan los tipos de nivel mas bajo a partir de los cuales es posible trabajar cualquier información. Están representados por los tipos primitivos:
- Números enteros
int, byte, long, short
- Números decimales
double, float
- Caracteres
char
- Booleanos
boolean
Con estas categorías, es posible trabajar cualquier información básica.
b. Los tipos por referencia.
Como he dicho anteriormente, esta explicación de momento “se nos queda grande” pero nos ayudara en el futuro, si al principio no se comprende plenamente es totalmente normal, intenta fijarte en la ilustración y cuando veamos el capitulo de Programación orientada a objetos quedará mucho mas claro.
Cuando la información con la que tenemos que trabajar es más compleja, una variable de tipo por referencia permite agrupar un conjunto de variables que son consistentes entre sí.
Este es el caso, por ejemplo, de una fecha. Una fecha no se puede volver a presentar por un tipo primitivo, ya que se requiere una variable para el año, otra para el mes y una última para el día. Una fecha se representa mediante el uso de tres variables enteras.
Una variable de tipo por referencia, simplemente es una variable que hace referencia a un objeto.
En los tipos por referencia, las variables “apuntan” a la dirección de memoria y no almacenan su valor, si no almacenan la dirección de memoria.
Vamos a ver un ejemplo teórico, este no es real en Java, pero es útil para la demostración:
Fecha d1 = new Date (1939,7,5);
Fecha d2 = d1;
La representación de este caso en memoria es:
Como podemos ver, el valor de la variable d2
apunta a la misma dirección de memoria que la variable d1
. Por lo tanto el comportamiento es el mismo que para las variables de tipo por valor: había una copia de la variable d1
(en este caso, una dirección) en el espacio de memoria asignado a la variable d2
. Las consecuencias son, sin embargo, diferentes. De hecho las variables d1
y d2
están relacionadas por que comparten las mismas variables de dia
, mes
y anio
.
- Una llamada a una función que devuelva un valor.
int edad = calcularEdad(fechaDeNacimiento);
c. El uso de valores literales.
Como hemos visto, es común inicializar variables de tipo numérico con un valor literal:
int poblacionAlbacete = 220000;
double porcentajeMujeres = 51.1;
El compilador javac interpreta los valores numéricos enteros como valores de tipo int
y los valores numéricos decimales como valores de tipo double
. En consecuencia, las dos declaraciones anteriores compilan.
Pero en la siguiente declaración, el compilador nos marcara un error:
byte b = 526;
El compilador marca el siguiente error:
java: incompatible types: possible lossy conversion from int to byte
El valor 526 esta fuera del rango de los valores aceptados por una variable de tipo byte
. El compilador indica que no puede convertir este valor de tipo int
a tipo byte
. Si el valor establecido está dentro del rango de valores aceptables por el tipo byte
, el problema desaparece.
byte b = 100;
El mismo comportamiento observamos para el tipo short
, cuando intentamos inicializar la variable con un valor fuera del rango aceptable para este tipo.
El mismo error ocurre cuando intentamos inicializar una variable de tipo float
con un valor decimal literal (considerado como double
). La diferencia es que el compilador arrojará un error, incluso si el valor está en el rango aceptable del tipo float
:
float f = 10.5;
Arroja el error:
java: incompatible types: possible lossy conversion from double to float
Esto es debido a que debemos decirle explicitamente al compilador que interprete el valor literal como un valor de tipo float
. Para ello tenemos que agregar la letra F
al número, sirve tanto con la F
, como con f
.
float f = 10.5F;
// ó
float f = 10.5f;
Otro caso en el que es posible encontrar un error es cuando deseamos inicializar una variable de tipo long
con un valor numérico que excede el rango de valores aceptables para una variable de tipo int
.
long l = 10123456789;
Arroja el error:
java: integer number too large
Para corregir el problema, debemos indicar explicitamente al compilador que interprete el valor literal como un valor de tipo long
. Para ello tenemos que agregar la letra L
ó l
.
long l = 10123456789L;
// ó
long l = 10123456789l;
Los valores numéricos decimales se pueden expresar con notación decimal o con notación científica.
float superficie = 2356.8f;
// ó
float supercifie = 2.3568e3f;
Podemos insertar caracteres en valores numéricos literales para facilitar la lectura. Las siguientes dos sintaxis son iguales:
long l1 = 10123456789L;
long l2 = 10_123_456_789l;
d. El tipo carácter.
El tipo char
se utiliza para almacenar un carácter únicamente. Una variable de tipo char
usa dos bytes para almacenar el código Unicode del carácter. En el juego de caracteres Unicode los primeros 128 caracteres son idénticos al juego de caracteres ASCII, los caracteres siguientes, hasta el 255, corresponden a los caracteres especiales del alfabeto latino (por ejemplo, caracteres acentuados). El resto se utiliza para los símbolos o los caracteres de otros alfabetos.
char caracterC = 'c';
El carácter que queramos almacenar en una variable de tipo char
debe ir entre comillas simples ''
ya que las comillas dobles, hacen referencia a los valores String
, como veremos más adelante.
Los caracteres específicos o los que tienen un significado particular para Java se representan por una secuencia de escape, se componen del carácter \
seguido por otro carácter que indica el significado de la secuencia de escape.
Secuencia | Significado |
---|---|
\t |
Tabulación |
\b |
Retroceso |
\n |
Salto de línea |
\r |
Retorno de carro |
\f |
Salto de página |
\' |
Comilla simple |
\" |
Comilla doble |
\\ |
Barra invertida |
Los caracteres Unicode no accesibles por teclado se representan también mediante una secuencia de escape compuesta por \u
seguido por el valor hexadecimal del código Unicode del carácter. Por ejemplo el símbolo € tiene la secuencia hexadecimal 20AC, si queremos representarla mediante la secuencia de escape sería:
char euro = '\u20AC'
Esto en caso de que no podamos introducir el carácter por teclado, si no podríamos introducir directamente:
char euro = '€';
Una cadena de caracteres está representada por la clase String
, pero esto se verá mas adelante.
e. El tipo boolean.
El tipo boolean
permite tener una variable que únicamente puede presentar dos estados:
- true
- false
La asignación se hace directamente con los valores true
o false
.
boolean disponible, modificable;
disponible = true;
modificable = false;
Únicamente podemos asignar o el valor true
o false
.
5. Los valores por defecto.
No siempre es obligatoria la inicialización de las variables. Por ejemplo, es el caso de las variables de clase que se inicializan con los siguientes valores predeterminados:
Tipo | Valor por defecto |
---|---|
byte |
0 |
short |
0 |
int |
0 |
long |
0 |
float |
0.0 |
double |
0.0 |
char |
\u0000 |
boolean |
false |
Tipos por referencia | null |
Sin embargo, las variables locales deben inicializarse antes de ser utilizadas. El compilador de Java realiza una comprobación cuando encuentra el uso de una variable local y genera un error si la variable no se ha inicializado.
Esta estructura recuerda el ámbito de las variables:
public class NombreDeLaClase{
//Variables de instancia
//Variables de Clase
...unMetodo(ARGUMENTOS){
//Vasriables Locales
}
}
6. El ámbito de las variables.
El ámbito de una variable es la porción de código desde la que podemos manipular esta variable. Depende de dónde se encuentre esta declaración.
La declaración de una variable puede hacerse en:
- El bloque de código de una clase
- El bloque de código de una función
- Un bloque de código dentro de una función
Una variable solo puede ser utilizada en el bloque donde se declara y en los sub-bloques. Si el mismo bloque de código se ejecuta varias veces durante la ejecución de la función, en el caso de un ciclo while
por ejemplo, la variable se creará cada vez que pase por el ciclo.
Sin embargo, tenemos la opción de declarar una variable interna a una función o un argumento de una función con el mismo nombre que otra variable declarada a nivel de clase. Se implementa en este caso el principio de localidad. Por lo tanto, la variable local tiene prioridad sobre la variable declarada a nivel de clase. Para acceder a la variable de la clase es preciso que vaya precedida por la palabra clave this
(en el caso de una variable de instancia) o por el nombre de la clase en el caso de una variable de clase.
public class NombreDeLaClase{
int miVariableDeInstancia;
static int miVariableDeClase;
unMetodo(ARGUMENTOS){
int miVariableLocal;
if(expresión booleana){
int miVariableDeBloque;
}
}
}
Las variables miVariableDeInstancia
y miVariableDeClase
son accesibles en toda la clase (todos los métodos y todos los bloques dentro de métodos). Se puede acceder a la variable miVariableLocal
desde su declaración hasta el final del bloque en el que se declara (también es accesible en los sub-bloques de este bloque).
7. El ciclo de vida de las variables.
La vida útil de una variable nos permite especificar durante cuánto tiempo estará disponible el contenido de una variable, durante la ejecución de la aplicación.
Para una variable declarada en un método, el tiempo de vida se corresponde con la duración de la ejecución de este. Tan pronto como finaliza la ejecución del método, la variable se elimina de la memoria. Se vuelve a crear durante la próxima llamada al método.
Se puede usar una variable de instancia, siempre que la instancia esté disponible.
Se puede acceder a una variable de clase (declarada con la palabra clave static
) durante todo el tiempo de funcionamiento de la aplicación.
8. Ejemplos sobre variables y tipos.
public class DeclaracionVariables {
public static void main(String[] args) {
//Declaración de la variable:
byte edad;
//Inicialización de la variable:
edad = 23;
//Declaración e inicialización en la misma linea:
byte edad2 = 26;
System.out.println("El valor de la variable ANTES es: "+ edad);
//Podemos actualizar el valor de las variables durante el codigo.
edad = 59;
System.out.println("El valor de la variable DESPUES es: "+ edad);
}
}
El valor de la variable ANTES es: 23
El valor de la variable DESPUES es: 59
9. Ejercicios.
Crea una variable float llamada tamañoFrasco y asigna el valor 330.50.
float tamañoFrasco = 330.50F;
Crea una variable llamada velocidadMaxima y asigna el valor 120.
int velocidadMaxima = 120;
Añade el tipo correcto para las siguientes variables.
- miNumero = 9;
- miFloatNum = 8.99f;
- miLetra = ‘O’;
- miBooleano = false;
int miNumero = 9;
float miFloatNum = 8.99f;
char miLetra = 'O';
boolean miBooleano = false;
Crea una clase con el nombre de Ejercicio_1. Declara e inicializa las siguientes variables.
Nombre Variable | Tipo de dato | Valor de la variable |
---|---|---|
nombre | Texto | Teresa |
edad | Entero corto | 22 |
salario | Decimal corto | 1850,99 |
carnet | lógico | verdadero |
public class Ejercicio_1 {
public static void main(String[] args) {
String nombre = "Teresa";
byte edad = 22;
float salario = 1850.99f;
boolean carnet = true;
}
}
El ejercicio pide únicamente declarar e inicializar las variables, pero vamos a ver como podemos mostrar esta información en pantalla.
Aunque ha salido al comienzo del capitulo, en el primer ejemplo, para pintar información en pantalla utilizamos la sintaxis:
System.out.println();
De momento no vamos a explicar esta sentencia, únicamente debemos saber que para pintar información en consola debemos utilizar esta sintaxis.
Vamos a añadir a nuestro programa que muestre los valores de la variable en la pantalla:
public class Ejercicio_1 {
public static void main(String[] args) {
String nombre = "Teresa";
byte edad = 22;
float salario = 1850.99f;
boolean carnet = true;
System.out.println(nombre);
System.out.println(edad);
System.out.println(salario);
System.out.println(carnet);
}
}
Si ejecutamos el programa:
Vemos como nos muestra el valor de las variables, pero podemos añadirle texto para dar formato y contexto al programa, para ello en el paréntesis, entre comillas ""
introducimos el texto que queremos mostrar, después el operador concatenación +
lo concatena con la variable o con mas texto. No te preocupes todo esto se explicará próximamente, únicamente intenta entender el ejemplo.
public class Ejercicio_1 {
public static void main(String[] args) {
String nombre = "Teresa";
byte edad = 22;
float salario = 1850.99f;
boolean carnet = true;
System.out.println("Nombre: " + nombre);
System.out.println("Edad: " + edad + " años");
System.out.println("Salario: " + salario + " euros");
System.out.println("Carnet: " + carnet);
}
}
El resultado del programa es:
¿Cuál de las siguientes opciones representa la sintaxis correcta del método principal de una clase en Java?
a) public void main(String args)
b) static void main(String args)
c) public static void main(String args) (Correcta)
d) void main(String args)
La opción correcta es la c) public static void main(String[] args).
¿Cuál de las siguientes definiciones describe correctamente una “palabra reservada” en Java?
a) Identificadores predefinidos con significado para el propio compilador y que no pueden utilizarse como identificadores creados por el usuario en los programas.
b) Palabras clave que se utilizan para declarar variables en Java.
c) Términos específicos utilizados en la documentación oficial de Java.
d) Funciones predefinidas que realizan operaciones específicas en Java.
La opción correcta es la a) “Identificadores predefinidos con significado para el propio compilador y que no pueden utilizarse como identificadores creados por el usuario en los programas.”
¿Qué es una variable en Java?
a) Nombre dado a un método en Java.
b) Palabra reservada que indica una operación específica en Java.
c) Tipo de dato utilizado para almacenar números enteros en Java.
d) Espacio en la memoria del ordenador donde se almacenará un valor que podrá cambiar durante la ejecución del programa.
La opción correcta es la d) “Espacio en la memoria del ordenador donde se almacenará un valor que podrá cambiar durante la ejecución del programa.”
El tipo primitivo
int
:
a) Representa un número decimal con precisión simple en Java.
b) Es una palabra reservada utilizada para declarar métodos en Java.
c) Permite almacenar números enteros ocupando un espacio de 4 bytes en memoria.
d) Define una secuencia de caracteres en Java.
La opción correcta es la c) “Permite almacenar números enteros ocupando un espacio de 4 bytes en memoria.”
El código bytecode:
a) Código intermedio entre código Java y código máquina resultado de compilar un programa Java y que se almacena en un fichero con extensión .class
b) Conjunto de instrucciones específicas utilizadas para la lógica de programación en Java.
c) Archivo de texto plano que contiene el código fuente de un programa Java.
d) Documentación detallada sobre el funcionamiento de un programa Java.
La opción correcta es la a) “Código intermedio entre código Java y código máquina resultado de compilar un programa Java y que se almacena en un fichero con extensión .class”
En la siguiente leccion veremos las constantes y los operadores, cualquier inquietud podeis dejarla abajo! Espero que os haya sido util.