5. Operadores
UD1 — Fundamentos de Programación
IES Thiar · Curso 2026 - 2027
| Aspecto | Valor |
|---|---|
| Resultado de aprendizaje | RA1 — Reconoce la estructura de un programa informático, identificando y relacionando los elementos propios del lenguaje de programación utilizado. |
| Criterios de evaluación cubiertos | CE 1.7 — Se han clasificado, reconocido y utilizado en expresiones los operadores del lenguaje. |
| Marco normativo | RD 405/2023 · RD 450/2010 · RD 659/2023 |
| Tecnología base | Java 25 LTS — operadores clásicos + pattern matching para instanceof (Java 16+). |
Introducción de la sección
Hasta ahora has creado variables, las has inicializado y las has mostrado por pantalla. Pero un programa que solo "guarda y muestra" no hace nada interesante: para que un programa de verdad sirva para algo, necesita calcular, comparar y decidir. Y para eso están los operadores. Un operador es un símbolo que toma uno o varios valores (llamados operandos) y produce un resultado: + suma, == compara, && combina condiciones, ++ incrementa. Java tiene más de 40 operadores repartidos en categorías: aritméticos, relacionales, lógicos, de asignación, de incremento, ternarios, de tipo...
El objetivo de esta sección es que conozcas los operadores esenciales de Java, que aprendas a combinarlos en expresiones y que entiendas los detalles que más sorprenden al principiante: por qué 5 / 2 da 2 y no 2.5 (división entera), qué significa eso del cortocircuito en && y ||, la diferencia entre ++i y i++ (que ha generado más bugs de los se admiten), y cómo el orden en que se evalúan los operadores (la precedencia) puede dar resultados inesperados si no usas paréntesis. Cuando acabes, sabrás escribir expresiones correctas y leer las de otros sin tropezar.
5.1 El operador de asignación =
Llevas usándolo desde la Sección 4: int edad = 25;. Pero hasta ahora lo has tratado como una instrucción más. En realidad, = es un operador —el de menor precedencia de todos (nivel 14 en la tabla de la Sección 5.9)— y tiene reglas propias que conviene conocer formalmente.
Cómo funciona: el lado derecho se evalúa primero
La asignación siempre sigue este orden:
- Se evalúa la expresión a la derecha del
=. - Se almacena el resultado en la variable a la izquierda.
Esto explica por qué esto funciona:
No hay paradoja: cuando Java evalúa x + 1, x aún vale 5. El 6 resultante se guarda después en x.
El lado izquierdo debe ser una variable
El lado izquierdo del = tiene que ser algo que pueda recibir un valor: una variable declarada. No puede ser un literal ni una expresión compuesta:
Asignación encadenada
= es asociativo por la derecha. Esto permite asignar un mismo valor a varias variables en una sola línea:
La asignación encadenada es legítima, pero en código profesional se prefiere una línea por variable para claridad.
= no es «igual a» en matemáticas
En matemáticas, x = x + 1 es una ecuación sin solución. En programación, es una instrucción que incrementa x en 1. No pienses en = como «igual a», piensa en él como «almacena en» o «toma el valor de».
5.2 Operadores aritméticos: la aritmética de la CPU
Los operadores aritméticos son los más familiares: suma, resta, multiplicación, división y módulo. Java los hereda de C/C++ y se comportan casi como en matemáticas, pero con dos trampas importantes que conviene desterrar desde el primer día.
Tabla de operadores aritméticos
| Operador | Operación | Ejemplo | Resultado | Notas |
|---|---|---|---|---|
+ |
Suma | 5 + 3 |
8 |
También concatena String |
- |
Resta | 5 - 3 |
2 |
También es operador unario: -x |
* |
Multiplicación | 5 * 3 |
15 |
|
/ |
División | 5 / 2 |
2 (¡no 2.5!) |
División entera si ambos operandos son enteros |
% |
Módulo (resto) | 5 % 2 |
1 |
Resto de la división entera |
La trampa de la división entera
Si en Java escribes 5 / 2, el resultado es 2, no 2.5. La razón es que cuando los dos operandos son enteros, Java realiza división entera: trunca los decimales hacia cero. Esto es la fuente número 1 de bugs aritméticos en principiantes.
Cuidado con el orden del casting.
(double) a / bconvierte primeroaadoubley luego divide (resultado2.5). Pero(double) (a / b)primero hace la división entera5 / 2 = 2y luego convierte el2a2.0: ¡sigue siendo entero! Los paréntesis importan. Lo verás en detalle en la Sección 7 (Conversión de tipos).
Módulo: más útil de lo que parece
El operador % devuelve el resto de la división entera. Parece exótico, pero es imprescindible en muchos patrones:
Pista
% solo funciona bien con enteros positivos. Con negativos, el signo del resultado sigue al dividendo: -7 % 3 es -1 en Java (no 2 como en Python). Si necesitas un módulo siempre positivo, usa Math.floorMod(a, b).
Operadores unarios
Algunos operadores aritméticos actúan sobre un solo operando (unarios):
| Operador | Operación | Ejemplo |
|---|---|---|
+x |
Identidad (no hace nada útil, pero existe) | +5 → 5 |
-x |
Negación aritmética | -x cambia el signo de x |
++x / x++ |
Pre/post incremento (Sección 5.3) | |
--x / x-- |
Pre/post decremento (Sección 5.3) |
5.3 Asignación compuesta e incremento/decremento
Asignación compuesta
La asignación compuesta combina una operación aritmética con la asignación en un solo operador. Es azúcar sintáctico: x += 5 equivale a x = x + 5, pero más corto y ligeramente más seguro (evita ciertos errores de casting implícito).
| Operador | Equivalente a | Ejemplo |
|---|---|---|
+= |
x = x + y |
precio += 10; |
-= |
x = x - y |
saldo -= 50; |
*= |
x = x * y |
precio *= 1.21; (añadir 21% IVA) |
/= |
x = x / y |
nota /= 2; |
%= |
x = x % y |
indice %= 7; (mantener en rango 0-6) |
Pista
La asignación compuesta es muy útil para actualizar contadores, saldos o índices. Es más legible que la forma completa (contador = contador + 1) y menos propensa a errores tipográficos.
Incremento y decremento: ++ y --
Java hereda de C los operadores ++ (suma 1) y -- (resta 1). Tienen dos formas: pre (antes de la variable) y post (después), y la diferencia es sutil pero importante.
| Forma | Nombre | Qué hace | Devuelve |
|---|---|---|---|
++x |
Pre-incremento | Incrementa x en 1 |
El nuevo valor de x |
x++ |
Post-incremento | Incrementa x en 1 |
El valor antes de incrementar |
--x |
Pre-decremento | Decrementa x en 1 |
El nuevo valor de x |
x-- |
Post-decremento | Decrementa x en 1 |
El valor antes de decrementar |
flowchart TD
X1["x = 5"] --> POST["a = x++"]
POST --> P1["1. Se lee el valor de x (5)"]
P1 --> P2["2. Se asigna a a: a = 5"]
P2 --> P3["3. Se incrementa x: x = 6"]
P3 --> P4["Resultado: a=5, x=6"]
X2["x = 5"] --> PRE["b = ++x"]
PRE --> R1["1. Se incrementa x: x = 6"]
R1 --> R2["2. Se lee el valor de x (6)"]
R2 --> R3["3. Se asigna a b: b = 6"]
R3 --> R4["Resultado: b=6, x=6"]
style X1 fill:#e3f2fd,stroke:#1565c0,color:#000
style POST fill:#fff3e0,stroke:#e65100,color:#000
style P1 fill:#fff3e0,stroke:#e65100,color:#000
style P2 fill:#fff3e0,stroke:#e65100,color:#000
style P3 fill:#fff3e0,stroke:#e65100,color:#000
style P4 fill:#ffebee,stroke:#c62828,color:#000
style X2 fill:#e3f2fd,stroke:#1565c0,color:#000
style PRE fill:#e8f5e9,stroke:#2e7d32,color:#000
style R1 fill:#e8f5e9,stroke:#2e7d32,color:#000
style R2 fill:#e8f5e9,stroke:#2e7d32,color:#000
style R3 fill:#e8f5e9,stroke:#2e7d32,color:#000
style R4 fill:#e8f5e9,stroke:#2e7d32,color:#000
Diagrama 5.1 — Diferencia entre x++ (post: asigna y luego incrementa) y ++x (pre: incrementa y luego asigna).
Cuidado
La diferencia entre ++x y x++ solo importa cuando el operador se usa dentro de una expresión más grande. Si va solo en una línea (x++; o ++x;), el efecto es idéntico: ambos incrementan x en 1. La trampa aparece en casos como a = x++ o array[x++] = valor, donde el orden de lectura/escritura cambia el resultado.
La regla mnemotécnica
Regla. La posición del
++te dice cuándo se incrementa respecto a la lectura del valor: -++x(prefijo): primero incrementa, luego usa el nuevo valor. -x++(sufijo): primero usa el valor actual, luego incrementa.
Para evitar bugs, muchos equipos Java modernos recomiendan no usar ++ dentro de expresiones complejas: ponlo siempre en su propia línea. La sentencia i++; sola no tiene ambigüedad.
5.4 Operadores relacionales
Los operadores relacionales comparan dos valores y devuelven siempre un boolean (true o false). Son la base de cualquier if, while o condición.
| Operador | Operación | Ejemplo | Resultado |
|---|---|---|---|
== |
Igualdad | 5 == 5 |
true |
!= |
Desigualdad | 5 != 3 |
true |
< |
Menor que | 3 < 5 |
true |
> |
Mayor que | 3 > 5 |
false |
<= |
Menor o igual que | 5 <= 5 |
true |
>= |
Mayor o igual que | 3 >= 5 |
false |
La trampa == en decimales
Igualar decimales con == es peligroso porque la aritmética de coma flotante no es exacta:
Esto no es un bug de Java, es inherente al estándar IEEE 754 de coma flotante: 0.1 no tiene representación exacta en binario. Para comparar decimales, usa un margen de tolerancia:
Pista
Para dinero y cantidades financieras, nunca uses double ni float: usa BigDecimal (lo verás en UD2). Para notas, medidas físicas y cálculos aproximados, double es suficiente, pero compara siempre con margen.
La trampa == en String (recordatorio)
Ya la veremos en la Sección 8, pero conviene anticiparla aquí porque encaja en este contexto: para comparar String (o cualquier objeto), usa .equals(), no ==. == compara identidad (si son el mismo objeto), .equals() compara contenido. Esto es válido para todos los operadores relacionales de igualdad: con primitivos == funciona; con referencias, casi nunca.
5.5 Operadores lógicos con cortocircuito
Los operadores lógicos combinan valores booleanos. Tienen una característica crucial llamada cortocircuito (short-circuit evaluation) que es una de las optimizaciones más útiles de Java.
Tabla de operadores lógicos
| Operador | Operación | Devuelve true si... |
Cortocircuito |
|---|---|---|---|
&& |
AND (Y lógico) | Ambos operandos son true |
Sí: si el primero es false, no evalúa el segundo |
|| |
OR (O lógico) | Al menos uno es true |
Sí: si el primero es true, no evalúa el segundo |
! |
NOT (Negación) | El operando es false |
(unario, no aplica) |
& |
AND sin cortocircuito | Ambos son true |
No: siempre evalúa ambos |
| |
OR sin cortocircuito | Al menos uno es true |
No: siempre evalúa ambos |
^ |
XOR (O exclusivo) | Exactamente uno es true |
No |
Los operadores &, | y ^ sin cortocircuito son raros en código normal; se usan sobre todo a nivel de bits cuando los operandos son enteros. En lógica booleana, siempre usa && y || con cortocircuito.
Tablas de verdad
Para && (Y lógico):
| a | b | a && b |
|---|---|---|
| true | true | true |
| true | false | false |
| false | true | false |
| false | false | false |
Para || (O lógico):
| a | b | a || b |
|---|---|---|
| true | true | true |
| true | false | true |
| false | true | true |
| false | false | false |
Para ! (negación):
| a | !a |
|---|---|
| true | false |
| false | true |
Qué es el cortocircuito y por qué importa
El cortocircuito significa que && deja de evaluar en cuanto encuentra un false (porque el resultado ya no puede ser true), y || deja de evaluar en cuanto encuentra un true (porque el resultado ya no puede ser false). Esto tiene dos usos prácticos importantísimos:
1. Evitar NullPointerException
flowchart TD
A["a && b"] --> B{"¿a es true?"}
B -->|"No"| C["Devuelve false<br/>SIN evaluar b<br/>(cortocircuito)"]
B -->|"Sí"| D["Evalúa b"]
D --> E{"¿b es true?"}
E -->|"No"| F["Devuelve false"]
E -->|"Sí"| G["Devuelve true"]
H["a || b"] --> I{"¿a es true?"}
I -->|"Sí"| J["Devuelve true<br/>SIN evaluar b<br/>(cortocircuito)"]
I -->|"No"| K["Evalúa b"]
K --> L{"¿b es true?"}
L -->|"Sí"| M["Devuelve true"]
L -->|"No"| N["Devuelve false"]
style A fill:#1565c0,color:#fff,stroke:#0d47a1
style H fill:#2e7d32,color:#fff,stroke:#1b5e20
style C fill:#fff3e0,stroke:#e65100,color:#000
style J fill:#fff3e0,stroke:#e65100,color:#000
Diagrama 5.2 — Cortocircuito en && y ||: si el primer operando ya decide el resultado, no se evalúa el segundo.
2. Evitar cálculos costosos
Si validacionRapida devuelve false, validacionCostosa ni se llama. Esto puede ahorrar muchísimo tiempo.
Leyes de De Morgan
Dos reglas útiles para simplificar condiciones complejas:
!(a && b)es equivalente a!a || !b!(a || b)es equivalente a!a && !b
Pista
Las leyes de De Morgan te permiten reescribir condiciones negativas en forma positiva, que suele ser más legible. edad < 18 se entiende mejor que !(edad >= 18).
5.6 Operadores bit a bit (introducción)
Java hereda de C un conjunto de operadores que actúan a nivel de bits sobre valores enteros (byte, short, int, long, char). En programación de alto nivel rara vez los usarás, pero aparecen en dominios como criptografía, compresión de datos, gráficos de bajo nivel, permisos de archivos y comunicación con hardware. Los verás por encima en esta sección; se profundizan en UD4 cuando tratemos operaciones sobre enteros.
Analogía
Los operadores bit a bit son como un interruptor para cada bombilla de una caseta de feria con 32 bombillas. Cada bit del número enciende (1) o apaga (0) una bombilla. Los operadores bit a bit permiten manipular esos interruptores de golpe: encender todos, apagar algunos, invertir el estado, desplazar los interruptores a la izquierda...
Tabla de operadores bit a bit
| Operador | Operación | Ejemplo | Resultado | Notas |
|---|---|---|---|---|
& |
AND bit a bit | 0b1100 & 0b1010 |
0b1000 (8) |
1 solo si ambos bits son 1 |
\| |
OR bit a bit | 0b1100 \| 0b1010 |
0b1110 (14) |
1 si al menos uno es 1 |
^ |
XOR bit a bit | 0b1100 ^ 0b1010 |
0b0110 (6) |
1 si exactamente uno es 1 |
~ |
NOT bit a bit (unario) | ~0b00001100 |
0b11110011 (-13) |
Invierte todos los bits |
<< |
Desplazamiento izquierda | 0b0001 << 3 |
0b1000 (8) |
Multiplica por 2^n |
>> |
Desplazamiento derecha (con signo) | 0b1000 >> 2 |
0b0010 (2) |
Divide por 2^n, conserva signo |
>>> |
Desplazamiento derecha (sin signo) | 0b1000 >>> 2 |
0b0010 (2) |
Rellena con ceros por la izquierda |
Ejemplos prácticos
Pista
Si no estás trabajando con bits explícitamente, no uses estos operadores. x << 1 para multiplicar por 2 es igual de rápido en Java moderno que x * 2 porque el compilador ya optimiza la multiplicación y el código es menos legible. Úsalos solo cuando manipules bits reales (máscaras, permisos, protocolos).
Asignación compuesta bit a bit
Existen los operadores &=, |=, ^=, <<=, >>=, >>>= equivalentes a x = x op y. Se ven en la tabla de precedencia (Sección 5.8 Precedencia) y funcionan igual que los aritméticos compuestos.
Cuidado
Los operadores bit a bit & y | se parecen a los lógicos && y ||, pero no son lo mismo. & y | siempre evalúan ambos operandos (sin cortocircuito) y operan bit a bit; && y || operan sobre boolean y tienen cortocircuito. Confundirlos es un bug sutil: usa siempre && y || para lógica booleana.
5.7 Otros operadores
Hay otros operadores importantes:
- El operador ternario
?: - El operador
instanceof
Pero los veremos según vayamos avanzando en el curso.
5.8 Precedencia de operadores
La precedencia determina qué operador se evalúa primero cuando hay varios en una expresión. Por ejemplo, 2 + 3 * 4 da 14, no 20, porque * tiene mayor precedencia que + y se evalúa primero.
Tabla de precedencia (de mayor a menor)
| Nivel | Operadores | Asociatividad |
|---|---|---|
| 1 (mayor) | () [] . (acceso a miembro) :: |
Izquierda |
| 2 | ! ++ -- + - (unarios) ~ (cast) |
Derecha |
| 3 | * / % |
Izquierda |
| 4 | + - (binarios) |
Izquierda |
| 5 | << >> >>> (desplazamientos de bits) |
Izquierda |
| 6 | < <= > >= instanceof |
Izquierda |
| 7 | == != |
Izquierda |
| 8 | & (AND bit a bit) |
Izquierda |
| 9 | ^ (XOR bit a bit) |
Izquierda |
| 10 | \| (OR bit a bit) |
Izquierda |
| 11 | && (AND lógico) |
Izquierda |
| 12 | \|\| (OR lógico) |
Izquierda |
| 13 | ?: (ternario) |
Derecha |
| 14 | = += -= *= /= %= &= \|= ^= <<= >>= >>>= |
Derecha |
Algunas reglas prácticas:
*,/,%se evalúan antes que+,-(como en matemáticas).- Los operadores relacionales (
<,>,==, etc.) se evalúan antes que los lógicos (&&,||). - La asignación
=es de las últimas, casi al final. - Los unarios (
!,-,++,--) son de los primeros.
Ejemplos
La regla de oro: usa paréntesis
Aprenderse la tabla de precedencia entera no es práctico y nadie lo hace. La regla profesional es simple:
Regla. Cuando una expresión mezcla más de dos operadores, usa paréntesis para dejar explícito el orden. Los paréntesis no cuestan nada en rendimiento (el compilador los elimina al generar bytecode) y hacen que el código sea legible para cualquier persona, incluyéndote a ti dentro de seis meses.
Pista
IntelliJ puede insertar paréntesis automáticamente cuando seleccionas una expresión y pulsas Alt+Enter → "Surround with parentheses". Úsalo cuando una expresión te parezca ambigua.
5.9 Errores comunes y buenas prácticas
Los ocho errores más frecuentes
| Error | Síntoma | Causa | Solución |
|---|---|---|---|
= en vez de == en un if |
El if siempre se cumple (o no compila) |
Confundir asignación con comparación | Revisa cada = en condiciones; usa == |
| División entera involuntaria | 5 / 2 == 2, no 2.5 |
Ambos operandos son enteros | Convierte uno a double: 5.0 / 2 |
Confundir ++i y i++ |
Resultado inesperado en expresiones | Olvidar cuándo se incrementa | Úsalo solo en su propia línea |
Comparar decimales con == |
0.1 + 0.2 != 0.3 |
Aritmética de coma flotante inexacta | Usa margen de tolerancia (EPSILON) |
Comparar String con == |
Da false aunque el texto sea igual |
Compara identidad, no contenido | Usa .equals() o Objects.equals() |
| Olvidar paréntesis en condiciones | Resultado distinto del esperado | Precedencia no intuitiva | Pon paréntesis explícitos |
NPE en && sin cortocircuito |
NullPointerException inesperado |
Usar & en vez de && |
Usa siempre && para lógica |
Buenas prácticas resumidas
- Para divisiones con decimales, asegúrate de que al menos un operando sea
double:5.0 / 2, no5 / 2. Si solo tienesint, haz casting:(double) a / b(ojo a los paréntesis). - Usa
%para paridad, ciclos y restos:x % 2 == 0para pares,indice % npara ciclos. ++y--en su propia línea salvo en casos muy obvios (forclásico). Evitaa = i++y similares.- Compara decimales con margen:
Math.abs(a - b) < EPSILON. Para dinero, usaBigDecimal. - Para
Stringy objetos, usa.equals()(oObjects.equals()si puede habernull). &&y||con cortocircuito para proteger llamadas que pueden dar NPE:obj != null && obj.metodo().- Paréntesis explícitos cuando una expresión mezcla más de dos operadores. No confíes en la memoria de la tabla de precedencia.
- Revisa tus expresiones con IntelliJ: las inspecciones te avisan de operaciones sospechosas (división entera, comparaciones raras, etc.).
Ejercicios propuestos
Ejercicio 5.1 (= vs ==). ¿Qué hace cada línea? ¿Cuáles compilan? ¿Cuáles son errores lógicos?
Ejercicio 5.2 (división entera). Predice el resultado de cada println sin ejecutarlo y comprueba después:
Ejercicio 5.3 (++i vs i++). Predice los valores finales de i, a, b y c sin ejecutarlo y comprueba después:
Ejercicio 5.4 (cortocircuito). El siguiente código ¿lanza NullPointerException? Explícalo:
Ejercicio 5.5 (De Morgan). Reescribe la siguiente condición sin usar !:
Ejercicio 5.6 (precedencia). Añade paréntesis a la siguiente expresión para que coincida con la evaluación que hace Java por defecto, y predice el resultado:
Ejercicio 5.7 (comparación de decimales). Explica por qué 0.1 + 0.2 == 0.3 da false y escribe una comparación correcta usando EPSILON.
Resumen de la sección 5
Antes de pasar a la siguiente sección, asegúrate de que controlas estos puntos:
- El operador de asignación
=evalúa primero el lado derecho y almacena el resultado en la variable de la izquierda. Es de menor precedencia y asociativo por la derecha. Nunca lo confundas con==(comparación):if (x = 5)asigna, no compara. - Los operadores aritméticos (
+,-,*,/,%) funcionan como en matemáticas, con la trampa de la división entera (5 / 2 == 2). Para decimales, al menos un operando debe serdouble. - La asignación compuesta (
+=,-=,*=,/=,%=) combina operación y asignación. El incremento/decremento++y--tienen forma pre (++x, primero incrementa) y post (x++, primero lee). - Los operadores relacionales (
==,!=,<,>,<=,>=) devuelvenboolean. Cuidado al comparar decimales con==(usa margen) y al compararString(usa.equals()). - Los operadores lógicos
&&y||tienen cortocircuito: dejan de evaluar en cuanto el resultado está decidido. Útil para evitar NPE y cálculos costosos.&,|,^son sin cortocircuito (raros en lógica). - La precedencia determina el orden de evaluación. No te la aprendas: usa paréntesis cuando haya más de dos operadores.
- Los ocho errores típicos:
=en vez de==, división entera,++ivsi++, decimales con==,Stringcon==, falta de paréntesis,&sin cortocircuito, ternarios anidados.