Java2 Certification
|
|
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
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 */ } }
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.
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.
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
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;
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;
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;
What will be output by the following statement?
System.out.println(-1 >>>1);
1) 0
2) -1
3) 1
4) 2147483647
What will be output by the following statement?
System.out.println(1 <<32);
1) 1
2) -1
3) 32
4)-2147483648
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;
1)o1=o2; 2)b=ob; 4)o1=b;
2)j= i<<j; 4)j=i<<l;
2)s+=i;
If you want to test these possibilities, try compiling this code
public class Llandaff{ public static void main(String argv[]){ Llandaff h = new Llandaff(); h.go(); } public void go(){ char c = 'c'; int i = 10; double d = 10; long l = 1; String s = "Hello"; //Start commenting these out till it all compiles c=c+i; s+=i; i+=s; c+=s; } }
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.
1) 1
With the left shift operator the bits wil "wrap around". Thus the result of
System.out.println(1 <<31); would be -2147483648
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
Twos Compliment Math
http://www.duke.edu/~twf/cps104/twoscomp.html
Article on Binary/Hex/Decimal Numbers by Jane Griscti
http://www.janeg.ca/scjp/oper/binhex.html
Shfting from JavaRanch
www.javaranch.com/campfire/StoryBits.jsp
Last updated
12 August 2001
copyright © Marcus Green 2001