Title: Operators
Course: CPS 261: Advanced Java Concepts ~ DL & MM MASTER

Operators:

Operator | Definition
+ | Addition
- | Subtraction
* | Multiplication
/ | Division
% | Remainder
++X | Pre-Increment
X++ | Post-Increment
--X | Pre-Decrement
X-- | Post-Decrement
<< | Left Shift
>> | Right Shift. If there is a Sign bit set, then a 1 is propogated in from the left
>>> | Right Shift. A zero is always propogated from the left even for negative numbers
& | And all of the Bits between 2 numbers
| | Or all of the Bits between 2 numbers
~ | Negate all of the Bits in a Number
^ | Exclusive Or all of the Bits between 2 numbers (similar to Or, except when both bits are set, we end up with a zero)
&& | And operation between 2 booleans
|| | OR operation between 2 booleans
! | Negate a boolean
^ | Exclusive Or 2 booleans

Simple Arithimetic Operators: (No booleans)
+     -    *    /    %

Shift   Operators: (No booleans, float or double)
<<      >>     >>>

Post Increment/Decrement, Pre Increment/Decrement (No booleans)
++XValue    XValue++    --XValue    XValue--

Comparison Operators: (No booleans)
<    >    ==   <=   >=   !=

Masking Operators: (No float , or double)
&    |    ~   ^

Special Operators1: (No booleans)
+=    -=    *=    /=     %=

Special Operators2: (No float, double)
&=    |=    ^=

Special Operators3: (No booleans, float, double)
<<=   >>=    >>>=

Boolean Operators:   (booleans only)
&&    ||  !   ^

Run the following program to see what most of the above operators do

Program to Test out Many of the above Operators

Look at the following code to see a detailed breakdown of how to use all of the above operators and which operations are legal for each datatype. In the following code operations that are legal show up with comments that look like:
//!

Sample program that tries all of the possibilities

Compound Operators:

All of the operators which include the = are called compound operators. For example:
+=     *=   -=    /=   %=   &=    |=
^=    <<=    >>=    >>>=

Compound Operators provide a shortcut to a binary operators. For example, the following 2 operations accomplish the same goal:
x = x + y;
x += y;

Another pair of equivalent operations:
x = x >> y;
x >>= y;

method parameter considerations:

Primitive datatypes are passed by-value which means that no matter what the called method does, when the method returns, the passed parameters are unchanged. The called method is in effect only passed a copy of the primitive parameter.


class Parameters
{
    static void modifyPrimitive(boolean boo, char c, byte b,
                        short s, int iValue, long lValue,
                        float f, double d)
    {
        boo = true;
        c ='b';
        b = 13;
        s = 13;
        iValue = 13;
        lValue = 13;
        f = 13.0F;
        d = 13.0;
    }
    public static void main(String[] args)
    {
        boolean myBoo = false;
        char    myChar = 'a';
        byte    myB = 1;
        short   myS = 1;
        int     myI = 1;
        long    myL = 1;
        float   myF = 1.0F;
        double  myD = 1.0;

        modifyPrimitive(myBoo, myChar, myB, myS, myI, myL, myF, myD);

//None of the original values have changed
        System.out.println("myBoo = " + myBoo);
        System.out.println("myChar = " + myChar);
        System.out.println("myB = " + myB);
        System.out.println("myS = " + myS);
        System.out.println("myI = " + myI);
        System.out.println("myL = " + myL);
        System.out.println("myF = " + myF);
        System.out.println("myD = " + myD);
    }
}


Passing Class Instances and Arrays

Now that we have determined what happens when Primitives are passed to a method, its time to look at the more complex objects.

Classes that contain Individual Data -

Consider the following example --- We have a Rectangle class with 2 ints in it. A handle is passed to our modifyObjects method. This method can change the contents of the 2 ints or any other data that is modifiable inside the object instance. The modifyObjects method cannot change the handle itself. In otherwords, the value of myR in the calling program won't change, but the values of data inside the class can change.

Arrays -

In this situation, Arrays are somewhat like Object Instances. A method can't change the handle myArr, but the contents of the array elements can be changed.

Immutable Objects -

We will discuss this more, but there are some classes that can't be changed (they are immutable). The following classes are immutable( String, Integer, Float, Double, etc.). When you attempt to change an immutable object you are creating a new instance of the class. Note that myStr is not changed when you return from modifyObjects.


class Rectangle
{
    int width = 1;
    int height =2;
}
class ObjParameters
{
    static void modifyObjects(Rectangle r, int[] arr, String str)
    {
        r.width = 10;
        r.height = 20;

        for (int i =0; i < arr.length; i ++)
            arr[i] = 10;

        str = "Modified in modifyObjects";
    }
    public static void main(String[] args)
    {
       Rectangle myR = new Rectangle();
       int [] myArr = {1,2,3};
       String myStr ="Original Value";

       modifyObjects(myR, myArr, myStr);

       // Rectangle gets changed
       System.out.println("myR width = " + myR.width + "  height =" + myR.height);

      // Array gets changed.
       System.out.print("myArr = ");
       for (int i = 0; i < myArr.length; i++)
            System.out.print(myArr[i] + ", ");
       System.out.println();

	// Strings don't get changed, because they are Immutable
       System.out.println("myStr = " + myStr);
    }
}


Reference Games

In this example, we are going to set one object equal to another, modify the new object and then see if the original object was changed. We are effectively doing the same thing as we did in the previous example when we passed parameters and we will get the same results. However, we are doing this without making procedure calls.

Make sure you understand what is going on in this example --- ask questions if the following example makes no sense to you.

class Rectangle
{
    int width = 1;
    int height =2;
}
class ObjReferences
{
    public static void main(String[] args)
    {
       Rectangle myR = new Rectangle();
       int [] myArr = {1,2,3};
       String myStr ="Original Value";

       Rectangle r;
       int [] a;
       String s;

       r = myR;
       r.width = 10;
       r.height = 20;
       a = myArr;
       for (int i=0; i < a.length; i++)
            a[i] = 10;

       s = myStr;
       s = "Modified version of String";

    // Rectangle contents are changed
       System.out.println("myR width = " + myR.width + "  height =" + myR.height);

    // Array contents are changed
       System.out.print("myArr = ");
       for (int i = 0; i < myArr.length; i++)
            System.out.print(myArr[i] + ", ");
       System.out.println();

     // String is not changed
       System.out.println("myStr = " + myStr);
    }
}


equals method and Overriding methods in the Object Class

All classes are derived from the Object class. We need to take a look at the key Object class key methods called toString and equals. Most of the classes that Java provides have overriden the default characteristics of these 2 methods.

toString() -

This method is called whenever Java needs to convert your class into a String. For example, in the following example, the toString method available to Rectangle1 will be called:
Rectangle1 r1 = new Rectangle(1,2);
System.out.println("r1 = " + r1);

If you don't override the default toString method in the Object class, your class won't be dumped in a very meaningful way. In the example below, the Rectangle1 class demonstrates the default toString, while the Rectangle2 class uses an overriden toString routine.

= = Operator

When you compare 2 classes with the = = Operator, you are asking whether the handles (pointers) for the two objects point to the same object instance. If the 2 objects have the same contents, but happen to be in different object instances than the = = Operator will return false.

equals method

By default the equals method provided in the Object class works the same as the = = Operator. Traditionally, equals should return true if 2 separate object instances have the same content. For your class to have this behavior, you must override the equals method in your class to provide this functionality. Note that this was done in the Rectangle2 class below:


class Rectangle1
{
    int width = 1;
    int height =2;
    Rectangle1 (int w, int h)
    {
        width = w;
        height = h;
    }
}
class Rectangle2
{
    int width = 1;
    int height =2;
    Rectangle2 (int w, int h)
    {
        width = w;
        height = h;
    }
    public boolean equals(Object obj)
    {
       Rectangle2 r2;

       if (obj != null && obj instanceof Rectangle2)
       {
            r2 = (Rectangle2)obj;
            if (r2.width == width && r2.height == height)
                return true;
            else
                return false;
        }
        else
            return false;
    }
    public String toString()
    {
        return "Rectangle2: width(" + width +
                    ") height(" + height + ")";
    }
}

class ObjectMethods
{
    public static void main(String[] args)
    {
       Rectangle1 r1= new Rectangle1(2,3);
       Rectangle1 r2= new Rectangle1(2,3);

       System.out.println("default r2.toString()  " + r2);

       if  (r1 == r2)
          System.out.println("r1 == r2");
        else
          System.out.println("r1 != r2");

       if (r1.equals(r2))
          System.out.println("r1 equals r2");
        else
          System.out.println("r1 does not equal r2");

      // *******************************************

       Rectangle2 r3= new Rectangle2(2,3);
       Rectangle2 r4= new Rectangle2(2,3);

       System.out.println("MY r3.toString()  " + r3);

       if  (r3 == r4)
          System.out.println("r3 == r4");
        else
          System.out.println("r3 != r4");

       if (r3.equals(r4))
          System.out.println("r3 equals r4");
        else
          System.out.println("r3 does not equal r4");

      // *******************************************

    }
}


String.equals

One of the more common mistakes that is made by beginning Java students is the use of the
= = Operator when the equals method should have been used.

Often it is desired to compare 2 strings. The == operator will tell you whether we are pointing to the same object. However, we usually are only interested in whether the 2 instances have the same content. When we want to know whether we have the same content, we should always use the equals method.

Unfortunately, the == Operator will sometimes seem to work. In the following example, note that comparing
s1 == s3 does return a true. However, comparing
s4 == s5 will not return true. Using the equals method will always give you the correct answer if you want to compare contents. The reason
s1 == s3 has to do with the efficiency of the Java compiler. The Java compiler determines that the literal string used to initialize s1 is the same as s3. So the Java compiler only allocates one hunk of memory for the 2 instances of the same literal string.


class StringEquals
{
    public static void main(String[] args)
    {
       String s1 = "12";
       String s2 = "34";
       String s3 = "12";
       String s4, s5;

       s4 = s1 + s2;
       s5 = s1 + s2;

     // this statement generates a true
       System.out.println("s1 == s3 " + (s1==s3));

     // this statement generates a false
       System.out.println("s4 == s5 " + (s4 == s5));

     // this statement generates a true
       System.out.println("s4.equals(s5) " + s4.equals(s5)  );




    }
}


Ternary Operators

I usually avoid these because I feel that overuse of Ternary Operators leads to unreadable code.

The basic format is:

(boolean expression)? expression1: expression2

A boolean expression is evaluated. If it is true, then expression1 is the result of the above code, otherwise expression2 is the result of the above code.


class Salary {
   public static void main(String [] args) {
      int salary = 30000;
      String status = (salary<15000)?"poor":"not poor";
      System.out.println("This salary is classified as " + status);
   }
}



Precedence:

In evaluating expressions, it is sometimes necessary to know the Order of precedence for operators. Unless parenthesis are used to force a different order, higher priority operators are evaluated first:

1. ++ postfix, -- postfix
2. ++ prefix, -- prefix, + unary, - unary, ~ , !
3. (type) casting
4. *, /, %
5. +(binary), -(binary)
6. <<, >>, >>>
7. <, >, <=, >=, instanceof
8. ==, !=
9. &
10. ^
11. |
12. &&
13. ||
14. ?:(ternary operator)
15. =, +=, -=, *=, /=, %=, >>= <<=, >>>=, &=, ^=, |=

For operators with the same precedence, expressions are evaluated from left to right.

See if you can figure out the result of the following statements:
x = 2;
y = 4;
z = ++x + y-- * 2   << 2;
z = 2*x++ + 3*x++;

x += y/x +10 % 3 * 2 >> 2;

Last Updated: September 20, 2002 10:26 PM