CSE 102
PRINCIPLES OF PROGRAMMING
Lecture 3 - Operators
Department of Computer Science,
FUD - 2024
Operators
Java provides a rich operator environment.
An operator is a symbol that tells the
compiler to perform a specific mathematical
or logical manipulation.
Java has four general classes of operators:
arithmetic, bitwise, relational, and logical.
Java also defines some additional operators
that handle certain special situations.
Arithmetic Operators
Java defines the following arithmetic
operators:
Operator Meaning
+ Addition
- Subtraction
* Multiplication
/ Division
% Modulus
Table 3.1: Java’s arithmetic operators
The operators +, –, *, and / all work the same
way in Java as they do in any other
programming languages (or algebra, for that
matter).
These can be applied to any built-in numeric
data type. They can also be used on objects
of type char.
Although the actions of arithmetic operators
are well known to all readers, a few special
situations warrant some explanation.
First, remember that when / is applied to an
integer, any remainder will be truncated; for
example, 10/3 will equal 3 in integer division.
You can obtain the remainder of this division
by using the modulus operator, %.
It works in Java the way it does in other
languages: it yields the remainder of an
integer division. For example, 10 % 3 is 1.
In Java, the % can be applied to both integer
and floating-point types. Thus, 10.0 % 3.0 is
also 1.
The following program demonstrates the modulus operator.
// Demonstrate the % operator.
class ModDemo {
public static void main(String args[]){
int iresult, irem;
double dresult, drem;
iresult = 10 / 3;
irem = 10 % 3;
dresult = 10.0 / 3.0;
drem = 10.0 % 3.0;
System.out.println("Result and remainder of 10 /
3: " + iresult + " " + irem);
System.out.println("Result and remainder of 10.0
/ 3.0: " + dresult + " " + drem);
}
}
Increment and Decrement
The ++ and the –– are Java’s increment and
decrement operators.
As you will see, they have some special
properties that make them quite interesting.
Let’s begin by reviewing precisely what the
increment and decrement operators do.
The increment operator adds 1 to its operand,
and the decrement operator subtracts 1.
Therefore,
x = x + 1;
is the same as
x++;
And
x = x - 1;
is the same as
--x;
Both the increment and decrement
operators can either precede (prefix) or
follow (postfix) the operand.
For example,
x = x + 1;
can be written as
++x; // prefix form
or as
x++; // postfix form
In the foregoing example, there is no
difference whether the increment is applied
as a prefix or a postfix.
However, when an increment or decrement is
used as part of a larger expression, there is
an important difference.
When an increment or decrement operator
precedes its operand, Java will perform the
corresponding operation prior to obtaining
the operand’s value for use by the rest of the
expression.
If the operator follows its operand, Java will
obtain the operand’s value before
incrementing or decrementing it.
Consider the following:
x = 10;
y = ++x;
In this case, y will be set to 11. However, if
the code is written as
x = 10;
y = x++;
Then y will be set to 10. In both
cases, x is still set to 11; the
difference is when it happens.
Relational and Logical Operators
In the terms relational operator and logical
operator, relational refers to the
relationships that values can have with one
another, and logical refers to the ways in
which true and false values can be
connected together.
Since the relational operators produce true
or false results, they often work with the
logical operators.
For this reason they will be discussed
together here.
Operato Meaning
r
== Equal to
=! Not equal to
> Greater
< Less then
>= Greater then or equal to
<= Less than or equal to
Table 3.2: Relational operators in Java
Operator Meaning
& AND
| OR
XOR Exclusive OR
|| Short-circuit OR
&& Short-circuit AND
! NOT
Table 3.3: Logical operators in Java
The outcome of the relational and logical
operators is a boolean value.
In Java, all objects can be compared for
equality or inequality using = = and !=.
However, the comparison operators, <, >,
<=, or >=, can be applied only to those
types that support an ordering relationship.
Therefore, all of the relational operators can
be applied to all numeric types and to type
char.
However, values of type boolean can only be
compared for equality or inequality, since the
true and false values are not ordered.
For example, true > false has no meaning
in Java.
For the logical operators, the operands must
be of type boolean, and the result of a
logical operation is of type boolean.
The logical operators, &, |, ^, and !, support
the basic logical operations AND, OR, XOR,
and NOT, according to the following truth
table.
P q P&q P|q P^q !p
False False False False False True
True False False True True False
False True False True true True
True true True True false false
Table 3.4: Logical operations
Here is a program that demonstrates several of the relational and logical operators:
// Demonstrate the relational and logical operators.
class RelLogOps {
public static void main(String args[]) {
int i, j;
boolean b1, b2;
i = 10;
j = 11;
if(i < j) System.out.println("i < j");
if(i <= j) System.out.println("i <= j");
if(i != j) System.out.println("i != j");
if(i == j) System.out.println("this won't execute");
if(i >= j) System.out.println("this won't execute");
if(i > j) System.out.println("this won't execute");
b1 = true;
b2 = false;
if(b1 & b2) System.out.println("this won't execute");
if(!(b1 & b2)) System.out.println("!(b1 & b2) is true");
if(b1 | b2) System.out.println("b1 | b2 is true");
if(b1 ^ b2) System.out.println("b1 ^ b2 is true");
}
}
Short-Circuit Logical Operators
Java supplies special short-circuit versions of
its AND and OR logical operators that can be
used to produce more efficient code.
To understand why, consider the following. In
an AND operation, if the first operand is
false, the outcome is false no matter what
value the second operand has.
In an OR operation, if the first operand is
true, the outcome of the operation is true no
matter what the value of the second
operand.
Thus, in these two cases there is no need to
evaluate the second operand.
By not evaluating the second operand, time is
saved and more efficient code is produced.
The short-circuit AND operator is &&, and the
short-circuit OR operator is ||.
Their normal counterparts are & and |. The
only difference between the normal and short-
circuit versions is that the normal operands
will always evaluate each operand, but short-
circuit versions will evaluate the second
operand only when necessary.
// Demonstrate the short-circuit operators.
class SCops {
public static void main(String args[]) {
int n, d, q;
n = 10;
d = 2;
if(d != 0 && (n % d) == 0) System.out.println(d + " is a factor of " +
n);
d = 0; // now, set d to zero
// Since d is zero, the second operand is not evaluated.
if(d != 0 && (n % d) == 0) System.out.println(d + " is a factor of " +
n);
/* Now, try same thing without short-circuit operator.
This will cause a divide-by-zero error.
*/
if(d != 0 & (n % d) == 0) System.out.println(d + " is a factor of " +
n);
}
}
The Assignment Operator
You have been using the assignment operator
since the beginning of this course.
Now it is time to take a formal look at it. The
assignment operator is the single equal sign,
=.
This operator works in Java much as it does in
any other programming languages. It has this
general form:
var = expression;
Here, the type of var must be compatible with
the type of expression.
The assignment operator does have one
interesting attribute that you may not be
familiar with:
It allows you to create a chain of assignments.
For example, consider this fragment:
int x, y, z;
x = y = z = 100; // set x, y, and z to 100
This fragment sets the variables x, y, and z to
100 using a single statement.
This works because the = is an operator that
yields the value of the right-hand expression.
Shorthand Assignments
Java provides special shorthand assignment
operators that simplify the coding of certain
assignment statements.
Let’s begin with an example. The assignment
statement shown here
x = x + 10;
can be written, using Java shorthand, as
x += 10;
The operator pair += tells the compiler to
assign to x the value of x plus 10.
Here is another example. The statement
x = x - 100;
is the same as
x -= 100;
Both statements assign to x the value of x
minus 100.
This shorthand will work for all the binary
operators in Java (that is, those that require
two operands).
The general form of the shorthand is
var op = expression;
+= -= *= /=
%= &= |= ^=
Table 3.5: Arithmetic and Logical assignment operators
Because these operators combine an operation
with an assignment, they are formally referred to
as compound assignment operators.
The compound assignment operators provide
two benefits.
First, they are more compact than their
“longhand” equivalents.
Second, they are implemented more efficiently
by the Java run-time system.
For these reasons, you will often see the
compound assignment operators used in
professionally written Java programs.
Type Conversion in Assignments
In programming, it is common to assign one
type of variable to another.
For example, you might want to assign an
int value to a float variable, as shown here:
int i;
float f;
i = 10;
f = i; // assign an int to a float
When compatible types are mixed in an
assignment, the value of the right side is
automatically converted to the type of the left
side.
Thus, in the preceding fragment, the value in i
is converted into a float and then assigned to
f.
However, because of Java’s strict type
checking, not all types are compatible, and
thus, not all type conversions are implicitly
allowed.
For example, boolean and int are not
compatible.
When one type of data is assigned to another
type of variable, an automatic type
conversion will take place if the two types are
compatible.
The destination type is larger than the source
type.
When these two conditions are met, a
widening conversion takes place.
For example, the int type is always large
enough to hold all valid byte values, and
both int and byte are integer types, so an
automatic conversion from byte to int can
be applied.
For widening conversions, the numeric
types, including integer and floating-point
types, are compatible with each other.
For example, the following program is
perfectly valid since long to double is a
widening conversion that is automatically
performed.
// Demonstrate automatic conversion from long to double.
class LtoD {
public static void main(String args[]) {
long L;
double D;
L = 100123285L;
D = L;
System.out.println("L and D: " + L + " " + D);
}
}
Although there is an automatic conversion
from long to double, there is no automatic
conversion from double to long since this
is not a widening conversion.
Thus, the following version of the preceding
program is invalid.
// *** This program will not compile. ***
class LtoD {
public static void main(String args[]) {
long L;
double D;
D = 100123285.0;
L = D; // Illegal!!!
System.out.println("L and D: " + L + " " + D);
}
}
There are no automatic conversions from the
numeric types to char or boolean. Also, char
and boolean are not compatible with each
other. However, an integer literal can be
assigned to char.
Casting Incompatible Types
Although the automatic type conversions are
helpful, they will not fulfill all programming
needs because they apply only to widening
conversions between compatible types.
For all other cases you must employ a cast.
A cast is an instruction to the compiler to
convert one type into another.
Thus, it requests an explicit type conversion.
A cast has this general form:
(target-type) expression
Here, target-type specifies the desired type to
convert the specified expression to.
For example, if you want to convert the type of
the expression x/y to int, you can write
double x, y;
// ...
(int) (x / y)
Here, even though x and y are of type
double, the cast converts the outcome of the
expression to int.
The parentheses surrounding x/y are
necessary. Otherwise, the cast to int would
apply only to the x and not to the outcome of
the division.
The cast is necessary here because there is no
automatic conversion from double to int.
When a cast involves a narrowing conversion,
information might be lost.
For example, when casting a long into a
short, information will be lost if the long’s
value is greater than the range of a short
because its high-order bits are removed.
When a floating-point value is cast to an
integer type, the fractional component will
also be lost due to truncation.
For example, if the value 1.23 is assigned to
an integer, the resulting value will simply
be 1.
The 0.23 is lost.
The following program demonstrates some
type conversions that require casts:
// Demonstrate casting.
class CastDemo {
public static void main(String args[]) {
double x, y;
byte b;
int i;
char ch;
x = 10.0;
y = 3.0;
i = (int) (x / y); // cast double to int
System.out.println("Integer outcome of x / y: " + i);
i = 100;
b = (byte) i;
System.out.println("Value of b: " + b);
i = 257;
b = (byte) i;
System.out.println("Value of b: " + b);
b = 88; // ASCII code for X
ch = (char) b;
System.out.println("ch: " + ch);
}
}