Friday, February 1, 2019

Java Tutorial: Operators

Chapters

Hello everybody! this is brainy ghosts and today we're gonna discuss the java operators. Java has several operator groups, operators are one of the essential part of every programming language for obvious reasons like computing,comparing,etc.

Assignment Operator


Let's create a java file in our workspace folder, then name it "JavaOperators", then write the basic code structure. 

Code:
public class JavaOperators
{
 
 public static void main(String[]args)
 {
  
  
  
 }
 
}
Alright! let's start with the assignment operator(=), you probably know this operator since I explained it in previous tutorials. This operator assigns the value on its right to the operand on its left.
public class JavaOperators
{
 
 public static void main(String[]args)
 {
  
   int intVar = 100;
  
 }
 
}
To understand that definition let's examine this code elaborately. The variables or numbers from the left and right of the operator are called operands. So, assignment operator assigns the operand value from the right to the left operand. From that explanation we can assure that the assignment operator evaluates from right to left. Operators have different ways of evaluation, some evaluates from right to left and vice versa, we will encounter some operators that evaluate from left to right.

Arithmetic Operators

Let's move on to arithmetic operators, Arithmetic operators are easy to understand because its operation and operator symbols are mostly like in mathematics, all arithmetic operators evaluate from left to right. Let's start at the additive(+) operator or the plus sign, This operator adds operands like literals and variables. Note: Unlike the "+" operator, other arithmetic operators like "-","*","/" and "%" doesn't work in String.
Code:
public class JavaOperators
{
 
 public static void main(String[]args)
 {
    String str = "Hello";
    String str2 = "Java!";
    int intVar = 100 + 1;
    String str3 = str + " " + str2;
    System.out.println(intVar);
    System.out.println(str3);
 }
 
}
Next is the subraction(-) operator, This operator substracts operands.
Code:
public class JavaOperators
{
 
 public static void main(String[]args)
 {
   int intVar = 100 - 1;
   System.out.println(intVar);
 }
 
}
Next is the multiplication(*) operator which multiply operands.
Code:
public class JavaOperators
{
 
 public static void main(String[]args)
 {
   int intVar = 100 * 2;
   System.out.println(intVar);
 }
 
}
Next is the division(/) operator which divides operands.
Code:
public class JavaOperators
{
 
 public static void main(String[]args)
 {
   int intVar = 100 / 2;
   System.out.println(intVar);
 }
 
}
Next is the modulus(%) or the remainder operator, This operator divides operands then return a remainder as a result of the operation.
Code:
public class JavaOperators
{
 
 public static void main(String[]args)
 {
   int intVar = 7 % 5;
   System.out.println(intVar);
 }
 
}
The result is 2, because 7/5 = 1 remainder 2. Also, when the dividend(left) is less than divisor(right) the operator will return the dividend as a result. try 5 % 7 and the result is 5.

Unary Operators


unary operators require only one operand; they perform various operations such as incrementing/decrementing a value by one, negating an expression, or inverting the value of a boolean.

Unary Plus(+) Operator

Let's start with the unary plus(+), This operator is rarely used because this operator indicates if the operand or expression is a positive value and since omitting this operator will automatically makes the operand positive, programmers tend to omit the plus unary to save time and reduce ambiguity when writing a code.
Code:
public class JavaOperators
{
 
 public static void main(String[]args)
 {
   int intVar = +7 + +7;
   System.out.println(intVar);
 }
 
}
In this example, we can see that "+" operator can be a unary plus or an additive operator.

Unary Minus(-) Operator

Next is the unary minus(-) which negates an operand or expression, The usage of this operator is similar to unary plus.
Code:
public class JavaOperators
{
 
 public static void main(String[]args)
 {
   int intVar = -7 - +7;
   System.out.println(intVar);
 }
 
}

In this example, we see that "-" can be a unary minus or a subtraction operator. To reduce the ambiguity of unary plus and minus, it is better to enclose the operands in parentheses.

Code: int intVar = (-7) - (+7);

Logical Complement(!) Operator

Next is the logical complement operator(!), this operator is used at boolean value and inverts it.
Code:
public class JavaOperators
{
 
 public static void main(String[]args)
 {
   boolean boolVar = !true;
   System.out.println(boolVar);
 }
 
}
Increment(++) and Decrement(--) Operator

Next is the increment(++) and decrement(--) operator. These two operators can be applied before or after the operand, The effect of the operator on the operand depends on its position. Let's define their usage first and we will use their postfix form where the operator position is at the end of the operand. The increment operator increment its operand by one and decrement operator decrement its operand by one. Now, that we know their general usage let's code their prefix and postfix positioning. let's start with postfix position.
Code:
public class JavaOperators
{
 
 public static void main(String[]args)
 {
   int intOne = 1;
   int intTwo = 1;
   System.out.println(intOne);
   System.out.println(intTwo);
   intOne++;
   intTwo--;
   System.out.println(intOne);
   System.out.println(intTwo);
 }
 
}

In this example, we see the postfix position of increment and decrement operator. Let's try prefix next.
Code:
public class JavaOperators
{
 
 public static void main(String[]args)
 {
   int intOne = 1;
   int intTwo = 1;
   System.out.println(intOne);
   System.out.println(intTwo);
   ++intOne;
   --intTwo;
   System.out.println(intOne);
   System.out.println(intTwo);
 }
 
}
When we compile and run this example, we see that the result of this code and the code before are the same. So, what's the difference between prefix and postfix? Well, in simple cases like this we can use the prefix and postfix form interchangeably but in complex cases like in multihreading or complex loops, it is essential to know their differences. Let's do an example to unveil their differences.
Code:
public class JavaOperators
{
 
 public static void main(String[]args)
 {
   int intOne = 1;
   int intTwo = ++intOne;
   System.out.println("pre: " + intTwo);
   intOne = 1; //resets intOne to 1
   intTwo = intOne++;
   System.out.println("post: " + intTwo);
 }
 
}

In this example, "++" prefix increments intOne by 1 before assigning intOne value to intTwo, that's why the first println result is 2. Next, "++" postfix assigns the value of intOne to intTwo before incrementing intOne value by 1. That's why the second println result is 1. The explanation here can work with "--".

Equality and Relational Operators


The equality and relational operators determine if one operand is greater than, less than, equal to, or not equal to another operand.

"equal to"(==) operator

Let's start with the "equal to"(==) operator, this operator compare two operands, returns true if two operands are equal, otherwise, returns false.
Code:
public class JavaOperators
{
 
 public static void main(String[]args)
 {
   int intOne = 1;
   int intTwo = 1;
   boolean bool = intOne == intTwo;
   System.out.println("Is intOne equals to intTwo? " + bool);
 }
 
}
In this example, the operator returns true because intOne and intTwo values are equal. When "==" operator is used with reference variables, then "==" operator will return true if the reference address of both variables are equal, otherwise, returns false.
Code:
public class JavaOperators
{
 
 public static void main(String[]args)
 {
   String strOne = "String";
   String strTwo = new String("String");
   System.out.println("Is intOne equals to intTwo? "
                      + (strOne == strTwo));
 }
 
}
In this example, strOne and strTwo have the same value but the result is false, that's because strOne reference is different from strTwo reference. We will learn how strOne and strTwo have different reference in future tutorials. To compare String values, use the equals() method.

Code: System.out.println("Is intOne equals to intTwo? " + strOne.equals(strTwo));

"not equal to"(!=) operator

Next is "not equal to"(!=) operator, this operator is the opposite of "equal to" operator. This operator returns true if two operands that being compared are not equal, otherwise, returns false.
Code:
public class JavaOperators
{
 
 public static void main(String[]args)
 {
   int intOne = 1;
   int intTwo = 1;
   boolean bool = intOne != intTwo;
   System.out.println("Is intOne not equals to intTwo? " + bool);
 }
 
}
Greater than(>) and less than(<) operators

Next is the greater than(>) operator, you saw this operator once in your math class, This operator returns true if the left operand is greater than the right operand, otherwise, returns false.
Code:
public class JavaOperators
{
 
 public static void main(String[]args)
 {
   int intOne = 2;
   int intTwo = 1;
   boolean bool = intOne > intTwo;
   System.out.println("Is intOne greater than intTwo? " + bool);
 }
 
}

Next is the less than(<) operator, this operator is the opposite of greater than.
Code:
public class JavaOperators
{
 
 public static void main(String[]args)
 {
   int intOne = 2;
   int intTwo = 1;
   boolean bool = intOne < intTwo;
   System.out.println("Is intOne less than intTwo? " + bool);
 }
 
}

greater than or equal to(>=) and less than or equal to(<=) operators

Next is the "greater than or equal to"(>=) and "less than or equal to"(<=) operators, >= operator returns true if the left operand is greater than or equal to the right operand, otherwise, returns false. <= operator is the opposite of >= operator.
Code:
public class JavaOperators
{
 
 public static void main(String[]args)
 {
   int intOne = 1;
   int intTwo = 1;
   System.out.println("Is intOne greater than or equal to"
              +" intTwo? "+ (intOne >= intTwo));
   System.out.println("Is intOne less than or equal to"
              +" intTwo? "+ (intOne <= intTwo));
   System.out.println("Increment intOne");
   intOne++;
   System.out.println("Is intOne greater than or equal to"
              +" intTwo? " + (intOne >= intTwo));
   System.out.println("Is intOne less than or equal to"
              +" intTwo? " + (intOne <= intTwo));
 }
 
}

"=" operator vs "==" operator

Remember that "=" operator and "==" operator are different. "=" operator is the asssignment operator that assigns a value whereas "==" operator is the equal to operator that compare two operands and returns a boolean value. Some beginners get confuse with this two operators.

Conditional Operators


Conditional-AND(&&) and Conditional-OR(||) operators

Next is the conditional operators. "&&" and "||" operators perform Conditional-AND and Conditional-OR operations on two boolean expressions. These operators exhibit "short-circuiting" behavior, which means that the second operand is evaluated only if needed.
Code:
public class JavaOperators
{
 
 public static void main(String[]args)
 {
   int intOne = 1;
   int intTwo = 1;
   boolean bool = (intOne == 1 && intTwo == 1);
   System.out.println("is intOne and intTwo equals to 1? "
                      + bool); //1st println
   intOne = 2;
   intTwo = 1;
   bool = (intOne == 1 && intTwo == 1);
   System.out.println("is intOne and intTwo equals to 1? "
                      + bool); //2nd println
   intOne = 1;
   intTwo = 1;
   bool = (intOne == 1 || intTwo == 1);
   System.out.println("is intOne or intTwo equals to 1? "
                      + bool); //3rd println
   intOne = 2;
   intTwo = 1;
   bool = (intOne == 1 || intTwo == 1);
   System.out.println("is intOne or intTwo equals to 1? "
                      + bool); //4th println
   intOne = 2;
   intTwo = 2;
   bool = (intOne == 1 || intTwo == 1);
   System.out.println("is intOne or intTwo equals to 1? "
                      + bool); //5th println
 }
 
}
"&&" checks the left and right conditions or operands, if you will. When both conditions are true then the result is true otherwise, the result is false.On the first println(), the result is true because intOne is equal to 1 and intTwo is equal to 1. If the left condition is true then "&&" operator checks the right condition next, if the right condition is true then the overall result is true, otherwise, false. On the second println() the result is false because intOne is not equal to 1. In this case, the left condition is false, therefore "&&" operator doesn't check the right condition and return false as a result. Thus, exhibiting "short-circuiting" behavior.

Next, "||" operator checks the left and right condition, when both or just one condition is true then the result is true, if both conditions are false then the result is false. On the third println() the result is true because both conditions are true, In this case, the left condition is true, therefore, "||" doesn't need to check the right condition. Thus, exhibiting "short-circuiting" behavior. On the fourth println(), the result is still true because, intTwo is equal to 1, In this case, though, the left condition is false, therefore, "||" checks the second condition and since one of the condition is true, the result is still true. The 5th println() result is false because both conditions are false.

Ternary(?:) Operator

ternary(?:) operator can be thought of if-then-else shorthand, if-then-else is part of the control flow statement topic so I won't cover if-then-else but I will demonstrate the ternary operator so you will have an idea on how if-then-else works.
Ternary operator general form: condition ? value1 : value2;
Code:
public class JavaOperators
{
 
 public static void main(String[]args)
 {
   int intOne = 2;
   int intTwo = 1;
   int intThree = (intOne > intTwo) ? intOne : intTwo;
   System.out.println(intThree);
 }
 
}
In this example, if the condition(intOne > intTwo) is true then value1 will be returned to intThree, if the condition is false, then value2 will be returned to intThree. That's why the result is 2 because intOne is greater than intTwo and in our ternary operation intOne is value1.By the way, The parentheses in condition are optional.

Type Comparison Operator


The type comparison operator or instanceof compares an object to a specified type. You can use it to test if an object is an instance of a class, an instance of a subclass, or an instance of a class that implements a particular interface. instanceof is used in typecasting objects.
General Form: object instanceof object-type;
Note: Since java14, instanceof now throws a compilation error instead of runtime error when the two operands are not compatible with each other.
Code:
interface I{}

class A{}

class B extends A implements I{}


public class JavaOperators
{
 
 public static void main(String[]args)
 {
   A a = new A();
   B b = new B();
   
   System.out.println("a instance of B? "
              + (a instanceof B)); //1st println()
   System.out.println("b instance of A? "
              + (b instanceof A)); //2nd println()
   System.out.println("a instance of I? "
              + (a instanceof I)); //3rd println()
   System.out.println("b instance of I? " 
              + (b instanceof I)); //4th println()
   
 }
 
}

In this example, we created an interface and two classes, then we instantiated those classes and compare if they are an instance of an object. On the first println we compare a to class B, and the result is false because class A is a parent class of class B. On the second println() the result is true because B is a subclass of A. On the third println() the result is false class A is not related to interface I. On the fourth println() the result is true because B implemented interface I. Remember that instanceof works with objects and doesn't work with primitive types.

If we reference a null value to a reference variable and use it in instanceof, instanceof will return false.
Code:
interface I{}

class A{}

class B extends A implements I{}


public class JavaOperators
{
 
 public static void main(String[]args)
 {
   B b = null;
   
   System.out.println("b instance of A? " + (b instanceof A));
   
 }
 
}
Don't be overwhelmed by those new keywords and syntax in this example, we will tackle those as we progress further. Just focus on the function of instanceof for now.

Bitwise and Shift Operators


Next is bitwise and bit shift operators. bitwise and bit shift operators are used to manipulate data bits. These operators are less commonly used.

Unary bitwise complement(~) operator

Let's start with the "unary bitwise complement"(~) also called binary ones complement operator, this operator inverts a bit pattern, just like one's complement, let's try it! For the sake of simplicity we will use the byte data type for some bitwise example so we can easily understand the operators that will be discussed here. Unary bitwise can be categorized in unary operators group or in bitwise and shift operator, I just put it in bitwise and shift operator because I think this operator is more related in this category.
Code:
public class JavaOperators
{
 
 public static void main(String[]args)
 {
   int intOne = ~1;
   System.out.println(intOne);
 }
 
}
In this example, the result is -2. To check if the result is correct open windows calculator if you're using windows go to programmer mode, click the Dword radio box, click the initial number(1) and click the "Not" button.

When you type 1 pay attention to the bits on calculator then click "Not" button. You see the zeroes have been flipped to ones and ones have been flipped to zeroes. The result is negative because we're dealing with signed bits when using "~" operator.

Bitwise AND(&) operator

Next is the bitwise AND(&), this operator evaluates each bit of two operands at the same time. If two operands bit is 1 then the result is one, then all other cases result to 0. Let's declare another byte variables let's try the values 50 and 25, then use the bitwise AND and compile and run.
Code:
public class JavaOperators
{
 
 public static void main(String[]args)
 {
   byte byteOne = 50;
   byte byteTwo = 25;
   int intThree = byteOne & byteTwo;
   System.out.println(intThree);
 }
 
}
I used int as intThree data type because the result of the "&" and other bitwise and shift operators are treated as int. If you change intThree data type to byte you will encounter a conversion error. The result of this example is 16. To check if the result is correct laid out their binaries like this:


In this illustration, we see when both operands' bits are 1, the result is 1. When one of the operand bits is 0 then the result is 0.

If you want more proof that our result is correct, open windows calculator if you're using windows, then click the byte radio button, type the first operand, click the "And" button then type the second operand and click "=" button. You see the result is 16.

Bitwise Inclusive OR(|) Operator

Next is the inclusive OR(|) or OR for short. This operator is like the AND but its process is different. If the bits of either operand are 1, the result is 1. all other cases result to 0.
Code:
public class JavaOperators
{
 
 public static void main(String[]args)
 {
   byte byteOne = 50;
   byte byteTwo = 25;
   int intThree = byteOne | byteTwo;
   System.out.println(intThree);
 }
 
}

The result of this example is 59. To compute the result manually try to laid out their binary like this:


In this illustration, we see that if one of the operand bit is 1 or both operands bit are 1 then the result is 1, if both operands bit are 0 then the result is 0.

If you want more proof that our result is correct, open windows calculator if you're using windows, then click the byte radio button, type the first operand, click the "Or" button then type the second operand and click "=" button. You see the result is 59.

Bitwise Exclusive OR(^) Operator

Next is the exclusive OR(^) or XOR for short. This operator is just like inclusive OR but with different rules. If only one of the operand bits is 1 the result is 1, All other cases result to 0.
Code:
public class JavaOperators
{
 
 public static void main(String[]args)
 {
   byte byteOne = 50;
   byte byteTwo = 25;
   int intThree = byteOne ^ byteTwo;
   System.out.println(intThree);
 }
 
}

The result of this example is 43. To compute the result manually try to laid out their binary like this:


In this illustration, we see that when one of the operand bit is 1 then the result is 1, when both operands bit are 1 or 0 then the result is 0.
If you want more proof that our result is correct, open windows calculator if you're using windows, then click the byte radio button, type the first operand, click the "Xor" button then type the second operand and click "=" button. You see the result is 43.

Signed Left Shift(<<) Operator

Signed left shift(<<) shifts bits to the left depending on the specified number of shifts, for example, let's try to shift 50 by 2 shifts. The left operand is the one that will be shifted and the right operand is the number of shift
Code:
public class JavaOperators
{
 
 public static void main(String[]args)
 {
   byte byteOne = 50;
   int intTwo = byteOne << 2;
   System.out.println(intTwo);
 }
 
}
open the windows calculator then go to programmer mode then type 50 with dec radio button selected then select Dword then click the Lsh button "Lsh" is the left shift operator then type the number of shift you want in our case we need 2 shifts. As you can see the result is 200 which is the same result on the console, but why? When we do the signed left shift it will add zeroes to the rightmost bit this bit is also called Least Significant Bit or LSB for short. Here are illustrations that explains how signed left shift works.


when we shift bits, the leftmost bit also called Most Significant Bit or MSB for short will be lost once they are shifted out from position 31 if int and position 63 if long. See the number on the bottom of bits in the calculator? that's the position that I'm talking about. We can see that the bit index in the calculator starts at 0.




Let's do another example, let's try -50 then left shift it to 8.
Code:
public class JavaOperators
{
 
 public static void main(String[]args)
 {
   byte byteOne = -50;
   int intTwo = byteOne << 8;
   System.out.println(intTwo);
 }
 
}
And the result is -12800. Here is an illustration that explains how we got the result.



If you want to check the result on the calculator: go to programmer mode then type 50 with dec radio button selected then click the "+" with "-" button also called the negate button then select Dword then click the Lsh button then type the number of shifts you want in our case we need 8 shifts.

Signed Right Shift(>>) Operator

Next is the signed right shift(>>), this operator shifts bits to the right. As you might have notice this operator has similar procedure to signed left shift but their differences are essential, One of their difference is obvious signed left shift shifts bits from right to left while this operator shifts bits from left to right.

Another difference is the signed right shift is sign dependent. You might asked "how signed right shift is sign dependent? you can't put a positive or negative sign to a binary.", Well, I already discussed how binary represents sign numbers I'll just add some additional information here, Open the window's calculator and select the byte radio button, type 127 and notice the binary.


As you can see the last bit position of byte which is position 7 is zero.

next type 128, reset the values on the calculator first then set the radio button to word because we can't type 128 when we're in the byte range, so, click the Word radio button, type 128 then switch back to byte.


Notice that the positive 128 became negative 128 and in the last bit position of byte which is position 7 is now 1, now, did you get what i'm trying to say? well, if not let me tell you, When the last bit position is zero it means that the binary is representing a positive number and when the last bit position is 1 it means that the binary is representing a negative number, this is only applicable on signed type like byte and all signed type in java, this is not applicable to unsigned type like char because unsigned type only represents positive numbers.

Why do we need to know this? Well, signed right shift depends on the last bit position when shifting bits,for example, let's try -50 then shift it to 2 then compile and run.
Code:
public class JavaOperators
{
 
 public static void main(String[]args)
 {
   byte byteOne = -50;
   int intTwo = byteOne >> 2;
   System.out.println(intTwo);
 }
 
}
In this example, the result is -13. Here are illustrations that show how signed right shift works with negative numbers.



In these Illustrations, we see that the two bits from the right side has been lost and two 1's bits were added to the left side.

You can check our result by using windows calculator: go to programmer mode then type 50 with dec radio button selected then click the "+" with "-" button also called the negate button then select byte radio button then click the Rsh button, "Rsh" is the right shift in the calculator then type the number of shifts you want in our case we need 2 shifts.

Now let's try positive 50 then shift it to 2.
Code:
public class JavaOperators
{
 
 public static void main(String[]args)
 {
   byte byteOne = 50;
   int intTwo = byteOne >> 2;
   System.out.println(intTwo);
 }
 
}
In this example, the result is 12. Here are illustrations that show how signed right shift works with positive numbers



In these Illustrations, we see that the two bits from the right side has been lost and two 0's bits were added to the left side.

Unsigned Right Shift(>>>) Operator

Next is the unsigned right shift(>>>), This operator shifts bits to the right just like signed right shift their difference is that this operator is not sign dependent, it means that this operator will only add zeroes to the right no matter what the value of the Most Significant bit, whereas signed right shift is sign dependent. Let's try an example.
Code:
public class JavaOperators
{
 
 public static void main(String[]args)
 {
   byte byteOne = -50;
   int intTwo = byteOne >>> 2;
   System.out.println(intTwo);
 }
 
}

In this example, the result is 1073741811. How's that happened? Here are illustrations that show how unsigned right shift operator works.



In these illustrations, we see that the bits of -50 on the right side was gone and two zeroes was added on the left side. That's why the result is 1073741811. This operator sometimes doesn't work well with byte and short because the result of >>> operator is treated as int, if we downcast the result of this operator to byte, we might get an unexpected result. But why? You can check my blog about typecasting primitive types and go to the section: "Downcasting a value that exceeds destination's capacity"

Compound Assignment Operators


Next is the compound assignment operators, these operators are shorthand of an operation and assignment. Let's try the "+=" operator, this operator adds the left operand to the right operand and assigns the result to left operand, let's try an example.
Code:
public class JavaOperators
{
 
 public static void main(String[]args)
 {
   byte byteOne = 50;
   byteOne += 50;
   //byteOne = byteOne + 50; //equivalent equation to: byteOne += 50;
   System.out.println(byteOne);
 }
 
}

In this example, the result is 100. Make sure to initialize the variable first before using the compound assignment, if you don't, you will encounter an error.
Code:
public class JavaOperators
{
 
 public static void main(String[]args)
 {
   byte byteOne += 50; //error
   System.out.println(byteOne);
 }
 
}

There are other shorthands as you see from the figure earlier and their functions are similar to this "+=" operator that I demonstrated, I think these operators are fairly easy so I'll leave it to you to explore and try.

No comments:

Post a Comment