Dr. Dobb's Journal Fall 1998
If you've been programming in Java for some time, you may think you're becoming an expert. You've wrestled with how to best use interfaces; you've mastered Java's event handling mechanism; you've even written one or two pure Java client/server applications. It might be time to consider becoming a Sun Certified Java Programmer.
When you need to prove you know Java like the back of your hand, you could whip out a laptop and program a cool workflow application. While that would be impressive, you could also pull out your business card and show the challenger a logo that says you've been certified by Sun as a Java programmer. That might be equally as impressive. (And a business card is a lot easier to carry around than a laptop.)
Branding yourself as a Sun Certified Java Programmer identifies you as someone who has taken the time to be recognized as an expert. Yes, there are plenty of people who have not been certified and who are also experts. You might be one of them. But it takes longer to prove you know what you say you know. And if you're trying to get your foot in the door for a job or assignment, having that credential can help create that opening.
I'll get to the technical challenges of becoming certified in a moment. But let's start by skipping right to the question that everyone asks -- is it worth it? Is it worth buying one of the study guides, studying for days or weeks, and finally paying $150.00 for the privilege of sweating through a tough, two-hour test that might be subtitled "Java trivial pursuit"?
My answer is: It depends on who you are. If you're about to make the leap into Java consulting or training, being certified is invaluable. I can tell you firsthand it has gotten me many assignments. If you want to stand out in the crowd of Java programmers, even within your own company, becoming certified is just what you need. On the other hand, if you are the chief technology officer for a global corporation, you might have all of the credentials you need. Or, if you're getting all the challenges and interesting assignments you want, then you might not want to bother -- at least not for the time being.
Either way, it certainly can't hurt you to be certified as a Java programmer if you want to show the world you are an expert. It can be a valuable credential, and you shouldn't scoff at the test before you've seen how difficult the test really is.
Many sharp Java programmers have gone down in a blaze of glory underestimating the test. The failure rate is high because the test is tough. To pass, you need lots of hands-on experience. You also need to study. I'll treat the rest of this article as a study guide. In fact, let's play a little Java trivial pursuit!
What are the colorful, little wedges you need to collect in your game board marker? The questions range over a wide area, including:
Here are four examples to test your Java mettle.
Some questions are easy to answer -- if you only had a moment to create a program and run it through your Java virtual machine. However, you don't have this luxury when taking the test. Here's an example involving casting.
Question: Given the classes in Example 1, what appears in the standard output when you run the Test class in the JVM? Select the single correct answer:
a. First the number 2, then the number 1.
b. First the number 1, then the number 2.
c. The number 1, then the number 1 again.
d. The number 2, then the number 2 again.
e. This code will not even compile, because you cannot declare an instance variable with the same name as an instance variable in a superclass.
Solution: Answering this question involves knowing how Java invokes a method and accesses data.
When you invoke a method given an object reference, the method that Java invokes depends on the actual type of that underlying object. In this question, the actual data type is class B, even though the object reference is declared as class A. When you invoke a.method(), class B's method is actually invoked. This is probably what you would expect; the behavior depends upon the actual object type.
However, this is not the case for accessing data. Even though you created an instance of class B, you assigned it to a reference whose type is class A. When you look at i, you get the value for an instance of class A, which is 1.
So, the answer here is a.
The fact that the declared type of an object determines which variable it accesses is a feature, not a problem. This allows you to get at a variable anywhere in a class hierarchy, even if a variable with that same name is declared again lower down in the hierarchy. You don't have this same problem with methods, because methods can always invoke their superclass's behavior to climb back up the hierarchy.
For example, if you were to add these two lines to the end of the main() method:
B b = (B)a; System.out.println(b.i);
then, given what you've just learned, what gets written to the standard output? The answer is the number 2. Java goes to the declared data type, which now is class B. In the object whose data type is declared as class B, i is set to 2.
The certification test requires that you understand what's going on with objects and references to objects.
Question: Given the definition in Example 2(a) for a class named Info, what happens when you run the main() method for Test in Example 2(b), assuming Info and Test are both defined in the same package? Select the single correct answer.
a. The main() method in Test ends prematurely because of a NullPointerException.
b. The number "1" is written to the standard output.
c. The number "2" is written to the standard output.
d. The value "null" is written to the standard output.
e. Nothing appears in the standard output.
Solution: This question is a classic that cuts to the heart of how Java uses pointers without calling them pointers. When you pass a primitive data type to a method, you are passing that primitive data type by value. For example, if you wrote the change() method in Example 2 as:
static void change(int i) {
i *= 2;
}
and you invoked it like this:
int i = 1; change(i);
the value 1 would be doubled in change(), but the i in change() has nothing to do with the i passed to change(). That is, arguments are passed by value, and changing a parameter in change() does not affect the argument passed to change().
This might seem straightforward enough, but the situation is trickier with objects. In the code in this question, the object reference is passed by value -- not the object itself. That is, the object is not copied, placed onto the stack, and passed to change(), as the case would be if the value passed to change() were an integer (or if this were C++ and you passed the object rather than a pointer to the object). Instead, the object reference is copied and passed to change(). Each reference has its own four bytes allocated to it and each reference points to the same underlying object. Figure 1 shows the situation just after the call to change().
The change() method doubles the value in the underlying object, as in Figure 2.
Finally, the reference in change() is set to null. But you still have a reference to the underlying object in the program that invoked change(); see Figure 3.
When you pop out of change(), the Info object has been updated, and you still have a reference to it. So, the correct answer is c.
One of the most difficult aspects to the test is that some questions may have more than one right answer. Here is an example involving constructors.
Question: Given the class definitions in Example 3 for A and B, what will happen when you try to invoke B's main() method? Choose all correct answers.
a. The number 1 will appear in the standard output.
b. The number 2 will appear in the standard output.
c. The number 3 will appear in the standard output.
d. The code will cause an InstantiationException to be thrown.
e. The code will not compile.
Solution: Let's trace through this code very carefully to see what the correct answer(s) might be.
You try to create a new instance of class B. You invoke a constructor with two int arguments. You have a constructor for B that takes two int arguments. So far, so good.
What happens next? B tries to invoke its superclass's constructor. Which constructor? The two argument constructor? No, sir! Since there is no explicit call to a constructor, class B invokes its superclass's no-args constructor.
The trouble is, there is no no-args constructor in class A in this case. Since you have overloaded the constructors in class A, Java does not provide a default, no-args constructor. The result is that this code does not even compile! The correct answer is e.
As you can see, even though you were instructed to "choose all correct answers," there was, in this case, only one right answer! Don't let this kind of thing throw you off on the real test.
Some questions require that you fill in the blank with your own solution. While this can be a snap if you had access to the APIs, you only have scratch paper to work with during the exam.
Question: How can you create an object that translates characters from a text file written using the encoding "8859-6" into Unicode? In your answer, assume you have an InputStream object associated with this text file referenced by the variable inStream. Assume that the local encoding is "8859-7". You should also declare your new object and call it obj in the same line of code that you create this new object.
Solution: Getting this question right means knowing a bit about the Reader and Writer classes, which are new in Java 1.1. In Java 1.0, there was a wide, nearly insurmountable gulf between local encoding (an example being eight-bit ASCII) and Unicode. If you are only ever working with files produced in a word processor in the United States, this is probably not a problem. The translation between ASCII to Unicode and back is trivial -- the upper eight bits in a Unicode representation of an ASCII value are 0, and the lower eight bits are the same as the ASCII value.
But here's the problem: Java is geared towards an international audience. If you're going to truly take advantage of Unicode, then you've got to be able to read files and write files based on any encoding in the world -- even if the files are different from the local encoding. This means you have to bridge the gap between the eight-bit world of operating systems and local files, and the 16-bit world of Java.
Here's an example: Suppose you have a file that is based on the encoding 8859-6, which happens to be Arabic. Figure 4 shows what that character set looks like.
If you assume that the local encoding is ISO 8859-7, you'll get into trouble in your mapping to Unicode if you don't specify you want an ISO 8859-6-specific mapping. Figure 5 shows what ISO 8859-7 looks like. You can see the characters are very different, and they would map to very different places in the Unicode character set, even though their local encoding uses the same bit patterns.
Luckily, this is not a problem in Java 1.1. If you want to specifically translate between a particular encoding and Unicode, you can use a class called InputStreamReader to do that for you. One of InputStreamReader's constructors takes two arguments: the input stream, and the encoding to use. Knowing this, your task is easy. The solution is:
InputStreamReader obj = new InputStreamReader(inStream, "8859-6");
This will map the characters in the text file referenced through inStream to Unicode using the ISO 8859-6 encoding, even though the local encoding would have made Java map the characters to a different part of Unicode given the same bit patterns in the text file.
As you might be able to tell from these questions, it's unlikely that someone who is not an expert in Java can pass the certification tests. The questions are just too difficult. If you answered these questions without trouble, then you might want to consider becoming certified by Sun as an expert (you need a score of 70 percent or above to pass). If you found these questions tricky, you might want to set your sights on passing this test to reach a mastery of the language.
If answering 60 difficult multiple-choice and fill in the blank questions does not make you feel like an expert, there's always the second level of certification: the Developer test. Developer certification consists of two parts: completing an involved coding assignment (my test had a 30 page spec), and then answering five essay questions to justify your design and implementation decisions.
The idea behind this two-tiered approach is that the programmer test confirms you can implement code using Java. The developer test challenges you to design using the benefits of Java's object-oriented nature.
Whether you decide to pursue Java certification or not, just studying for the test can sharpen your skills and reveal features and facts about the language that you didn't know before.
For More Information
Sun Microsystems Inc.
Sun Educational Services
901 San Antonio Road
Palo Alto, CA 94303
800-422-8020
http://suned.sun.com/suned/ index.html
DDJ