Вы находитесь на странице: 1из 11
Contenido Introducción   1 Los Operadores Aritméticos 2 Los Operadores de Asignación

Contenido

Introducción

 

1

Los

Operadores

Aritméticos

2

Los

Operadores

de Asignación

3

Los

Operadores

Lógicos

3

Los Operadores Relacionales

 

3

Operadores

booleanos

4

 

Negación

Lógica (¬, NOT)

4

Conjunción Lógica ( , AND)

Conjunción Lógica ( , AND)

5

Disyunción Lógica (

Disyunción Lógica ( , OR)

, OR)

5

Disyunción

Lógica

exclusiva (

Disyunción Lógica exclusiva ( , XOR) 5

, XOR)

5

Los Operadores Lógicos de Java

5

¿Qué es eso de la evaluación condicional?

6

La Precedencia de los Operadores

 

8

El Operador Cast

 

9

Introducción

En nuestro camino para obtener todos los elementos necesarios para ser buenos programadores en Java, debemos a estas alturas formalizar el significado y la precedencia de cada uno de los operadores sobre los tipos de dato primitivos que ya conocemos. Una vez hecho esto, estaremos mucho más cerca de nuestra meta, que es la de convertirnos en buenos programadores en Java y de paso, aprobar con altas notas este curso.

Los Operadores Aritméticos

El lenguaje Java soporta varios operadores aritméticos para los números enteros y de punto flotante. Se incluye + (suma), - (resta), * (multiplicación), / (división), y % (módulo, es decir, resto de una división entera). La siguiente tabla muestras estos operadores y su uso:

Operador

Uso

Descripción

 

+ op1 + op2

Suma op1 y op2

 

- op1 - op2

Resta op2 de op1

 

* op1 * op2

Multiplica op1 por op2

 

/ op1 / op2

Divide op1 por op2

 

% op1 % op2

Calcula el resto de dividir op1 entre op2

El tipo de los datos devueltos por una operación aritmética depende del tipo de sus operandos; si se suman dos enteros, se obtiene un entero como tipo devuelto con el valor de la suma de los dos enteros.

Estos operadores se deben utilizar con operandos del mismo tipo, o si no realizar una conversión de tipos de uno de los dos operandos al tipo del otro.

El lenguaje Java sobrecarga la definición del operador + para incluir la concatenación de cadenas. El siguiente ejemplo utiliza + para concatenar la cadena "Contados ", con el valor

de la variable contador y la cadena " caracteres.":

System.out.print("Contados " + contador + " caracteres.");

Esta operación automáticamente convierte el valor de contador a una cadena de caracteres.

Existen dos operadores aritméticos que funcionan como atajo de la combinación de otros: ++ que incrementa su operando en 1, y -- que hace el decremento de su operando en 1.

Ambos operadores (++ y --), tienen una versión prefija, y otra posfija. La correcta utilización de cada versión es crítica en situaciones donde el valor de la sentencia es utilizado en mitad de un cálculo más complejo, por ejemplo para control de flujos.

Las operaciones con ++ y -- son:

Operador

Uso

Descripción

++

op++

Incrementa op en 1; se evalúa al valor anterior al incremento.

++

++op

Incrementa op en 1; se evalúa al valor posterior al incremento.

--

op--

Decremento de op en 1; se evalúa al valor anterior al decremento.

--

--op

Decremento de op en 1; se evalúa al valor posterior al decremento.

Los operadores + y - tienen versiones unarias que realizan las siguientes operaciones:

Operador

Uso

Descripción

+

+op

Convierte op a entero si es un byte, short o char

-

-op

Niega aritméticamente op

Estos operadores difícilmente los usaremos en este curso; pero es conveniente saber que existen en el lenguaje.

Los Operadores de Asignación

El operador de asignación básico es el =, que se utiliza para asignar un valor de una variable a otra, o asignar un literal a una variable. Por ejemplo:

int contador = 0; //Inicia la variable contador con un valor de 0

Java además proporciona varios operadores de asignación que permiten realizar un atajo en la escritura de código. Permiten realizar operaciones aritméticas, lógicas, de bit y de asignación con un único operador.

Supongamos que necesitamos sumar un número a una variable y almacenar el resultado en la misma variable, como a continuación:

i = i + 2;

Se puede abreviar esta sentencia con el operador de atajo +=, de la siguiente manera:

i += 2;

La siguiente tabla muestra los operadores de atajo de asignación y sus equivalentes largos:

Operador

Uso

Equivalente a

+=

op1 += op2

op1 = op1 + op2

-=

op1 -= op2

op1 = op1 - op2

*=

op1 *= op2

op1 = op1 * op2

/=

op1 /= op2

op1 = op1 / op2

%=

op1 %= op2

op1 = op1 % op2

&=

op1 &= op2

op1 = op1 & op2

Los Operadores Lógicos

Los operadores lógicos son fundamentales en la algoritmia programación. Gracias a ellos, podemos controlar el flujo de ejecución de nuestros programas. El saber manejarlos es primordial para escribir algoritmos correctos en cualquier lenguaje de programación.

Los Operadores Relacionales

Un operador relacional compara dos valores y determina la relación existente entre ambos.

Revisando algunas definiciones matemáticas, nos enteramos que los números conforman un conjunto ordenado. Cada uno tiene una posición relativa. Sabemos que el 2 "es menor que" el 4 y que el 6 "es más grande que" el 1. Al comparar dos números, realizamos una función de relación. En Java disponemos de los operadores relacionales para verificar si se cumple una relación. Estas operaciones comparan dos valores numéricos y retornan con un valor booleano.

Los operadores relacionales y su significado se muestran en la tabla presentada a continuación; Ambos operandos son variables de tipo entero o de punto flotante (byte, short, int, long, float o double). :

Operador

Forma de Uso en Java

Expresión

Resultado

Matemática

 

Equivalente

>

A > B

> A > B Verdadero si A es mayor que B.
> A > B Verdadero si A es mayor que B.
> A > B Verdadero si A es mayor que B.

Verdadero si A es mayor que B.

>=

A >= B

>= A >= B Verdadero si A es mayor o igual que B.
>= A >= B Verdadero si A es mayor o igual que B.
>= A >= B Verdadero si A es mayor o igual que B.

Verdadero si A es mayor o igual que B.

<

A < B

< A < B Verdadero si A es menor que B.
< A < B Verdadero si A es menor que B.
< A < B Verdadero si A es menor que B.

Verdadero si A es menor que B.

<=

A <= B

<= A <= B Verdadero si A es menor o igual que B.
<= A <= B Verdadero si A es menor o igual que B.
<= A <= B Verdadero si A es menor o igual que B.

Verdadero si A es menor o igual que B.

==

A == B

== A == B Verdadero si A es igual a B.

Verdadero si A es igual a B.

!=

A != B

!= A != B Verdadero si A es diferente de B.
!= A != B Verdadero si A es diferente de B.
!= A != B Verdadero si A es diferente de B.

Verdadero si A es diferente de B.

Veamos un ejemplo en Java sobre el uso de estos operadores.

public class Relaciones {

public static void main(String args[]){

int

i = -3;

byte

b = 5;

float

f = 1e-10f;

double d = 3.14; boolean b1 = i > i; boolean b2 = i < b; boolean b3 = b <= f; boolean b4 = f >= d; boolean b5 = d != 0; boolean b6 = 1 == f;

System.out.println( i + " > " + i + " = " + b1); System.out.println( i + " < " + b + " = " + b2); System.out.println( b + " <= " + f + " = " + b3); System.out.println( f + " >= " + d + " = " + b4); System.out.println( d + " != " + 0 + " = " + b5); System.out.println( 1 + " == " + f + " = " + b6);

}

}

Operadores booleanos

Cuando necesitamos evaluar la condición de verdad de una o más expresiones lógicas en una sola sentencia, las podemos unir en una sola construcción del lenguaje. Esto lo podemos llamar azúcar sintáctico, ya que no aporta mayor poder al lenguaje, pero sí nos hace la vida más fácil. Antes de ver cuáles son estos operadores hablemos primero de las tablas de verdad lógica para las proposiciones compuestas de negación, conjunción y disyunción.

Negación Lógica (¬, NOT) El operador de negación lógica opera sobre un único valor de verdad (es un operador unario), devolviendo el valor contradictorio de la proposición considerada. El literal de este operador es !. Veamos su tabla de verdad, que es la más simple:

A

¬A

true

false

false

true

Conjunción Lógica (

El operador de conjunción lógica funciona sobre dos operandos de tipo booleano, devolviendo

verdadero si y solo si ambos operandos son verdaderos. Su tabla de verdad es la siguiente:

, AND)son verdaderos. Su tabla de verdad es la siguiente: A B true true true true false

A

B

A B
A B
A B

true

true

true

true

false

false

false

true

false

false

false

false

Disyunción Lógica (

El operador de disyunción lógica funciona sobre dos operandos de tipo booleano, devolviendo

verdadero si alguno de los operandos es verdadero. Su tabla de verdad es la siguiente:

, OR)operandos es verdadero. Su tabla de verdad es la siguiente: A B true true true true

A

B

A B
A B
A B

true

true

true

true

false

true

false

true

true

false

false

false

Disyunción Lógica exclusiva ( , XOR) El operador disyunción lógica exclusiva funciona sobre dos operandos de tipo booleano, devolviendo verdadero si y solo si únicamente uno de los operandos es verdadero. Si ambos operandos son verdaderos o ambos son falsos devolverá falso. Su tabla de verdad es la siguiente:

falsos devolverá falso. Su tabla de verdad es la siguiente: A B true true false true

A

B

A B
A B
A B

true

true

false

true

false

true

false

true

true

false

false

false

Con estas tablas sencillas y fáciles de recordar podemos hablar ahora de nuestros operadores booleanos en Java.

Los Operadores Lógicos de Java La siguiente tabla muestra los literales y el uso de los operadores lógicos de Java:

Nombre

Operador

Utilización

Resultado

AND

&&

A && B

Verdadero cuando A y B son verdaderos. Evaluación condicional.

OR

||

A || B

Verdadero cuando A o B son verdaderos. Evaluación condicional.

NOT

!

!A

Verdadero si A es falso.

AND

&

A & B

Verdadero cuando A y B son verdaderos. Siempre evalúa ambos operandos.

OR

|

A|B

Verdadero cuando A o B son verdaderos. Siempre evalúa ambos operandos

XOR

^

A^B

Verdadero cuando A y B son diferentes.

Además Java soporta un operador ternario, el ?:, que se comporta como una versión reducida de la sentencia if-else:

expresión ? operacion1 : operacion2;

El operador ?: evalúa la expresión y devuelve (ejecuta) operación1 si expresión es cierta, o devuelve operación2 si expresión es falsa.

La expresión anterior es equivalente a:

if (expresión){

operacion1;

else{

operacion2;

}

¿Qué es eso de la evaluación condicional? A pesar de tener dos operadores lógicos para AND y para OR, Seguimos teniendo las mismas tablas de verdad y los resultados que arrojan estas operaciones en Java se rigen por ellas. Sin embargo, el comportamiento de Java es distinto si usamos && en vez de & o si usamos || en vez de |. El resultado de la expresión lógica SIEMPRE será el mismo, pero internamente tienen un comportamiento diferente lo que puede afectar el valor de nuestros operandos si construimos expresiones complicadas que alteran los valores de tales operandos en la expresión.

Cuando estamos en presencia de un operador AND u OR con un solo símbolo, siempre se evalúan ambos operandos. En cambio para el operador con el símbolo repetido, su evaluación cambia según el valor del primer operando.

Por ejemplo, tenemos la siguiente operación:

boolean x = true && false; //evalúa ambos operandos

El resultado es falso, pero la JVM tiene que evaluar el segundo operando para saberlo. En cambio con la siguiente expresión:

boolean x = false && true; //solo evalúa el primer operando

La JVM no se molesta en evaluar el último operando, porque la operación AND es verdadera solamente cuando ambos operandos son verdaderos.

En el caso del operador ||, se evalúa el segundo operando si el primero es falso. Cuando el primero es verdadero, no tiene en cuenta el otro operando: el resultado es verdadero sin importar el valor del segundo operando.

¿Por qué esto es importante? Pensemos en las siguientes expresiones lógicas:

boolean b; int a = 3, x = 8;

A. (++a > (x – a) –1) || (++a != 3);

b =

B. (x < 0) && ((--x – a ) >= 3);

b =

C.

b = (++a

> (x – a) –1) | (++a != 3);

D. b = (x < 0) & ((--x – a ) >= 3);

Para nuestra fortuna en condiciones normales solo nos preguntarán por el valor de b que es un booleano; pero ¿qué tal si alguien en su mente retorcida pregunta por los valores finales de a y de x después de efectuar la operación lógica indicada? Nos enfrentamos entonces a un problema que es sencillo pero sumamente engañoso, y no está de más decir que es una auténtica aberración de la programación. Note que en cada caso usamos operadores ++ y -- prefijos de modo que el valor de b, x y a solo se ve afectado por el uso de AND y OR en sus dos tipos respectivos. Note que a las variables se les hace el incremento o decremento correspondiente y luego se evalúan en la expresión.

El siguiente programa en Java nos calcula el resultado de b y nos indica en cada caso cuál es el valor final de de a y de x:

public class Expresiones{ public static void main (String args[]){ boolean b ; int a = 3, x = 8;

System.out.println ("Para cada expresión a=" + a + " y x="+x);

b =

System.out.println ("\n------------\nPUNTO A\n------------");

System.out.println ("b =

System.out.println ("b=" + b + "\na=" + a + "\nx=" + x);

(++a

> (x - a) -1) || (++a != 3);

(++a

> (x - a) -1) || (++a != 3);");

a=3;

x=8;

b =

System.out.println ("\n------------\nPUNTO B\n------------");

System.out.println ("b =

System.out.println ("b=" + b + "\na=" + a + "\nx=" + x);

(x < 0) && ((--x - a ) >= 3);

(x < 0) && ((--x - a ) >= 3);");

a=3;

x=8;

b = (++a

System.out.println ("\n------------\nPUNTO C\n------------");

System.out.println ("b = (++a

System.out.println ("b=" + b + "\na=" + a + "\nx=" + x);

> (x - a) -1) | (++a != 3);

> (x - a) -1) | (++a != 3)");

a=3;

x=8;

b = (x < 0) & ((--x - a ) >= 3);

System.out.println ("\n------------\nPUNTO D\n------------"); System.out.println ("b = (x < 0) & ((--x - a ) >= 3"); System.out.println ("b=" + b + "\na=" + a + "\nx=" + x);

}

}

La salida de este programa es:

------------ PUNTO A ------------ b = (++a > (x - a) -1) || (++a !=
------------
PUNTO A
------------
b =
(++a
> (x - a) -1) || (++a != 3);
b=true
a=4
x=8
------------
PUNTO B
------------
b =
(x < 0) && ((--x - a ) >= 3);
b=false
a=3
x=8
------------
PUNTO C
------------
b = (++a
> (x - a) -1) | (++a != 3)
b=true
a=5
x=8
------------
PUNTO D
------------
b = (x <
0) & ((--x - a ) >= 3
b=false
a=3
x=7

Note que en los puntos A. y C. el valor de b es true. Y en los puntos B. y D. el valor de b es false. Como ve, el valor de la expresión lógica se mantiene pero los valores finales de a y de x cambian dependiendo de si se usa AND u OR de uno o de dos símbolos.

El anterior ejemplo ilustra lo retorcido que puede llegar a ser un lenguaje de programación si el programador se propone hacer sus programas de esa forma. Como recomendación no use expresiones como estas en sus expresiones lógicas ya que son fuente de errores y confusiones.

Finalmente, si se tienen dudas sobre el orden de evaluación de los operadores y por qué se obtuvieron estos resultados lea detenidamente la siguiente sección sobre la precedencia de operadores, y después revise nuevamente el ejemplo anterior.

La Precedencia de los Operadores

Cuando en una sentencia aparecen varios operadores el compilador deberá de elegir en qué orden aplica los operadores. A esto se le llama precedencia. Los operadores con mayor precedencia son evaluados antes que los operadores con una precedencia relativa menor. Cuando en una sentencia aparecen operadores con la misma precedencia:

Los operadores binarios, (menos los de asignación), son evaluados de izquierda a derecha.

Los operadores de asignación son evaluados de derecha a izquierda.

Se puede indicar explícitamente al compilador de Java cómo se desea que se evalúe la expresión con paréntesis balanceados ( ). Para hacer que el código sea más fácil de leer y mantener, es preferible ser explícito e indicar con paréntesis qué operadores deben ser evaluados primero. Si no se indica explícitamente al compilador el orden en que se quiere que se realicen las operaciones, entonces el compilador decide basándose en la precedencia asignada a los operadores.

La siguiente tabla muestra la precedencia asignada a los operadores de Java. Los operadores de la tabla están listados en orden de precedencia: cuanto más arriba aparezca un operador, mayor es su precedencia. Los operadores en la misma línea tienen la misma precedencia:

Tipo de operadores

 

Operadores de este tipo

 

Operadores posfijos

 

[ ] . (parametros)

expr++

expr--

 

Operadores unarios

 

++expr

--expr

+expr

-expr

~

!

Creación o conversión

 

new (tipo) expr

 

Multiplicación

 

*

/

%

Suma

 

+

-

Desplazamiento

 

<<

>>

>>>

 

Relacionales

 

<

<=

>

>=

instanceof

 

Igualdad

 

==

!=

AND a nivel de bit

 

&

 

OR a nivel de bit

 

^

XOR a nivel de bit

 

|

AND lógico

 

&&

 

OR lógico

 

||

Condicional

 

? :

 

Asignación

=

+=

-=

*=

/=

%=

&=

^=

|=

>>= >>>==

Existe una palabra clave llamada instanceof que puede ser interpretada como un operador encargado de comprobar si un objeto es una instancia de una determinada clase, por ejemplo:

String cad = "unTexto"; Bolean resultado = cad instanceof String;

El Operador Cast

Cada vez que realizamos una operación obtenemos un resultado. Este resultado podrá tener un tipo de dato diferente de los operandos. Veamos el siguiente ejemplo:

public class CambioTipo { public static void main(String args[]){ byte unByte = 2; byte otroByte = 3; byte result = unByte + otroByte;

}

}

Al compilarlo, Java nos dice lo siguiente:

----jGRASP exec: javac -g /home/cmartinez/CambioTipo.java CambioTipo.java:5: possible loss of precision

found

required: byte byte result = unByte + otroByte;

: int

^

1 error

----jGRASP wedge: exit code for process is 1.

El error en la compilación se debe a que se produjo un cambio de tipo en el resultado: en vez de obtener un byte se obtuvo un int. Este es un cambio de tipo implícito.

Si no queremos que quede así, podemos forzar al compilador que nos entregue un byte. Lo haremos de la siguiente forma:

byte result = (byte)(unByte + otroByte);

Aquí estamos realizando un cambio explícito de tipo con un operador cast. Este operador aparece como el nombre del tipo a obtener entre paréntesis siempre antepuesto al resultado que se desea modificar.

Veamos la siguiente definición que es un error común de programación:

float f = 3.14;

Sabemos ya que nos dará un error debido a que es un literal double que trata de disfrazarse de float. Si usamos cast lo transformamos en float:

float f = (float)3.14;

Con esta nueva sentencia el compilador no tendrá ningún problema. El operador cast se ocupó de convertir un double en un float.

Existe un cierto peligro en la utilización indiscriminada de este operador. Observemos el siguiente programa:

public class Int2Byte {

public static void main(String args[]){

}

}

int

byte unByte = (byte)unInt; System.out.println("El resultado es: " + unByte);

unInt = 5000;

Aquí intentamos meter a forzadamente un valor int cuyo valor es más grande de lo soportado por un byte. Java ignora este tipo de error y continúa como si no hubiese ocurrido nada extraño. Si ejecutamos el programa la salida será la siguiente:

El resultado es: -120

El resultado dista mucho del valor original. El operador cast se comportó como una picadora de bits. Si miramos con lupa ambos valores, nos damos cuenta que ocurrió:

Página

10

00000000000000000001001110001000 : un int de 32bits cuyo valor es 5000

10001000 : un byte de 8bits de valor -120, complemento a 2

Resulta que al aplicar el cast "cortamos" la variable int en los primeros 8 bits que corresponden al tamaño de una variable tipo byte.

Página

11