The Shift Operators (<<, >>,>>>) in Java

The Java language provides three operator for performing bitwise shifting on 32 and 64 bit integer values. These are all binary operators with the first operand being the value to be shifted, and the second operand saying how far to shift.

  • The << or left shift operator shifts the value given by the first operand leftwards by the number of bit positions given by the second operand. The empty positions at the right end are filled with zeros.
  • The ‘>>’ or arithmetic shift operator shifts the value given by the first operand rightwards by the number of bit positions given by the second operand. The empty positions at the left end are filled by copying the left-most bit. This process is known as sign extension.
  • The ‘>>>’ or logical right shift operator shifts the value given by the first operand rightwards by the number of bit positions given by the second operand. The empty positions at the left end are filled with zeros.

Notes:

  1. These operators require an int or long value as the first operand, and produce a value with the same type as
    the first operand. (You will need to use an explicit type cast when assigning the result of a shift to a byte,
    short or char variable.)
  2. If you use a shift operator with a first operand that is a byte, char or short, it is promoted to an int and the
    operation produces an int.)
  3. The second operand is reduced modulo the number of bits of the operation to give the amount of the shift. For
    more about the mod mathematical concept, see Modulus examples.
  4. The bits that are shifted off the left or right end by the operation are discarded. (Java does not provide a
    primitive “rotate” operator.)
  5. The arithmetic shift operator is equivalent dividing a (two’s complement) number by a power of 2.
  6. The left shift operator is equivalent multiplying a (two’s complement) number by a power of 2.

The following table will help you see the effects of the three shift operators. (The numbers have been expressed in binary notation to aid vizualization.)

There examples of the user of shift operators in Bit manipulation

The Instance of Operator

This operator checks whether the object is of a particular class/interface type. instanceof operator is written as:

( Object reference variable ) instanceof (class/interface type)

Example:

public class Test {
     public static void main(String args[]){
          String name = "Buyya";
          // following will return true since name is type of String
          boolean result = name instanceof String;
          System.out.println( result );
     }
}

This would produce the following result:

true

This operator will still return true if the object being compared is the assignment compatible with the type on the right.

Example:

class Vehicle {}
public class Car extends Vehicle {
    public static void main(String args[]){
        Vehicle a = new Car();
        boolean result = a instanceof Car;
        System.out.println( result );
    }
}

This would produce the following result:

true

The Assignment Operators (=, +=, -=, *=, /=, %=, <<=, >>= , >>>=, &=, |= and ^=)

The left hand operand for these operators must be a either a non-final variable or an element of an array. The right hand operand must be assignment compatible with the left hand operand. This means that either the types must be the same, or the right operand type must be convertible to the left operands type by a combination of boxing, unboxing or widening. (For complete details refer to JLS 5.2.)

The precise meaning of the “operation and assign” operators is specified by JLS 15.26.2 as:

A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (T) ((E1) op (E2)), where T is the type of E1, except that E1 is evaluated only once.

Note that there is an implicit type-cast before the final assignment.

  1. =

The simple assignment operator: assigns the value of the right hand operand to the left hand operand.

Example: c = a + b will add the value of a + b to the value of c and assign it to c
  1. +=

The “add and assign” operator: adds the value of right hand operand to the value of the left hand operand and assigns the result to left hand operand. If the left hand operand has type String, then this a “concatenate and
assign” operator.

Example: c += a is roughly the same as c = c + a
  1. -=

The “subtract and assign” operator: subtracts the value of the right operand from the value of the left hand
operand and assign the result to left hand operand.

Example: c -= a is roughly the same as c = c - a
  1. *=

The “multiply and assign” operator: multiplies the value of the right hand operand by the value of the left hand
operand and assign the result to left hand operand. .

Example: c *= a is roughly the same as c = c * a
  1. /=

The “divide and assign” operator: divides the value of the right hand operand by the value of the left hand operand
and assign the result to left hand operand.

Example: c /*= a is roughly the same as c = c / a
  1. %=

The “modulus and assign” operator: calculates the modulus of the value of the right hand operand by the value of
the left hand operand and assign the result to left hand operand.

Example: c %*= a is roughly the same as c = c % a
  1. <<=

The “left shift and assign” operator.

Example: c <<= 2 is roughly the same as c = c << 2
  1. >>=

The “arithmetic right shift and assign” operator.

Example: c >>= 2 is roughly the same as c = c >> 2
  1. >>>=

The “logical right shift and assign” operator.

Example: c >>>= 2 is roughly the same as c = c >>> 2
  1. &=

The “bitwise and and assign” operator.

Example: c &= 2 is roughly the same as c = c & 2
  1. |=

The “bitwise or and assign” operator.

Example: c |= 2 is roughly the same as c = c | 2
  1. ^=

The “bitwise exclusive or and assign” operator.

Example: c ^= 2 is roughly the same as c = c ^ 2

The conditional-and and conditional-or Operators ( && and || )

Java provides a conditional-and and a conditional-or operator, that both take one or two operands of type boolean and produce a boolean result. These are:

  • && – the conditional-AND operator,
  • || – the conditional-OR operators. The evaluation of && is equivalent to the following pseudo-code:
{
     boolean L = evaluate();
     if (L) {
          return evaluate();
     } else {
         // short-circuit the evaluation of the 2nd operand expression
        return false;
    }
}

The evaluation of || is equivalent to the following pseudo-code:

{
    boolean L = evaluate();
    if (!L) {
        return evaluate();
    } else {
        // short-circuit the evaluation of the 2nd operand   expression
       return true;
    }
}

As the pseudo-code above illustrates, the behavior of the short-circuit operators are equivalent to using if / else statements.

Example – using && as a guard in an expression

The following example shows the most common usage pattern for the && operator. Compare these two versions of a method to test if a supplied Integer is zero.

public boolean isZero(Integer value) {
      return value == 0;
}

public boolean isZero(Integer value) {
      return value != null && value == 0;
}

The first version works in most cases, but if the value argument is null, then a NullPointerException will be thrown.

In the second version we have added a “guard” test. The value != null && value == 0 expression is evaluated by first performing the value != null test. If the null test succeeds (i.e. it evaluates to true) then the value == 0
expression is evaluated. If the null test fails, then the evaluation of value == 0 is skipped (short-circuited), and we don’t get a NullPointerException.

Example – using && to avoid a costly calculation

The following example shows how && can be used to avoid a relatively costly calculation:

public boolean verify(int value, boolean needPrime) {
      return !needPrime | isPrime(value);
}

public boolean verify(int value, boolean needPrime) {
     return !needPrime || isPrime(value);
}

In the first version, both operands of the | will always be evaluated, so the (expensive) isPrime method will be called unnecessarily. The second version avoids the unnecessary call by using || instead of |.

Related Article: Object Class Methods and Constructor in Java

The Relational Operators (<, <=, >, >=)

The operators <, <=, > and >= are binary operators for comparing numeric types. The meaning of the operators is as
you would expect. For example, if a and b are declared as any of byte, short, char, int, long, float, double or the
corresponding boxed types:

The result type for these operators is boolean in all cases.
Relational operators can be used to compare numbers with different types. For example:

int i = 1;
long l = 2;
if (i < l) {
      System.out.println("i is smaller");
}

Relational operators can be used when either or both numbers are instances of boxed numeric types. For example:

Integer i = 1; // 1 is autoboxed to an Integer
Integer j = 2; // 2 is autoboxed to an Integer
if (i < j) {
     System.out.println("i is smaller");
}
The Equality Operators (==, !=)

The == and != operators are binary operators that evaluate to true or false depending on whether the operands are equal. The == operator gives true if the operands are equal and false otherwise. The != operator gives false if
the operands are equal and true otherwise.

These operators can be used operands with primitive and reference types, but the behavior is significantly different. According to the JLS, there are actually three distinct sets of these operators:

  • The Boolean == and != operators.
  • The Numeric == and != operators.
  • The Reference == and != operators.

However, in all cases, the result type of the == and != operators is boolean.

The Numeric == and != operators

When one (or both) of the operands of an == or != operator is a primitive numeric type (byte, short, char, int, long, float or double), the operator is a numeric comparison. The second operand must be either a primitive
numeric type, or a boxed numeric type.

The behavior other numeric operators is as follows:

  1. If one of the operands is a boxed type, it is unboxed.
  2. If either of the operands now a byte, short or char, it is promoted to an int.
  3. If the types of the operands are not the same, then the operand with the “smaller” type is promoted to the “larger” type.
  4. The comparison is then carried out as follows:
    • If the promoted operands are int or long then the values are tested to see if they are identical.
    • If the promoted operands are float or double then:
      • the two versions of zero (+0.0 and -0.0) are treated as equal
      • a NaN value is treated as not equals to anything, and
      • other values are equal if their IEEE 754 representations are identical.

Note: you need to be careful when using == and != to compare floating point values.

The Boolean == and != operators

If both operands are boolean, or one is boolean and the other is Boolean, these operators the Boolean == and != operators. The behavior is as follows:

  • If one of the operands is a Boolean, it is unboxed.
  • The unboxed operands are tested and the boolean result is calculated according to the following truth table
ABA==BA!=B
FALSEFALSETRUEFALSE
FALSETRUEFALSETRUE
TRUEFALSEFALSETRUE
TRUETRUETRUEFALSE

There are two “pitfalls” that make it advisable to use == and != sparingly with truth values:

  • If you use == or != to compare two Boolean objects, then the Reference operators are used. This may give an unexpected result; see Pitfall: using == to compare primitive wrappers objects such as Integer
  • The == operator can easily be mistyped as =. For most operand types, this mistake leads to a compilation error. However, for boolean and Boolean operands the mistake leads to incorrect runtime behavior; see Pitfall – Using ‘==’ to test a boolean

The Reference == and != operators

If both operands are object references, the == and != operators test if the two operands refer to the same object. This often not what you want. To test if two objects are equal by value, the .equals() method should be used
instead.

String s1 = "We are equal";
String s2 = new String("We are equal");

s1.equals(s2); // true

// WARNING - don't use == or != with String values
s1 == s2; // false

Warning: using == and != to compare String values is incorrect in most cases;

About the NaN edge-cases

JLS 15.21.1 states the following:

If either operand is NaN, then the result of == is false but the result of != is true. Indeed, the test x != x
is true if and only if the value of x is NaN.

This behavior is (to most programmers) unexpected. If you test if a NaN value is equal to itself, the answer is “No it
isn’t!”. In other words, == is not reflexive for NaN values.

However, this is not a Java “oddity”, this behavior is specified in the IEEE 754 floating-point standards, and you will find that it is implemented by most modern programming languages.

The Lambda operator ( -> )

From Java 8 onwards, the Lambda operator ( -> ) is the operator used to introduce a Lambda Expression. There are two common syntaxes, as illustrated by these examples:

Version ≥ Java SE 8
a -> a + 1             // a lambda that adds one to its argument
a -> { return a + 1; } // an equivalent lambda using a block.

A lambda expression defines an anonymous function, or more correctly an instance of an anonymous class that implements a functional interface.
(This example is included here for completeness. Refer to the Lambda Expressions topic for the full treatment.)

LEAVE A REPLY

Please enter your comment!
Please enter your name here