Operators and Assignments

 In this section you should be able to:

  1. Determine the result of applying any operator (including assignment operators and instanceof) to operands of any type class scope or accessibility or any combination of these.

 

  1. Determine the result of applying the Boolean equals (Object) method to objects of any combination of the classes java.lang.String, java.lang.Boolean, java.lang.Object.

 

  1. In an expression involving the operators &, |, &&, || and variables of known values state which operands are evaluated and the value of the expression.

 

  1. Determine the effect upon objects and primitive values of passing variables into methods and performing assignments or other modifying operations in that method.

 

Operators and Assignments

Category

Operators

Description

Unary

++    --    +    -    !    ~    ( )

++ --

+ -

~

!

( )

Increment/decrement operators

Unary plus/minus (pos/neg)

Bitwise inversion

Boolean complement

Cast

Arithmetic

*    /    %

*

/

%

Multiply

Division

Modulo operator

+    -

+

-

Plus

Minus

Shift

<<    >>    >>>

<< 

>> 

>>> 

Signed left shift

Signed right shift

Unsigned right shift operator (also known - zero fill right shift)

Comparison

<    <=    >    >=    instanceof

< 

<=

> 

>=

instanceof

Less than

Less than or equal to

More than

More than or equal to

Tests the class of an object at runtime

==    !=

==

!=

Equal to

Not equal to

Bitwise

&    ^    |

&

^

|

AND

XOR

OR

Short-circuit

&&    ||

&&

||

AND

OR

Used only for Boolean types and can be used to test the 2nd only if the first doesn’t equate

i.e.

false && true = false: if one operand is false the result is false without regard to the other operand. Similarly

true && false = true: if one operand is true the result is true without regard to the other operand

Conditional

?:

?:

Also known as ternary operator, works like an if/else statement

 

A = X ? B : C

 

If X = true

            A = B

Else

            A = C

Assignment

=    “op=”

=

op=

Equals

Op represents operator, i.e.

+=, *=

e.g.

x = x+ 2;

could be written

x+=2;

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Conversion rules in Assignments

In the description below, I have given basic rules for assignment when source and destination are of different types.

1.      If source and destination are of the same type, assignment happens without any issues.

2.      If source is of a smaller size than destination but source and destination are of compatible types, then no casting is required. Implicit widening takes place in this case. An example is assigning an int to a long.

3.      If source and destination are of compatible types but source is of larger size than destination, explicit casting is required. In this case if no casting is provided then the program does not compile.

 

 

Remember these rules when using data types with the various operators.  There will be questions which may try to catch you out. The following example seems to go against rule 1 even though the rule is correct, and it gets me every time:

Q:        Will the following code compile?

1.              byte b = 2;

2.              byte b1 = 3;

3.              b = b * b1;

A.     Yes

B.     No

 

A:        B. No

 

Although the source and destination are the same, the two operands, which are originally bytes, get converted by the operator into ints before the multiplication. The result of the multiplication is an int, which cannot be assigned to byte b. See the screen shot below showing the code in use in a class called test:

To get the code to perform how I want I need to change it to something like the following:

1.  byte b = 2;

2.  byte b1 = 3;

3.  b = (byte)(b * b1);

Otherwise I would need to introduce another variable of the int type to hold the result.

1.  byte b = 2;

2.  byte b1 = 3;

3.  int i = b * b1;

 

 

Floating point numbers

Decimal numbers (for example 1.3) are of the type double by default. To make them of type float they must be followed by F or f (example 1.3F or 1.3f).

 

The equality operator

The equality operator (==) when applied to objects, returns true if the two objects have the same reference value, otherwise false.  The example below illustrates this:

            String str1 = “first string”;

     String str2 = new String(“first string”);

     String str3 = “first string”;

     boolean test1 = (str1==str2);

     boolean test2 = (str1==str3);

 

In the example above test1 is set to false because str1 and str2 point to different references. As str1 and str3 point to the same reference, test2 gets set to true. When a string is initialised without using the new operator, and with an existing string, then the new string also points to the first string’s location. So in the example above str1 and str3 point to the same pool of memory and hence test2 gets set to true. The string str2 on the other hand is created using the new operator and hence points to a different block of memory. Hence test1 gets set to false.

An example of the code above in use is shown below in a short test program. (if you were to compile the code below you would only output the results of test1 and test2).

 

 

The conditional operators && and ||

Operator && returns true if both operands are true, otherwise false. Operator || returns false if one or the other operands is false, otherwise true. Just as in basic AND, OR logic.

&& (AND)

Result

 

|| (OR)

Result

false

false

false

false

false

false

false

true

false

false

true

true

true

false

false

true

false

true

true

true

true

true

true

true

The important thing to note about these operators however, is that they are short-circuited. This means that the left operand before the right operand. If the result of the operation can be evaluated after completing the left operand, then the right side is not computed. In this respect they these operators are different from their bit-wise counterparts – bit-wise AND (&), and bit-wise OR (|).

The bitwise operators are not short-circuited. This means that both the operands of the bit-wise operator will always be evaluated independently of the result of the evaluations.

 

Storing integral types

All the integer types in Java™ are internally stored in two’s complement. In two’s complement, positive numbers have their corresponding binary representation. Two’s complement representation of negative numbers is generated using the following 3 step process.

1.      First get the binary representation of the number.

2.      Then interchange the zeros and ones in the binary representation.

3.      Finally, add one to the result. So for example two’s complement of -18 (minus 18) would be (assuming one byte representation)

·        Converting 18 to binary:                   00010010

·        Interchanging zeros and ones:         11101101

·        Adding 1:                                           11101110

 

So 11101110 would be the binary representation of -18 using two bytes and using two’s complement representation.

 

The shift operators

The shift left operator in Java™ is “<<”. There are two operators for doing the right shift. Signed right shift “>>” and unsigned (or zero fill) right shift “>>>”.

The left shift operator fills the right bits by zero. The effect of each left shift is multiplying the number by two. The example below demonstrates this:

int i = 13;   // i is       00000000 00000000 00000000 00001101

i = i << 2;   // i is now   00000000 00000000 00000000 00110100

After this left shift, i becomes 52 which is the same as multiplying i by 4.

Zero fill right shift is represented by the symbol >>>. This operator fills the leftmost bits by zeros. So the result of applying the operator >>> is always positive. (In two’s complement representation the leftmost bit is the sign bit. If the sign bit is zero the number is positive, similarly, if the sign bit is a one then the number is a negative.) The example below illustrates applying the >>> operator on a number.

int b = 13;   // b is       00000000 00000000 00000000 00001101

b = b >>> 2;  // b is now   00000000 00000000 00000000 00000011

So the result of doing an unsigned (zero fill) right shift by 2 on 13 is 3.

The next example explains the effect of applying the operator >>> on a negative number.

int b = -11;  // b is       11111111 11111111 11111111 11110101

b = b >>> 2;  // b is now   00111111 11111111 11111111 11111101

So the result of applying an unsigned (zero fill) right shift operator with operand 2 on -11 (minus 11) is 1073741821.

Signed right shift operator (>>) fills the left most bit by the sign bit. The result of applying the signed shift bit has the same sign as the left operand. For positive numbers the signed right shift operator and the unsigned (zero fill) right shift operator both give the same results. For negative numbers the results are different. The example below illustrates the signed right shift.

Int b = -11;  // b is 11111111 11111111 11111111 11110101

B = b >> 2;   // b is now 11111111 11111111 11111111 11111101

/* 2’s complement of -3. Here the sign bit 1 gets filled in the two most significant bits.

The result of doing a signed right shift by 2 on -11 is -3.

Recap Operator Precedence

Precedence

Type

Operator

Operation           

Associates

0

 

( )

parenthesis

L to R

1

 

[], ., ,, ++, --

array subscript, member selection, comma delimiter, post increment, post decrement

L to R

2

unary

++, --, +, -, !

prefix increment, prefix decrement, positive, negative, NOT

R to L

3

unary

(type), new

typecast, object instantiation

R to L

4

binary multiplicative

*, /, %

multiplication, division, modulo

L to R

5

binary arithmetic

+, -, +

addition, subtraction, string concatenation

L to R

6

binary shift

<<, >>, >>>

left shift, signed right shift, unsigned right shift (with 0)

 

7

binary relational (evaluates to boolean)

>=, <=, >, <, instanceof

greaterThanOrEqual, lessThanOrEqual, greaterThan, lessThan, type comparison

L to R

8

binary equality (evaluates to boolean)

==, !=

EqualTo, notEqualTo

L to R

9

binary/boolean conjunction

&

bitwise AND, boolean AND

L to R

10

binary/boolean XOR

^

bitwise XOR, boolean XOR

L to R

11

binary/boolean disjunction

|

bitwise OR, boolean OR

L to R

12

logical conjunction

&&

logical AND (short circuits)

L to R

13

logical disjunction

||

logical OR (short circuits)

L to R

14

tertiary conditional (evaluates to boolean)

?:

(boolean statement)?(expression if true):(expression if false)

R to L

15

binary assignment

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

assignment, plusAssgn, minusAssgn, timesAssgn, dividesAssgn, moduloAssgn, leftShiftAssgn, rightShiftAssgn, rightShiftAssgnW0, ANDAssgn, XORAssgn, ORAssgn

R to L

 

 

back