Vous êtes sur la page 1sur 8

Operadores

Los operadores de Java son muy parecidos en estilo y funcionamiento a los de C.


Tanto C, como C++, como Java, proporcionan un conjunto de operadores para
poder realizar acciones sobre uno o dos operandos. Un operador que actúa sobre
un solo operando es un operador unario, y un operador que actúa sobre dos
operandos es un operador binario.

Algunos operadores pueden funcionar como unarios y como binarios, el ejemplo


más claro es el operador ­ (signo menos). Como operador binario, el signo menos
hace que el operando de la derecha sea sustraido al operando de la izquierda; como
operador unario hace que el signo algebraico del operando que se encuentre a su
derecha sea cambiado.

En la siguiente tabla aparecen los operadores que se utilizan en Java, por orden de
precedencia:

. [] ()
++ --
! ~ instanceof
* / %
+ -
<< >> >>>
< > <= >= == !=
& ^ |
&& ||
? :
= op= (*= /= %= += -= etc.) ,

Los operadores numéricos se comportan como esperamos:

int + int = int

Los operadores relacionales devuelven un valor booleano.

Para las cadenas, se pueden utilizar los operadores relacionales para comparaciones
además de + y +=para la concatenación:

String nombre = "nombre" + "Apellido";

El operador = siempre hace copias de objetos, marcando los antiguos para


borrarlos, y ya se encargará el garbage collector de devolver al sistema la memoria
ocupada por el objeto eliminado.

Java, a diferencia de C++, no soporta la sobrecarga de operadores. Esto significa


que no es posible redefinir el entorno en el que actúa un operador con respecto a
los objetos de un nuevo tipo que el programador haya definido como propios.

Un caso interesante, que se sale de la afirmación anterior, es el


operador + (signo más), que se puede utilizar para realizar una suma aritmética o
para concatenar cadenas (¡Java lo sobrecarga internamente!). Cuando el
signo más se utiliza en esta última forma, el operando de la derecha se convierte
automáticamente en una cadena de caracteres antes de ser concatenada con el
operando que se encuentra a la izquierda del operador +. Esto asume que el
compilador sabe que el operando de la derecha es capaz de soportar la conversión.
Y ese conocimiento lo tiene porque comprueba todos los tipos primitivos y muchos
de los tipos internos que se utilizan. Obviamente, el compilador no sabe
absolutamente nada de los tipos que haya definido el programador.

A continuación se detallan algunos de los operadores que admite Java y que se


suelen agrupar en

operadores aritméticos, relacionales y condicionales, operadores lógicos y que


actúan sobre bits y, finalmente, operadores de asignación.

Operadores Aritméticos
Java soporta varios operadores aritméticos que actúan sobre números enteros y
números en coma flotante. Los operadores binarios soportados por Java son:

+ suma los operandos


­ resta el operando de la derecha al de la izquierda
* multiplica los operandos
/ divide el operando de la izquierda entre el de la derecha
% resto de la división del operando izquierdo entre el derecho

Como se ha indicado anteriormente, el operador más (+), se puede utilizar para


concatenar cadenas, como se observa en el ejemplo siguiente:

"miVariable tiene el valor " + miVariable + " en este programa"

Esta operación hace que se tome la representación como cadena del valor
de miVariable para su uso exclusivo en la expresión. De ninguna forma se altera el
valor que contiene la variable.

En C++ no se soporta la concatenación de cadenas con el operador más (+); hay


que utilizar la función strcat() para poder concatenar dos cadenas y el uso de esta
función puede resultar peligroso porque no hay protección contra el traspaso de los
límites del array que se utiliza como destino de la cadena concatenada.

El operador módulo (%), que devuelve el resto de una división, a diferencia de C++,
en Java funciona con tipos en coma flotante además de con tipos enteros. Cuando
se ejecuta el programa que se muestra en el ejemplo java401.java.

La salida que se obtiene por pantalla tras la ejecución del ejemplo es la que se
reproduce a continuación:

%java java401
x mod 10 = 3
y mod 10 = 3.299999999999997
Los operadores unarios que soporta Java son

+ indica un valor positivo


­ negativo, o cambia el signo algebraico
++ suma 1 al operando, como prefijo o sufijo
­­ resta 1 al operando, como prefijo o sufijo

En los operadores de incremento (++) y decremento (­­), en la versión prefijo, el


operando aparece a la derecha del operador, ++x; mientras que en la versión sufijo,
el operando aparece a la izquierda del operador, x++. La diferencia entre estas
versiones es el momento en el tiempo en que se realiza la operación representada
por el operador si éste y su operando aparecen en una expresión larga. Con la
versión prefijo, la variable se incrementa (o decrementa) antes de que sea utilizada
para evaluar la expresión en que se encuentre, mientras que en la versión sufijo, se
utiliza la variable para realizar la evaluación de la expresión y luego se incrementa
(o decrementa) en una unidad su para realizar la evaluación de la expresión y luego
se incrementa (o decrementa) en una unidad su valor.

Operadores Relacionales y Condicionales


Aunque Java y C++ soportan los mismos operadores relacionales, devuelven
valores diferentes. Los operadores relacionales en Java devuelven un tipo
booleano, true o false; mientras que en C++ devuelven un valor entero, en donde
se puede considerar al valor cero como false y a un valor no-cero como true.

> el operando izquierdo es mayor que el derecho


>= el operando izquierdo es mayor o igual que el derecho
< el operando izquierdo es menor que el derecho
<= el operando izquierdo es menor o igual que el derecho
== el operando izquierdo es igual que el derecho
!= el operando izquierdo es distinto del derecho

Los operadores relacionales combinados con los operadores condicionales (o lógicos


en C++), se utilizan para obtener expresiones más complejas. Los operadores
condicionales que soporta Java son:

&& expresiones izquierda y derecha son true


|| o la expresión izquierda o al expresión de la derecha son true
! la expresión de la derecha es false

Los programadores C++ se encontrarán con que Java restringe el uso de estos
operadores, porque en C++ la representación de true y false es muy diferente a
Java. En Java, los operandos de estos operadores deben ser tipos booleanos, o
expresiones que devuelvan un tipo booleano, mientras que en C++ puede ser
cualquier tipo entero o expresión que devuelva un tipo entero, sin restricciones.

Una característica importante del funcionamiento de los operadores && y ||, tanto
en Java como en C++ (y que es pasado a veces por alto, incluso por
programadores experimentados) es que las expresiones se evalúan de izquierda a
derecha y que la evaluación de la expresión finaliza tan pronto como se pueda
determinar el valor de la expresión. Por ejemplo, en la expresión siguiente:
( a < b ) || ( c < d )

si la variable a es menor que la variable b, no hay necesidad de evaluar el operando


izquierdo del operador || para determinar el valor de la expresión entera. En casos
de complicadas, complejas y largas expresiones, el orden en que se realizan estas
comprobaciones puede ser fundamental, y cualquier error en la colocación de los
operandos puede dar al traste con la evaluación que se desea realizar y, estos
errores son harto difíciles de detectar, ya que se debe estudiar concienzudamente el
resultado de las expresiones en tiempo de ejecución para poder detectar el
problema.

Operadores a Nivel de Bits


Java y C, C++ comparten un conjunto de operadores que realizan operaciones
sobre un solo bit cada vez. Java también soporta el operador >>>, que no existe en
C o C++ y, además, el entorno en el que se realizan algunas de las operaciones no
siempre es el mismo en Java que en los otros lenguajes.

Los operadores de bits que soporta Java son los que aparecen en la siguiente
tablita:

Operador Uso Operación


Desplaza bits del operando hacia la derecha las posiciones
>> Operando >> Despl
indicadas (con signo)
Desplaza bits del operando hacia la izquierda las posiciones
<< Operando << Despl
indicadas
Desplaza bits del operando hacia la derecha las posiciones
>>> Operando >>> Despl
indicadas (sin signo)

& Operando & Operando Realiza una operación AND lógiga entre los dos operandos

| Operando | Operando Realiza una operación OR lógica entre los dos operandos


Realiza una operación lógica OR Exclusiva entre los dos
^ Operando ^ Operando
operandos

~ ~Operando Complementario del operando (unario)

En Java, el operador de desplazamiento hacia la derecha sin signo, rellena los bits
que pueden quedar vacíos con ceros. Los bits que son desplazados fuera del
entorno se pierden.

En el desplazamiento a la izquierda, hay que ser precavidos cuando se trata de


desplazar enteros positivos pequeños, porque el desplazamiento a la izquierda tiene
el efecto de multiplicar por 2 para cada posición de bit que se desplace; y esto es
peligroso porque si se desplaza un bit 1 a la posición más alta, el bit 31 o el 63, el
valor se convertirá en negativo.

Operadores de Asignación
El operador = es un operador binario de asignación de valores. El valor almacenado
en la memoria y representado por el operando situado a la derecha del operador es
copiado en la memoria indicada por el operando de la izquierda. Al contrario que en
C++, el operador de asignación (ni ningún otro) no se puede sobrecargar en Java.

Java soporta toda la panoplia de operadores de asignación que se componen con


otros operadores para realizar la operación que indique ese operador y luego
asignar el valor obtenido al operando situado a la izquierda del operador de
asignación. De este modo se pueden realizar dos operaciones con un solo operador.

+= -= *= /= %= &= |= ^= <<=
>>= >>>=

Por ejemplo, las dos sentencias que siguen realizan la misma función:

x += y;
x = x + y;

Y las otras comprobaciones siguen el mismo patrón. C++ no soporta el


operador >>>= porque tampoco soporta el operador a nivel de bits de
desplazamiento sin signo (>>>).

Operadores Ternario if-then-else


Java, lo mismo que C y C++, soporta este operador ternario. No obstante, la
construcción utilizada por este operador es lago confusa, aunque se puede llegar a
entender perfectamente cuando uno lee en el pensamiento lo que está escrito en el
código. La forma general del operador es:

expresion ? sentencia1 : sentencia2

en donde expresion puede ser cualquier expresión de la que se obtenga como


resultado un valor booleano, porque en Java todas las expresiones condicionales se
evalúan a booleano; y si es trueentonces se ejecuta la sentencia1 y en caso
contrario se ejecuta la sentencia2. La limitación que impone el operador es
que sentencia1 y sentencia2 deben devolver el mismo tipo, y éste no puede ser
void.

Puede resultar útil para evaluar algún valor que seleccione una expresión a utilizar,
como en la siguiente sentencia:

cociente = denominador == 0 ? 0 : numerador / denominador

Cuando Java evalúa la asignación, primero mira la expresión que está a la izquierda
del interrogante. Sidenominador es cero, entonces evalúa la expresión que está
entre el interrogante y los dos puntos, y se utiliza como valor de la expresión
completa. Si denominador no es cero, entonces evalúa la expresión que está
después de los dos puntos y se utiliza el resultado como valor de la expresión
completa, que se asigna a la variable que está a la izquierda del operador de
asignación, cociente.

En el ejemplo java402.java se utiliza este operador para comprobar que el


denominador no es cero antes de evaluar la expresión que divide por él,
devolviendo un cero en caso contrario. Hay dos expresiones, una que tiene un
denominados cero y otra que no.

class java402 {
public static void main( String args[] ) {
int a = 28;
int b = 4;
int c = 45;
in t d = 0;

// Utilizamos el operador ternario para asignar valores a


// las dos variables e y f, que son resultado de la
// evaluación realizada por el operador
int e = (b == 0) ? 0 : (a / b) ;
int f = (d == 0) ? 0 : (c / d);
// int f = c / d;

System.out.println( "a = " + a );


System.out.println( "b = " + b );
System.out.println( "c = " + c );
System.out.println( "d = " + d );
System.out.println();
System.out.println( "a / b = " + e );
System.out.println( "c / d = " + f );
}
}

El programa se ejecuta sin errores, y la salida que genera por pantalla es la que se
reproduce:

%java java402
a = 28
b=4
c = 45
d=0

a/b=7
c/d=0

Si ahora cambiamos la línea que asigna un valor a la variable f, y quitamos este


operador, dejándola como:

int f = c / d;

se producirá una excepción en tiempo de ejecución de división por cero,


deteniéndose la ejecución del programa en esa línea.

%java java402
java.lang.ArithmeticException: / by zero at java402.main(java402.java:40)

Errores comunes en el uso de Operadores


Uno de los errores más comunes que se cometen cuando se utilizan operadores es
el uso incorrecto, o no uso, de los paréntesis cuando la expresión que se va a
evaluar es compleja. Y esto sigue siendo cierto en Java.

Cuando se programa en C/C++, el error más común es el siguiente:

while( x = y ) {
// . . .
}
EL programador intenta realmente hacer una equivalencia (==) en vez de una
asignación. En C/C++ el resultado de esta asignación siempre será true si y no es
cero, y lo más seguro es que esto se convierta en un bucle infinito. En Java, el
resultado de esta expresión no es un booleano, y el compilador espera un booleano,
que no puede conseguir a partir de un entero, así que aparecerá un error en tiempo
de compilación que evitará que el programa se caiga al ejecutarlo. Es decir, este
error tan común, para que se dé en Java tienen que ser x e y booleanos, lo cual no
es lo más usual.

Otro error muy difícil de detectar en C++ es cuando se utiliza el operador


unario & cuando la lógica requiere un operador &&; o utilizar el operador unario |,
en lugar del operador ||. Este es otro problema difícil de detectar porque el
resultado es casi siempre el mismo, aunque sólo por accidente. En Java, no ocurre
esto y se puede utilizar perfectamente el operador unario & como sinónimo del
operador &&, o el operador | como sinónimo de ||; pero si se hace así, la
evaluación de la expresión no concluirá hasta que todos los operandos hayan sido
evaluados, perdiendo de esta forma las posibles ventajas que podría reportar la
evaluación de izquierda a derecha.

Moldeo(casting) de Operadores
Es lo que se conoce como casting, refiriéndose a "colocar un molde". Java
automáticamente cambia el tipo de un dato a otro cuando es pertinente. Por
ejemplo, si se asigna un valor entero a una variable declarada como flotante, el
compilador convierte automáticamente el int a float. El casting, o moldeo,
permite hacer esto explícitamente, o forzarlo cuando normalmente no se haría.

Para realizar un moldeo, se coloca el tipo de dato que se desea (incluyendo todos
los modificadores) dentro de paréntesis a la izquierda del valor. Por ejemplo:

void moldeos() {
int i = 100;
long l = (long)i;
l ong l 2 = ( l ong )200 ;
}

Como se puede ver, es posible realizar el moldeo de un valor numérico del mismo
modo que el de una variable. No obstante, en el ejemplo el moldeo es superfluo
porque el compilador ya promociona los enteros a flotantes cuando es necesario
automáticamente, sin necesidad de que se le indique. Aunque hay otras ocasiones
en que es imprescindible colocar el moldeo para que el código compile.

En C/C++ el moldeo puede causar auténticos quebraderos de cabeza. En Java, el


moldeo es seguro, con la excepción de cuando se realiza una conversión estrecha,
es decir, cuando se quiere pasar de un dato que contiene mucha información a otro
que no puede contener tanta, en donde se corre el riesgo de perder información.
Aquí es donde el compilador fuerza a que se coloque un moldeo expreso, indicando
al programador que "esto puede ser algo peligroso, así que si quieres que lo haga,
dímelo expresamente". Cuando se trata de una conversión ancha, no es necesario
el moldeo explícito, ya que el nuevo tipo podrá contener más información que la
que contiene el tipo original, no ocasionándose ninguna pérdida de información, así
que el compilador puede realizar el moldeo explícitamente, sin la intervención del
programador para confirmar la acción.
Java permite el moldeo de cualquier tipo primitivo en otro tipo primitivo, excepto en
el caso de los booleanos, en que no se permite moldeo alguno. Tampoco se permite
el moldeo de clases. Para convertir una clase en otra hay que utilizar métodos
específicos. La clase String es un caso especial que se verá más adelante.

Vous aimerez peut-être aussi