Return to Tutorial Index

Back to the home page of this site

morterboard

Java2 Certification
Tutorial

 

You can discuss this topic with others at http://www.jchq.net/discus
Read reviews and buy a Java Certification book at http://www.jchq.net/bookreviews/jcertbooks.htm


5)Operators and Assignments

Objective 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.

The instanceof operator

The instanceof operator is a strange beast, in my eyes it looks like it ought to be a method rather than an operator. You could probably write an great deal of Java code without using it, but you need to know about it for the purposes of the exam. It returns a boolean value as a test of the type of class at runtime. Effectively it is used to say


Is thisclass an instanceof thisotherclasss

If you use it in the following trivial way it does not seem particularly useful

public class InOf {
        public static void main(String argv[]){
        InOf i = new InOf();
               if(i instanceof InOf){
                   System.out.println("It's an instance of InOf");
                }//End if
        }//End of main
}

As you might guess this code will output

"It's an instance of InOf"

However circumstances may arise where you have access to an object reference that refers to something further down the hierarchy. Thus you may have a method that takes a Component as a parameter which may actually refer to a Button, Label or whatever. In this circumstance the instanceof operator can be used to test the type of the object, perform a matching cast and thus call the appropriate methods. The following example illustrates this

import java.awt.*;
public class InOfComp {
        public static void main(String argv[]){
        }//End of main
        public void mymethod(Component c){
        if( c instanceof Button){
                Button bc = (Button) c;
                bc.setLabel("Hello");
                }
                else
        if (c instanceof Label){
                Label lc = (Label) c;
                lc.setText("Hello");
                }
        }//End of mymethod
}

If the runtime test and cast were not performed the appropriate methods, setLabel and setText would not be available. Note that instanceof tests against a class name and not against an object reference for a class.

The + operator

As you might expect the + operator will add two numbers together. Thus the following will output 10 

int p=5;  
int q=5; 
System.out.println(p+q);  

The + operator is a rare example of operator overloading in Java. C++ programmers are used to being able to overload operators to mean whatever they define. This facility is not available to the programmer in Java, but it is so useful for Strings, that the plus sign is overridden to offer concatenation. Thus the following code will compile

String s = "One";  
String s2 = "Two"  
String s3 = ""; 
s3 = s+s2;  
System.out.println(s3); 

This will output the string OneTwo. Note there is no space between the two joined strings. 

If you are from a Visual Basic background the following syntax may not be familiar

s2+=s3 

This can also be expressed in Java in a way more familiar to a Visual Basic programmer as 

s2= s2+s3 

Under certain circumstances Java will make an implicit call to the toString method. This method as it's name implies tries to convert to a String representation. For an integer this means toString called on the number 10 will return the string "10". 

This becomes apparent in the following code 

int p = 10;  
String s = "Two";  
String s2 = ""; 
s2 = s + p;  
System.out.printlns(s2); 

This will result in the output

Two10 

Remember that it is only the + operator that is overloaded for Strings. You will cause an error if you try to use the divide or minus (/ -) operator on Strings. 

Assigning primitive variables of different types

A boolean cannot be assigned to a variable of any other type than another boolean. For the C/C++ programmers, remember that this means a boolean cannot be assigned to -1 or 0, as a Java boolean is not substitutable for zero or non zero. 

With that major exception of the boolean type the general principle to learn for this objective is that widening conversions are allowed, as they do not compromise accuracy. Narrowing conversions are not allowed as they would result in the loss of precision. By widening I mean that a variable such as a byte that occupies one byte (eight bits) may be assigned to a variable that occupies more bits such as an integer. 

However if you try to assign an integer to a byte you will get a compile time error 

byte b= 10;  
int i = 0;  
b = i;

Primitives may be assigned to "wider" data types, a boolean can only assigned to another boolean

As you might expect you cannot assign primitives to objects or vice versa. This includes the wrapper classes for primitives. Thus the following would be illegal

int j=0;  
Integer k = new Integer(99);  
j=k; //Illegal assignment of an object to a primitive 

An important difference between assigning objects and primitives is that primitives are checked at compile time whereas objects are checked at runtime. This will be covered later as it can have important implications when an object is not fully resolved at compile time. 

You can, of course, perform a cast to force a variable to fit into a narrower data type. This is often not advisable as you will loose precision, but if you really want enough rope, Java uses the C/C++ convention of enclosing the data type with parenthesis i.e. (), thus the following code will compile and run 

public class Mc{ 
public static void main(String argv[]){ 
    byte b=0;  
    int i = 5000;  
    b = (byte) i;  
    System.out.println(b); 
    }  
}

The output is 
-120 

Possibly not what would be required.

Assigning object references of different types

When assigning one object reference to another the general rule is that you can assign up the inheritance tree but not down. You can think of this as follows. If you assign an instance of Child to Base, Java knows what methods will be in the Child class. However a child may have additional methods to its base class. You can force the issue by using a cast operation.









Object references can be assigned up the hierarchy from Child to Base.

The following example illustrates how you can cast an object reference up the hierarchy

class Base{}
public class ObRef extends Base{
public static void main(String argv[]){
        ObRef o = new ObRef();
        Base b = new Base();
        b=o;//This will compile OK
        /*o=b; 	This would cause an error indicating
		an explicit cast is needed to cast Base 
		to ObRef */
        }
}

The bit shifting operators

I hate bit the whole business of bit shifting. It requires filling your brain with a non intuitive capability that an infinitesimally small number of programmers will ever use. But that's all the more reason to learn it especially for the exam as you probably won't learn it via any other means. This objective could do with a whole bunch of warning or banana skin icons, so if anyone has any good ones send them to me.  The results can be surprising, particularly on negative numbers.


To understand it you have to be fairly fluent in at thinking in binary, ie knowing the value of the bit at each position i.e. 

32, 16, 8, 4, 2, 1 

If you are from a C/C++ background you can take slight comfort from the fact that the meaning of the right shift operator in Java is less ambiguous than in C/C++. In C/C++ the right shift could be signed or unsigned depending on the compiler implementation. If you are from a Visual Basic background, welcome to programming at a lower level. 

Note that the objective only asks you to understand the results of applying these operators to int values. This is handy as applying the operators to a byte or short, particularly if negative, can have some very unexpected results. 

Signed shifting << and >>

The left and right shift operators move the bit pattern to the left or right and leave the sign bit alone. 

For positive numbers the results are fairly predictable. Thus the signed shift of the positive number gives the following results
 

int x = 14;  
int y = 0;  
y = x >>2;  


System.out.println(y);  

Outputs 3, one bit is lost and falls off the right hand side 

int x = 14;  
int y = 0;  
y = x <<2;  
System.out.println(y);  

Outputs 56 

So what do you expect to get when you right shift a negative number? You might expect the same result as right shifting a positive number except that the result keeps the negative sign. If we shift 4 places, what actually happens is that the spaces, left moving the other bits across, take on the value of the most significant bit (i.e. the sign bit). The effect of this is that each shift still divides a minus number by two. This sounds like it will be easy enough to understand until you realise the implication of twos complement storage of binary numbers. 

Twos complement works a little like a physical odomenter on a cars clock. Imagine you wind back to zero and then go below zero into the negative numbers. The first number you get to will not be one, but one below the biggest number you can represent with all the available wheels. If this sounds rather unlikely fire up the windows calculator, put it into scientific mode, enter a minus number and then switch to binary mode. This will display the bit pattern for the number you just entered. 

If all of this talk of bit patterns and twos complement representation does your head in a bit you may like to think of the bit shifting as a process of repeated multiplication or division by two. This approach works fine until you start to shift a negative number to the right so it loses bits from the right hand side. 

Unsigned Right Shift >>>

The unsigned right shift >>> performs a shift without attaching any significance to the sign bit. Thus in an integer, all 32 bits are shifted by the value of the operand and padding on the left uses zeros. This also generally has the effect of making a negative number positive. I say generally because before the shift is performed a mod 32 operation is performed on the operand(or mod 64 for a long) The unsighed Right Shift can lead can lead to some very weird results. The following statement

System.out.println(-1 >>>1);

Results in the following output

2147483647

The exam probably won't ask you to give the exact result but it might give you some alternatives such as 0, -1 etc etc and you have to pick the most likely result.

What would you expect the result of the following statement to be?

System.out.println(-1 >>> 32);

If you read that as -1 being shifted 32 places to the right whilst ignoring the significance of the sign place then the real answer of -1 may be a surprise. The reason is the mod 32 that is performed on the operand before the shift. Thus if you divide 32 by 32 you get zero and if you perform an unsigned shift of zero places to the right you still end up with -1. Don't dismiss this as an irrelevent peculiarity as it may come up in the exam.

A mod 32 is performed on the shift operand which affects shifts of more than 32 places

I have created an applet that allows you to try out the various shift operations and see both the decimal and bit pattern results. I have included the source code so you can see how it works, check it out at

http://www.software.u-net.com/applets/BitShift/BitShiftAr.html

Here is a screen shot of this applet in use

BitShift Applet


 

Question 1)

Given the following classes which of the following will compile without error?

interface IFace{}
class CFace implements IFace{}
class Base{}
public class ObRef extends Base{
public static void main(String argv[]){
        ObRef ob = new ObRef();
        Base b = new Base();
        Object o1 = new Object();
        IFace o2 = new CFace();
        }
}

1) o1=o2;
2) b=ob;
3) ob=b;
4) o1=b;


Question 2)

Given the following variables which of the following lines will compile without error?

String s = "Hello";
long l = 99;
double d = 1.11;
int i = 1;
int j = 0;
1) j= i <<s;
2) j= i<<j;
3) j=i<<d;
4)j=i<<l;


Question 3)

Given the following variables

char c = 'c';
int i = 10;
double d = 10;
long l = 1;
String s = "Hello";

Which of the following will compile without error?

1) c=c+i;
2) s+=i;
3) i+=s;
4) c+=s;


Question 4)

What will be output by the following statement?

System.out.println(-1 >>>1);

1) 0
2) -1
3) 1
4) 2147483647


Question 5)

What will be output by the following statement?

System.out.println(1 <<32);

1) 1
2) -1
3) 32
4)-2147483648


Question 6)

Which of the following are valid statements?

1) System.out.println(1+1);
2) int i= 2+'2';
3) String s= "on"+'one';
4) byte b=255;

Answers

Answer 1)

1)o1=o2;
2)b=ob;
4)o1=b; 

Answer 2)

2)j= i<<j;
4)j=i<<l;








Answer 3)

2)s+=i;

Answer 4)

4) 2147483647

Although you might not be able to come up with that number in your head, understanding the idea of the unsigned right shift will indicate that all the other options are not correct.

Answer 5)

1) 1

With the left shift operator the bits wil "wrap around". Thus the result of

System.out.println(1 <<31);
would be -2147483648

Answer 6)

1) System.out.println(1+1);
2) int i= 2+'2';
Option 3 is not valid because single quotes are used to indicate a character constant and not a string.
Option 4 will not compile becuase 255 is out of the range of a byte


Other sources on this topic
The Sun Tutorial
http://java.sun.com/docs/books/tutorial/java/nutsandbolts/operators.html
(nothing on instanceof that I could find at Sun)

Richard Baldwin
http://home.att.net/~baldwin.dick/Intro/Java022.htm#bitwiseoperations
(nothing on instanceof that I could find here either)

Jyothi Krishnan on this topic at

http://www.geocities.com/SiliconValley/Network/3693/obj_sec5.html#obj15

Last updated
7 Jan 2000
copyright © Marcus Green 1999