Section 5 Operators and assignments
There are different kinds of operators.
1. Unary operators.
1.1 Increment and Decrement operators :
(++ and -- )
You can apply these in two ways: postfix and
prefix form. In post-fix form( eg. x++ ) value of the variable/expression
is modified after the value is taken for the execution of statement. In
prefix form( eg. ++x) , value of the variable/expression is modified before
the value is taken for the execution of statement.
x = 3; y = 1; y = x++; S.o.p(x+" "+y); //will print 4, 3 x = 3; y = 1; y = ++x; S.o.p(x+" "+y); //will print 4, 4 x = 3; x = x++; // Will print 3 !!! Why? Read on...Steps:
1.2 Unary minus and unary plus( + -) : + has no effect other than to stress positivity. - negates an expression’s value. (2’s complement for integral expressions)
int i = 3;
i = -i;
S.o.p(i); //will print -3
i = Integer.MIN_VALUE;
i = -i; //Here,
i will still be Integer.MIN_VALUE because -ive of Integer.MIN_VALUE exceeds
Integer.MAX_VALUE by 1 so it does not fit into an int.
1.3 Boolean Negation (!) : Inverts the value of a boolean expression.
boolean flag = false;
S.o.p( !flag); //will
print 'true'
1.4 Complement ~ (Only for integral types)
Inverts the bit pattern of an integral expression.
int i = 12; // 0000 0000 0000 0000 0000 0000
0000 1100
i = ~i; //
1111 1111 1111 1111 1111 1111 1111 0011
1.5 Cast () : Forces the compiler to cast
one type of value to another type. Compiler still checks whether this cast
is possible or not. If a compiler can prove that the
given cast can never be valid then it give a
compile time error.
int 300; // 0000 0000 0000 0000
0000 0001 0010 1100 , doesn't fit into byte.
byte b = (byte) i; //the cast fits shoves 300
into a byte but takes only last 8 bits: 0010 1100, other bits are lost.
So, b gets 44 instead of 300.
Consider this:
class A { }
class B { }
....
A a = new A();
B b = new B();
Object o = a; //All objects are Objects, so no
cast is needed.
A a1 = (A) o; //All
objects are not objects of class A, so cast is needed. Compiler sees that
a variable of class Object can point to an object of class A, so ok.
B b1 = (B) a; //ERROR,
compiler sees that a variable of class A, can NEVER point to an object
of class B so there is no point in trying to cast a to b.
Arithmetic operators - ( *, / , %, +, -
) (Applied only to numeric types except +
which can be applied to Strings) :
Important Point: All arithmetic operations
are done after promoting (if needed) both the operands to 'int’. And
the result is always atleast an int. That
means, is any of the operands is smaller than an int, then it will be promoted
to either an int or to the type of other operand if it is bigger than int.
ie.
byte b1 = 10;
byte b2 = 20;
byte b3 = b1 + b2; //Will
not compile as b1 and b2 will be promoted to int and the result is an int
which can't be put into a byte without a cast.
byte b1 = 10;
long g = 20;
byte b3 = g + b2; //Will
not compile as b2 will be promoted to long and the result is a long which
can't be put into a byte without a cast.
EXCEPTION Compound operators: +=. -=, etc. b +=
1; will compile because this is interpreted
as:
b = (byte) (b + 1); //Note
the explicit casting. This is automatically done by the compiler for compound
operators.
Points to Remember:
32%7 = 4 ( 32 -
7*4 = 4),
32%-7 = 4 ( 32 - (-7
* -4) = 4),
(-32)%7 = -4 ( -32 - (7*-4) = -4),
-32%-7 = -4 ( -32 - (-7*4) = -4)
<< is used for shifting bits right
to left. 0 bits are brought in from the right.
Sign
bit (MSB) is NOT preserved. Eg.
int i = 0x80000002;; int k = i<<1; i =>
1000 0000 0000 0000 0000 0000 0000 0010 -2147483646 k => 0000 0000 0000
0000 0000 0000 0000 0100 => 4
Notice that sign bit of k (leftmost bit) is 0
that means it is a positive no. In affect, k is i*2 but as -2147483646*2
doesn't fit into an int, overflow occured and only last 32 bits were put
into k.
>> is used for shifting bits left to right.
The sign bit (the leftmost bit or the Most significant bit) keeps propagating
towards right so Sign bit (MSB) IS preserved. Eg. int i = 0x80000002;;
int k = i>>1; i => 1000 0000 0000 0000 0000 0000 0000 0010 -2147483646
k => 1100 0000 0000 0000 0000 0000 0000 0001 -1073741823 Notice that sign
bit of k (leftmost bit) is 0 that means it is a negative no. In affect,
k is i/2 .
There is never an overflow with >> or >>> But
notice what happens with -1:
1111 1111 1111 1111 1111 1111 1111 1111 -1 1111
1111 1111 1111 1111 1111 1111 1111 -1 -1 >> -1 is -1
>>> is same as >> except that sign is not preserved.
0
bits are inserted from the right instead of the sign bits. Eg.
int i = 0x80000002;; int k = i>>>1; i => 1000
0000 0000 0000 0000 0000 0000 0010 -2147483646 k => 0100 0000 0000 0000
0000 0000 0000 0001 1073741825
Notice that sign bit of k (leftmost bit) is 0
that means it is a positive no. In affect, k is i/2 .
Points to remember:
Points to remember:
Points to remember:
Points to remember:
Important Fact: You may know that other operators return a value. Eg. a + b returns the sum of a and b, a^b returns the XOR of a and b etc. What you may not know is the = operator also returns a value. I.e a = 3 assigns 3 to a but the whole expression (a=3) also returns a value which is equal to the RHS of the operator ie. 3. That's the reason b = a = 3; works. And that's the reason if( flag = true){} also works.
Compound operators: a
+= b; is actually interpreted by the compiler
as: a = (type of a) (a + b);
So,
byte b = 3; b = b+1; //won't
work as b + 1 returns an int and explicit cast is needed.
b += 1; // will
work because it is interpreted as: b = (byte) (b+1);
Note the cast.
Ternary Operator:
Possible uses:
int a, b, c; // initialize the values somehow.
boolean flag = ...//some way of setting it.
a = flag? 10:20; a = (b == c) ? m1() : m2();
Here, it is important to know that it will
only compile if the return types of m1() and m2 are compatible with the
type of a. It won't compile if m1() or
m2() return void.
Points to remember:
Consider the declarations:
String s1, s2; //initialize them somehow
Boolean bool1, bool2;//initialize them somehow
boolean flag1, flag2; //initialize them somehow
Object obj1; //initialize it somehow
Points to remember:
Points to Remember:
int i = 10;
boolean flag = true;
if( flag || ++i = 11) { ... } // Here, i will NOT be incremented.
if( !flag && ++i = 11) { ... }// Here, i will NOT be incremented.
if( flag || m1() ) { ... } // Here, m1 will NOT be called.
In the above cases, the outcome of the whole expression
can be determined by just looking at the first part, so second part is
NOT evaluated.
VERY IMPORTANT FACT: In java EVERY
THING is passed by value. For primitive, it's value is passed
(as expected). For object, the value of it's reference is passed. Read
a detailed example explanation here : Pass
by value
void changeObjects(String str, StringBuffer sb)
{
str = "123"; //makes the reference str to point to new string object containing "123". you are changing the reference here.
str = str + "123"; //strings are immutable. It will create a new string containing "abc123". The original "abc" will remain as it is.
sb.append("123"); //changes the actual object itself. you are NOT changing the reference here.
}
....
String s = "abc";
StringBuffer sb = new StringBuffer("abc");
changeString(s, sb);
System.out.println(s); //Will still print "abc".
System.out.println(sb); //Will still print "abc123".