Este capítulo analiza las características fundamentales de Java como lenguaje de programación. Entender estas características te ayudará a comprender por qué el código se escribe de cierta manera y qué ventajas ofrece Java frente a otros lenguajes.
Java se destaca por:
Ser un lenguaje de propósito general (sirve para casi cualquier tipo de programa)
Tener un sistema de tipos estático y fuerte (el compilador verifica los tipos antes de ejecutar)
Estar orientado a objetos por diseño (aunque esto se estudiará más adelante)
Lenguaje de Propósito General¶
Java es un lenguaje de propósito general, lo que significa que no está diseñado para resolver un único tipo de problema específico, sino que puede utilizarse para desarrollar prácticamente cualquier tipo de software.
¿Qué significa “propósito general”?¶
Para entender esto, primero hay que conocer la diferencia con los lenguajes de dominio específico (DSL - Domain Specific Languages). Estos son lenguajes diseñados para resolver un problema muy particular:
SQL (Structured Query Language): Diseñado específicamente para consultar y manipular bases de datos. Podés escribir
SELECT * FROM usuarios WHERE edad > 18, pero no podés crear una interfaz gráfica ni un servidor web con SQL.HTML (HyperText Markup Language): Define la estructura de páginas web. Podés marcar títulos, párrafos e imágenes, pero no podés hacer cálculos matemáticos ni procesar archivos.
CSS (Cascading Style Sheets): Controla la presentación visual de páginas web (colores, fuentes, layouts). Solo sirve para eso, no para lógica de negocio.
MATLAB: Especializado en computación numérica, matrices y visualización de datos científicos. Excelente para ingeniería, pero no para hacer una aplicación de chat.
Expresiones Regulares (Regex): Un mini-lenguaje para describir patrones de texto. Útilísimo para validar emails o buscar en texto, pero no es un lenguaje de programación completo.
En contraste, un lenguaje de propósito general como Java (o C, Python, C++, Go) puede usarse para crear:
Aplicaciones donde Java es utilizado¶
Table 1:Aplicaciones de Java por dominio
Dominio | Ejemplos concretos | Tecnologías/Frameworks comunes |
|---|---|---|
Aplicaciones empresariales | Sistemas bancarios (procesamiento de transacciones), sistemas ERP (gestión empresarial), sistemas CRM (gestión de clientes) | Spring, Jakarta EE, Hibernate |
Aplicaciones web (backend) | Servidores que procesan peticiones HTTP, APIs RESTful, microservicios | Spring Boot, Micronaut, Quarkus |
Aplicaciones móviles | Aplicaciones Android nativas | Android SDK, Kotlin/JVM |
Aplicaciones de escritorio | IDEs como IntelliJ IDEA y Eclipse, herramientas de productividad | JavaFX, Swing |
Sistemas embebidos | Dispositivos IoT, tarjetas inteligentes (como las SIM de celulares), Blu-ray players | Java ME, Embedded Java |
Big Data | Procesamiento de datos masivos, análisis en tiempo real, pipelines de datos | Hadoop, Apache Spark, Apache Kafka, Apache Flink |
Juegos | Minecraft (escrito completamente en Java), juegos indie | LWJGL (gráficos OpenGL), jMonkeyEngine, libGDX |
¿Significa que Java es la mejor opción para todo?¶
No. Ser de propósito general significa que Java puede usarse para casi cualquier cosa, pero no que sea la mejor opción para todo. Cada lenguaje tiene fortalezas:
Ventajas de aprender un lenguaje de propósito general¶
Reutilización de conocimientos: Una vez que dominás Java, podés trabajar en aplicaciones web, Android, sistemas distribuidos, o Big Data sin aprender un lenguaje completamente nuevo.
Ecosistema unificado: Usás las mismas herramientas (IDEs, sistemas de build, bibliotecas base) sin importar el tipo de proyecto.
Comunidad amplia: Hay millones de desarrolladores Java en el mundo. Cualquier problema que tengas, probablemente alguien ya lo resolvió y documentó.
Tipado Estático y Fuerte¶
Java implementa un sistema de tipado estático y fuerte. Esta característica fundamental influye profundamente en cómo se escribe, se verifica y se ejecuta el código.
¿Qué es un “tipo” en programación?¶
Un tipo de dato define tres cosas importantes:
Qué valores puede almacenar una variable: Un
intalmacena números enteros, unStringalmacena texto, unbooleanalmacena verdadero o falso.Cuánta memoria ocupa: Un
inten Java siempre ocupa 4 bytes (32 bits), undoublesiempre ocupa 8 bytes (64 bits).Qué operaciones son válidas: Podés sumar dos
int, pero no podés sumar unintcon unStringdirectamente (aunque sí concatenarlos).
En C ya trabajaste con tipos: int, float, double, char, punteros, structs. Java tiene un sistema de tipos similar pero más estricto.
Tipado Estático: los tipos se verifican ANTES de ejecutar¶
En un lenguaje con tipado estático, el tipo de cada variable:
Se declara explícitamente (con algunas excepciones modernas)
Se conoce en tiempo de compilación (antes de ejecutar el programa)
No puede cambiar durante la ejecución del programa
El compilador verifica que todas las operaciones de tipos sean correctas antes de crear el ejecutable. Si hay un error de tipos, el programa ni siquiera compila.
Ejemplo: Declaración de Variables¶
No se preocupen por los detalles del siguiente código, en la siguiente página del apunte veremos detalles más profundos de este tema, por ahora, aprovechemos las similitudes con C.
int edad = 25; // 'edad' es de tipo int, para siempre
String nombre = "Ana"; // 'nombre' es de tipo String, para siempre
// Esto funciona: asignar un nuevo valor del MISMO tipo
edad = 30; // ✅ OK: 30 también es int
// Esto NO compila: intentar cambiar el tipo de valor
edad = "treinta"; // ❌ Error de compilación: String no es int¿Qué significa “tiempo de compilación” vs “tiempo de ejecución”?¶
Esta distinción es fundamental:
Tiempo de compilación (compile time): Es cuando el compilador
javaclee tu código fuente (.java) y lo convierte a bytecode (.class). En esta etapa, el compilador verifica la sintaxis y los tipos. Si hay errores, no se genera el bytecode y no podés ejecutar nada.Tiempo de ejecución (runtime): Es cuando la JVM ejecuta el bytecode compilado. El programa ya pasó la verificación del compilador y está “corriendo”. Los errores aquí son excepciones que ocurren mientras el programa funciona.
El tipado estático detecta errores de tipos en tiempo de compilación, lo que significa que te enterás del error antes de ejecutar el programa, antes de que llegue a producción, antes de que un usuario lo vea.
Comparación con Tipado Dinámico¶
En lenguajes con tipado dinámico como Python, las variables no tienen tipos fijos. El tipo se determina en tiempo de ejecución, según el valor asignado en cada momento:
Python (tipado dinámico):
edad = 25 # edad contiene un int
print(type(edad)) # <class 'int'>
edad = "treinta" # ✅ Ahora edad contiene un str (¡sin error!)
print(type(edad)) # <class 'str'>
edad = [1, 2, 3] # ✅ Ahora edad contiene una lista
print(type(edad)) # <class 'list'>Este código Python ejecuta sin problemas. Pero esto puede causar errores inesperados:
def calcular_doble(x):
return x * 2
print(calcular_doble(5)) # 10 (OK, número)
print(calcular_doble("hola")) # "holahola" (¿¡¿Qué?!? String repetido)¿Es esto un bug o una feature? Depende de tu intención, pero el punto es que Python no te avisa que algo raro está pasando.
Java (tipado estático):
int edad = 25;
edad = "treinta"; // ❌ Error de compilación: esto no se llega a ejecutarEl compilador de Java te fuerza a pensar en los tipos desde el principio. Esto puede parecer restrictivo, pero en proyectos grandes con múltiples desarrolladores, previene categorías enteras de bugs.
Tipado Fuerte: conversiones explícitas obligatorias¶
Java también implementa tipado fuerte, lo que significa que no permite conversiones automáticas entre tipos cuando podría haber pérdida de información o ambigüedad. Si querés convertir entre tipos, debés hacerlo explícitamente mediante casting.
¿Qué es el casting?¶
El casting (conversión de tipos) es decirle explícitamente al compilador: “Sé que estos tipos son diferentes, pero quiero hacer esta conversión de todas formas”. La sintaxis es poner el tipo destino entre paréntesis antes del valor:
double precio = 19.99;
int precioEntero = (int) precio; // Casting explícito: convierte a int
System.out.println(precioEntero); // Imprime: 19 (se pierde el .99)El (int) es el casting. Estás diciendo “convertí este double a int”. El compilador acepta porque vos lo pediste explícitamente, pero te advierte implícitamente que hay pérdida de información (se pierde el .99).
¿Por qué Java no hace esto automáticamente?¶
Sin el casting, este código no compila:
double precio = 19.99;
int precioEntero = precio; // ❌ Error: possible lossy conversion from double to intComparación con Tipado Dinámico (Python)¶
En lenguajes con tipado dinámico como Python, las variables no tienen tipos fijos:
edad = 25 # edad contiene un int
edad = "treinta" # ✅ Ahora edad contiene un str (¡sin error!)
edad = [1, 2, 3] # ✅ Ahora edad contiene una listaEste código Python ejecuta sin problemas, pero puede causar errores inesperados en tiempo de ejecución. Java detecta estos problemas en tiempo de compilación, antes de que el programa se ejecute.
Ventajas del tipado estático y fuerte¶
Ahora que entendés la diferencia, veamos por qué Java eligió este enfoque:
Detección temprana de errores: Muchos bugs se detectan en tiempo de compilación, antes de ejecutar el programa. No necesitás ejecutar todos los casos posibles para encontrar un error de tipos —el compilador lo encuentra por vos.
Mejor rendimiento: El compilador conoce los tipos de antemano, entonces puede generar código más eficiente. No necesita verificar tipos en cada operación durante la ejecución.
Herramientas inteligentes: Los IDEs (como IntelliJ o Eclipse) pueden ofrecerte:
Autocompletado preciso: Saben qué métodos y propiedades tiene cada variable
Refactorización segura: Pueden renombrar variables o métodos en todo el proyecto sin romper nada
Detección de errores en tiempo real: Ves los errores mientras escribís, no al ejecutar
Documentación implícita: Los tipos actúan como documentación. Cuando ves:
public double calcularImpuesto(double monto, double tasa)Sabés inmediatamente que la función recibe dos números decimales y devuelve otro decimal. No necesitás leer la documentación o el código interno.
Contratos claros: Los tipos establecen “contratos” entre diferentes partes del código. Si una función espera un
String, no podés pasarle unintpor error.
Tabla comparativa de sistemas de tipos¶
Table 2:Comparación de sistemas de tipos
Característica | Java | Python | C |
|---|---|---|---|
Tipado | Estático y fuerte | Dinámico y fuerte | Estático y débil |
Declaración de tipos | Obligatoria | Opcional (type hints desde Python 3.5) | Obligatoria |
Conversiones implícitas | Solo widening (sin pérdida) | Limitadas | Muchas (especialmente con punteros) |
Detección de errores de tipos | Compilación | Ejecución | Compilación (parcial) |
La Estructura Obligatoria: Clases en Java¶
Aunque Java es fundamentalmente un lenguaje orientado a objetos, en las primeras etapas del aprendizaje trabajaremos principalmente con los aspectos procedurales del lenguaje: tipos de datos, operadores, estructuras de control y funciones (que en Java se llaman “métodos”).
¿Por qué todo debe estar en una clase?¶
Esta es una diferencia importante con C. En C, podés escribir funciones “sueltas”:
En C:
#include <stdio.h>
// Función suelta, no pertenece a ninguna estructura
int sumar(int a, int b) {
return a + b;
}
int main() {
printf("%d\n", sumar(3, 5));
return 0;
}En Java, esto no es posible. Todo código debe estar dentro de una clase:
public class Calculadora { // ← Todo dentro de una clase
public static int sumar(int a, int b) {
return a + b;
}
public static void main(String[] args) {
System.out.println(sumar(3, 5));
}
}¿Por qué Java toma esta decisión? Porque fue diseñado desde cero como un lenguaje orientado a objetos. La filosofía es: “todo es un objeto” (o pertenece a una clase que puede crear objetos). Incluso cuando no necesitás objetos, la estructura de clase está presente.
La clase como “contenedor obligatorio”¶
Por ahora, pensá en la clase como un contenedor obligatorio para tu código. Es como un archivo en C, pero con reglas adicionales:
El nombre del archivo debe coincidir con el nombre de la clase pública. Si tu clase se llama
Calculadora, el archivo debe llamarseCalculadora.java.Cada archivo
.javatípicamente contiene una clase pública. Puede contener más clases, pero solo una puede serpublic.El método
maines el punto de entrada, igual que en C, pero debe estar dentro de una clase.
El programa Java más simple¶
public class HolaMundo {
public static void main(String[] args) {
System.out.println("¡Hola, mundo!");
}
}Descomponiendo cada parte:
public: Modificador de acceso. Significa que esta clase/método es accesible desde cualquier otro código. (Más adelante verás otros comoprivateyprotected.)class HolaMundo: Declara una clase llamadaHolaMundo. El archivo debe llamarseHolaMundo.java.static: Indica que el método pertenece a la clase, no a un objeto instanciado. Esto es crucial paramainy para nuestro uso inicial.void: El método no devuelve ningún valor (igual que en C).main: Nombre especial que la JVM busca como punto de entrada.String[] args: Parámetro que recibe argumentos de línea de comandos (igual quechar* argv[]en C).System.out.println(...): Forma de imprimir en Java.System.outes el equivalente astdouten C.
Métodos Estáticos: Funciones sin necesidad de objetos¶
En las primeras semanas del curso, escribirás métodos dentro de clases, pero
todos serán estáticos (con la palabra clave static).
¿Qué significa static?¶
La palabra static significa que el método (o variable) pertenece a la clase misma, no a los objetos que podrían crearse a partir de ella.
Para entenderlo con una analogía:
Una clase es como un molde para hacer galletas
Un objeto es una galleta hecha con ese molde
Un método estático es algo que podés hacer con el molde directamente, sin necesidad de hacer galletas primero
Esto se verá en profundidad cuando estudies OOP. Por ahora, lo importante es:
Con
static: Podés llamar al método directamente usando el nombre de la clase:Calculadora.sumar(3, 5)Sin
static: Necesitarías crear un objeto primero (lo verás más adelante)
Ejemplo: Biblioteca de funciones matemáticas¶
public class Matematica {
// Método estático: se puede llamar sin crear un objeto
public static int sumar(int a, int b) {
return a + b;
}
public static int restar(int a, int b) {
return a - b;
}
public static double promediar(double[] numeros) {
if (numeros.length == 0) {
return 0.0; // Evitar división por cero
}
double suma = 0;
for (double num : numeros) {
suma += num;
}
return suma / numeros.length;
}
public static int factorial(int n) {
if (n < 0) {
return -1; // Indicar error (factorial no definido para negativos)
}
int resultado = 1;
for (int i = 2; i <= n; i++) {
resultado *= i;
}
return resultado;
}
public static void main(String[] args) {
// Llamadas a métodos estáticos desde la misma clase
// (no hace falta escribir "Matematica.")
int suma = sumar(5, 3);
System.out.println("5 + 3 = " + suma);
int resta = restar(10, 4);
System.out.println("10 - 4 = " + resta);
double[] valores = {10.0, 20.0, 30.0, 40.0};
double promedio = promediar(valores);
System.out.println("Promedio: " + promedio);
System.out.println("5! = " + factorial(5));
}
}Salida:
5 + 3 = 8
10 - 4 = 6
Promedio: 25.0
5! = 120Llamar métodos estáticos desde otra clase¶
Si querés usar estos métodos desde otro archivo, usás el nombre de la clase:
// Archivo: OtroPrograma.java
public class OtroPrograma {
public static void main(String[] args) {
// Llamada con nombre de clase completo
int resultado = Matematica.sumar(100, 200);
System.out.println("Resultado: " + resultado);
// También podemos usar factorial
System.out.println("10! = " + Matematica.factorial(10));
}
}Este es exactamente el mismo patrón que usás con métodos de Java como Math.sqrt(), Math.abs(), Integer.parseInt(), etc. Son métodos estáticos de clases de la biblioteca estándar.
¿Por qué empezar con métodos estáticos?¶
Este enfoque te permite:
Concentrarte en la lógica algorítmica: Pensás en cómo resolver problemas con funciones, entrada y salida, sin la complejidad adicional de objetos.
Reutilizar conocimientos de C: La estructura
funcion(parámetros) → resultadoes idéntica conceptualmente. Solo cambia un poco la sintaxis.Dominar tipos de datos y estructuras de control: Practicás con
if,for,while, arreglos, etc., antes de agregar la capa de objetos.Prepararte para OOP gradualmente: Cuando llegue el momento de crear objetos, ya dominarás la sintaxis y podrás concentrarte en los conceptos nuevos.
Diferencias Clave entre Java y C¶
Dado que venís de programar en C, es útil tener un resumen de las diferencias principales que encontrarás al empezar con Java:
Table 3:Comparación Java vs C
Aspecto | C | Java |
|---|---|---|
Gestión de memoria | Manual ( | Automática (Garbage Collector) |
Punteros | Acceso directo a memoria | No existen (solo referencias a objetos) |
Estructura del código | Funciones sueltas | Todo dentro de clases |
Arreglos | No verifican límites (buffer overflow posible) | Verifican límites (lanza excepción) |
Strings | Arrays de | Tipo |
Booleanos | No existe (se usa | Tipo |
Compilación | A código máquina nativo | A bytecode (ejecuta en JVM) |
Portabilidad | Recompilar para cada plataforma | El mismo bytecode en cualquier JVM |
Archivos header |
| No existen (todo en |
Preprocesador |
| No existe |
Ejemplo lado a lado¶
El mismo programa en C y Java:
// programa.c
#include <stdio.h>
int calcular_suma(int arr[], int n) {
int suma = 0;
for (int i = 0; i < n; i++) {
suma += arr[i];
}
return suma;
}
int main() {
int numeros[] = {1, 2, 3, 4, 5};
int n = sizeof(numeros) / sizeof(numeros[0]);
int resultado = calcular_suma(numeros, n);
printf("La suma es: %d\n", resultado);
return 0;
}// Programa.java
public class Programa {
public static int calcularSuma(int[] arr) {
int suma = 0;
for (int i = 0; i < arr.length; i++) { // .length en vez de pasar n
suma += arr[i];
}
return suma;
}
public static void main(String[] args) {
int[] numeros = {1, 2, 3, 4, 5};
int resultado = calcularSuma(numeros); // No necesita pasar el tamaño
System.out.println("La suma es: " + resultado);
}
}Diferencias a notar:
No hay
#include: Java usaimportpara traer clases de otros paquetes, pero las clases básicas están disponibles automáticamente.Todo dentro de clase: El código está envuelto en
public class Programa { ... }.Métodos son
static: Equivalente a funciones libres de C para nuestro uso inicial.int[]en vez deint arr[]: Java prefiere poner los corchetes junto al tipo, no junto al nombre de la variable.arr.lengthen vez de pasar tamaño: Los arreglos en Java conocen su propio tamaño. No hay que calcularlo ni pasarlo como parámetro.System.out.printlnen vez deprintf: Diferente API para salida estándar. Java también tieneSystem.out.printf()si preferís format strings.Concatenación con
+: En vez de usar%dy format strings, Java permite concatenar directamente strings con números.
Resumen¶
Java se caracteriza por ser:
Lenguaje de propósito general: Puede usarse para casi cualquier tipo de software (empresarial, web, móvil, embebido, Big Data, juegos), aunque no siempre es la mejor opción para cada dominio específico.
Tipado estático: Los tipos de las variables se declaran explícitamente y se verifican en tiempo de compilación. El compilador detecta errores de tipos antes de que el programa ejecute.
Tipado fuerte: Las conversiones entre tipos incompatibles deben ser explícitas (casting). Java no “adivina” qué conversión querés hacer —te obliga a ser explícito sobre posibles pérdidas de información.
Orientado a objetos por diseño: Todo código debe estar dentro de clases. Inicialmente usamos métodos
staticpara trabajar de forma similar a C, pero la estructura de clase siempre está presente.Diferencias principales con C:
No hay punteros ni gestión manual de memoria
Los arreglos conocen su tamaño y verifican límites
Todo está dentro de clases
Tipo
booleannativo yStringcomo tipo de primera clase
La estrategia pedagógica “Late Objects” que usamos en este curso permite dominar primero los fundamentos del lenguaje (tipos, operadores, estructuras de control, métodos) antes de abordar los conceptos de programación orientada a objetos. Esto aprovecha tu conocimiento previo de C mientras te prepara gradualmente para las características más avanzadas de Java.
Referencias Bibliográficas¶
Gosling, J., Joy, B., Steele, G., & Bracha, G. (2005). The Java Language Specification (3rd ed.). Addison-Wesley Professional.
Bloch, J. (2018). Effective Java (3rd ed.). Addison-Wesley Professional.
Eckel, B. (2006). Thinking in Java (4th ed.). Prentice Hall.
Deitel, P., & Deitel, H. (2017). Java How to Program, Early Objects (11th ed.). Pearson.
Oracle Corporation. (n.d.). The Java Tutorials. Recuperado de https://
docs .oracle .com /javase /tutorial/
Ejercicios¶
Solution to Exercise 1
El código genera un error porque Java tiene tipado fuerte y no permite conversiones implícitas que puedan causar pérdida de información (narrowing). En este caso, convertir de double a int implica descartar la parte decimal.
Solución:
double precio = 19.99;
int precioEntero = (int) precio; // Casting explícito
System.out.println(precioEntero); // 19El casting explícito (int) indica al compilador que el programador es
consciente de la posible pérdida de precisión.
```{exercise}
:label: ej-metodos-estaticos
Escribí un método estático `esPar` que reciba un número entero y devuelva `true` si es par y `false` si es impar. Luego, crea un método `main` que lo pruebe.
```
````{solution} ej-metodos-estaticos
:class: dropdown
```java
public class Utilidades {
public static boolean esPar(int numero) {
return numero % 2 == 0;
}
public static void main(String[] args) {
System.out.println("4 es par: " + esPar(4)); // true
System.out.println("7 es par: " + esPar(7)); // false
System.out.println("-2 es par: " + esPar(-2)); // true
}
}
```
**Nota:** El operador `%` (módulo) devuelve el resto de la división. Si el resto
de dividir por 2 es 0, el número es par.
Solution to Exercise 2
Java fue diseñado desde sus orígenes como un lenguaje puramente orientado a objetos. Esta decisión arquitectónica significa que:
No existen funciones globales: Todo método debe pertenecer a una clase.
El punto de entrada es un método: El método
maindebe estar dentro de una clase para que la JVM pueda ejecutarlo.Organización consistente: Incluso programas simples siguen la misma estructura que aplicaciones complejas.
Ventajas:
Consistencia: Todo el código sigue las mismas reglas.
Escalabilidad: Es fácil expandir un programa simple a uno complejo.
Integración: El código se organiza naturalmente en unidades reutilizables.
Ejemplo mínimo:
public class HolaMundo {
public static void main(String[] args) {
System.out.println("¡Hola!");
}
}Aunque usemos static para evitar crear objetos inicialmente, la estructura de
clase está presente desde el principio.
Solution to Exercise 3
No, ser de propósito general no significa ser óptimo para todos los casos. La elección del lenguaje depende del contexto:
Cuándo Java es una buena elección:
Aplicaciones empresariales complejas (Spring Boot, Jakarta EE).
Sistemas que requieren portabilidad entre plataformas.
Proyectos con requisitos de escalabilidad y mantenibilidad a largo plazo.
Cuándo otros lenguajes pueden ser mejores:
Python: Scripts rápidos, ciencia de datos, machine learning (bibliotecas como NumPy, TensorFlow).
Python es preferido para: scripts rápidos, ciencia de datos, machine learning (bibliotecas como NumPy, TensorFlow, PyTorch).
C/C++: Sistemas embebidos, drivers, software que requiere máximo rendimiento (motores gráficos, sistemas operativos).
Go: Microservicios ligeros con alta concurrencia.
Rust: Sistemas donde la seguridad de memoria es crítica.
Conclusión: Java es versátil, pero la mejor herramienta depende del problema específico, el ecosistema existente y las competencias del equipo.
Solution to Exercise 4
Análisis del programa:
public class Conversor: Define una clase llamadaConversorque actúa como contenedor del código. El archivo debe llamarseConversor.java.public static double celsiusAFahrenheit(double celsius):public: Accesible desde cualquier parte del código.static: Pertenece a la clase, no necesita un objeto para ser llamado.double: Tipo de retorno, el método devuelve un número decimal.celsiusAFahrenheit: Nombre del método (convención camelCase en Java).(double celsius): Parámetro de tipodouble.La fórmula
(celsius * 9.0 / 5.0) + 32.0convierte Celsius a Fahrenheit.
public static void main(String[] args):Punto de entrada del programa (la JVM busca este método para comenzar).
void: No devuelve ningún valor.String[] args: Arreglo de strings con argumentos de línea de comandos.
System.out.println(...): Imprime una línea en la salida estándar. El operador+concatena los valores en un solo String.
Salida esperada:
25.0°C = 77.0°FConceptos clave demostrados:
Estructura obligatoria de clase
Métodos estáticos (sin necesidad de objetos)
Tipado explícito (
double)Concatenación de String con
+
Solution to Exercise 5
Análisis línea por línea:
int a = 100;— ✅ Compila. Declaración simple de entero.long b = a;— ✅ Compila. Widening automático:int(32 bits) →long(64 bits). No hay pérdida de información.double c = b;— ✅ Compila. Widening automático:long(64 bits entero) →double(64 bits punto flotante). Seguro para la mayoría de valores.int d = c;— ❌ No compila. Narrowing:double→intpodría perder información (la parte decimal). Solución:int d = (int) c;byte e = a;— ❌ No compila. Narrowing:int(32 bits) →byte(8 bits). El valor 100 cabe en un byte, pero el compilador no lo sabe en general. Solución:byte e = (byte) a;float f = 3.14;— ❌ No compila. Los literales decimales como3.14sondoublepor defecto. Asignardoubleafloates narrowing. Solución 1:float f = 3.14f;(sufijofindica literal float) Solución 2:float f = (float) 3.14;
Regla general: Las conversiones de “mayor a menor” (long→int, double→float, int→byte) requieren casting explícito porque pueden perder información.
Solution to Exercise 6
public class Comparador {
public static int maximo(int a, int b) {
if (a > b) {
return a;
} else {
return b;
}
}
public static void main(String[] args) {
int x = 10, y = 25;
int resultado = maximo(x, y);
// Opción 1: Concatenación con +
System.out.println("El máximo entre " + x + " y " + y + " es " + resultado);
// Opción 2: printf (más similar a C)
System.out.printf("El máximo entre %d y %d es %d%n", x, y, resultado);
}
}Cambios realizados:
Todo el código está dentro de
public class ComparadorSe agregó
statica los métodosSe eliminó
#include(Java no usa preprocesador)printfse convierte enSystem.out.printfo se usa concatenaciónEn
printfde Java, usamos%nen vez de\npara portabilidadNo hace falta
return 0;enmainde Java (esvoid)
````{exercise}
:label: ej-tipado-estatico-dinamico
Explicá qué imprimiría cada línea en Python y qué pasaría si intentaras lo mismo en Java:
```python
print("5" + str(3))
print("5" + 3)
print("5" * 3)
print(int("5") + 3)
```{solution} ej-tipado-estatico-dinamico
:class: dropdown
**En Python (tipado dinámico y fuerte):**
1. `print("5" + str(3))` → `"53"`
- Convertimos explícitamente `3` a string con `str()`
- Luego concatenamos dos strings
2. `print("5" + 3)` → ❌ `TypeError: can only concatenate str (not "int") to str`
- Python **no** convierte implícitamente int a str
- Es tipado **fuerte**: rechaza mezclar tipos incompatibles
3. `print("5" * 3)` → `"555"`
- En Python, `str * int` es **repetición de string**
- Esta es una operación válida definida para strings
4. `print(int("5") + 3)` → `8`
- Convertimos explícitamente `"5"` a entero con `int()`
- Sumamos dos enteros
**En Java (tipado estático y fuerte):**
1. `System.out.println("5" + 3);` → `"53"` ✅
- Java permite concatenación de String con otros tipos usando `+`
- Es la **única excepción** a las reglas estrictas de tipos
2. En Java no necesitás `str()`, el `+` con String ya convierte
- `System.out.println("5" + 3);` funciona directamente
3. `System.out.println("5" * 3);` → ❌ **Error de compilación**
- Java **no** tiene operador de repetición de string
- Para repetir: `"5".repeat(3)` (desde Java 11) → `"555"`
4. `System.out.println(Integer.parseInt("5") + 3);` → `8` ✅
- Usamos `Integer.parseInt()` en vez de `int()`
- La sintaxis cambia, pero el concepto es igual
**Diferencia clave:** Tanto Python como Java son de tipado **fuerte** y rechazan mezclar tipos incompatibles. La diferencia es que Java detecta los errores en **compilación** (antes de ejecutar), mientras que Python los detecta en **ejecución** (cuando llega a esa línea).
```
---
**Anterior:** {ref}`Orígenes e Historia de Java <apunte/01_origenes.md>`
**Siguiente:** Continuá explorando los fundamentos de Java con los tipos de
datos primitivos y operadores.