Sun Certified Programmer Examination Revision Book

©1999 Dylan Walsh

:

Disclaimers

No claims are made about the accuracy of this document and no responsibility is taken for any errors. The exam objectives below, in green, are quoted from Sun Microsystems website. The author has not corrected any errors in the text of those objectives (of which there are many, both grammatical and factual). Also there are parts quoted from the Javadocs, also the property of Sun Microsystems.

If you find any errors, please email dylanwalsh@engineer.com

Introduction

The purpose of this document is to provide a basis for revising for the Sun Certified Programmer examinations not to teach the Java language or the topics required for the exam. It is designed to collect all the essential information you need to retain, in one place, and is designed for someone who has already finished their own study, and is about to take the exam.

If you are just starting to prepare for the exam, then I recommend the following steps:

  1. Buy a good certification book, read the chapters, and do all of the example questions and exercises. This is necessary even if you are already experienced in Java. According to Barry Boones book, Java instructors have failed this exam. Many people have to take the exam more than once, and there are thing which are examined that you may not encounter in everyday programming, or would lookup in the docs as needed. This exam is regarded as being more difficult than most other certifications.
  2. The books I used to study for the exam were:
  3. Java 1.1 Certification Study Guide, by Roberts and Heller

    Java Certification for Programmers and Developers, by Barry Boone

    You don't need to buy both, but I found that a good way to study was to do one chapter from each every evening. I did chapters on different topics, which made it more interesting and meant that I revised the same topic later in the other book. If you are going to buy just one, then get the Roberts and Heller one, it is widely regarded as the best. Both of these are designed for 1.1, but there are new versions for Java 2 in the pipeline (search on Amazon).

  4. There are courses available which I cannot comment on as I studied for the exam without sitting any courses. While these may be worthwhile, I suggest you still follow step 1. as they may be general Java courses, and not cover some of the specific issues which come up in the exam.
  5. When you are finished studying, do any and all mock exams available. In addition to those which come with the books, there many available online, and you can find lists of links to them on some of the websites below. Do not sit the exam until you are getting marks above the pass level (71%, I suggest aiming for 80% or more in the practice exams). A habit you may find useful is when you are marking yourself, for every question you get wrong, hit yourself over the head with a baseball bat… Just kidding, for every question you get wrong, find out what the right answer is, and why, and write that down in a notebook for future revision. Make sure you do the Sun sample questions - there are approx. ten available for each of the Java 1.02, 1.1 and 2 exams, and I suggest doing all of them as they most accurately reflect the exam.
  6. Read this document the night, or morning, before you take the exam.

 

 

The Exam

Here are just a few comments on the exam itself. Firstly, time will not be a problem, you should have time to answer all the questions, and review them, and possibly be able to leave early. It will really be an issue of whether you know/understand what it required. Generally, the questions in the real exam are a lot better than the mock exams which are going around: They are unambiguously worded, the sample code is usually short, and the slant of the questions is towards whether you understand the principles rather than whether you have memorized a lot of methods etc. The majority of the questions are on the core language itself rather than its APIs i.e. language fundamentals rather than AWT, Input/Output, java.lang etc. Of course, you do need to study these topics to get a pass mark.

About This Document

This document is structured around the objectives for the exams. For each objective, I have attempted to list all the bare-bones information you may need to remember for the exam.

The objectives for the Java 2 platform are much more concise and less detailed than those for 1.1, so this document is based around the latter. Where there are any differences in the Java 2 exam, I have described them.

 

Section Title: Language Fundamentals

Java 1.1: Only methods defined in the current class are listed, not those inherited from its super class. So if you can't find a method you think should be there, search up the class inheritance hierarchy.

The new Javadoc format in the JDK 1.2 shows inherited members (in their own tables), so this point may not be relevant to the Java2 platform exam.

 

The order is as follows: package declarations, import statements, then class definitions. The order of public vs. non-public class definitions does not matter. However, note that with Suns JDK, you can only have one top-level public class per source file, and the name of the file must be the same as the name of the public class. For example;

package acme.applications.userinterfaces;

import java.awt.*

public class SomeClass {

etc.

 

[The following rules apply to creating a main() method, which allows you to run the class as an application. You can create any number of methods in a class called main (overloading), which take other arguments, are not public and static, or return a value. To be able to run the class, however, there must be one method called main that takes an array of Strings as an argument, and that method must be public, static, and not return a value. Otherwise you will get a runtime error when you try to execute the class]

The main() method must be public, static, not return a value, and take an array of strings. Either of the following two examples are the accepted way of declaring main (depending on who you listen to):

public static void main(String[] args)

public static void main(String args[])

 Note that 'args' is just a common name for the array, and you can call it anything you like. Also:

static public void main(String[] args)

is perfectly legal and will compile.

 

The command line arguments, after the java command and the name of the program, are placed in the String array, starting at array element zero.

 

Java keywords (check that you know what each of these does, if not, find out before you take the exam!):

abstract

boolean

break

byte

case

catch

char

class

const

continue

default

do

double

else

extends

final

finally

float

for

goto

if

implements

import

instanceof

int

interface

long

native

new

null

package

private

protected

public

return

short

static

super

switch

synchronized

this

throw

throws

transient

try

void

volatile

while

The keywords in red are reserved but not used.

Note that while they are not keywords, the boolean and null literals (true, false and null) cannot be used as identifiers.

[Note that Roberts & Heller lists true and false as keywords on page 4, but these are literals, not keywords]

 

Class level variables (variables declared in the class, but outside of any methods, i.e. static and instance variables) are automatically initialised to a default value, if no explicit assignment has been made. The defaults are 0 for numerical types, '\u000' for chars, false for booleans, and null for objects.

 

The elements of an array are always (even inside a method) initialised to their default values when no explicit assignment has been made to the element.

 

If you do not initialise a variable declared in a method to some value, you will get a compiler error.

 

 

Primitive Type

Size

Range of Values

byte

8 bit

-27 to 27-1

short

16 bit

-215 to 215-1

int

32 bit

-231 to 231-1

long

64 bit

-263 to 2 63-1

char

16 bit

'\u0000' to '\uffff'

(0 to 216-1 )

 

Identifiers may contain only letters, numbers, dollar signs, i.e. "$", or underscores, i.e. "_". The first character cannot be a number. Obviously an identifier cannot have the same spelling as a keyword or the boolean and null literals (true, false and null) as described earlier.

 

Octal literals begin with zero e.g. 013042 (and obviously only digits 0-7 are allowed). Hexadecimal literals begin with zero and an 'x' e.g. 0x23e4A (digits allowed are 0-9 and a to f, the 'x' and the letters can be upper or lower case).

 

String duh = "This should be obvious, but I'll include an example anyway." 

 

Use \u followed by four hexadecimal digits representing the 16 bit unicode character e.g.

char x='\u1234'

Java also supports certain escape codes for special characters such as '\n' for newline. See a textbook for more.

 

 Section Title: Operators and Assignments

These operators are followed by a number which defines by how many bits the number is shifted.

>> performs a signed right-shift, that is, if the most significant (i.e. first on the left) bit is 1, then when it right-shifts the bits, it fills in a 1s on the left. If the most significant bit is 0, then when it right-shifts the bits, it fills in a 0s on the left. As the first bit represents the sign of a number (positive or negative), this preserves the sign of the number.

>>> performs an unsigned right-shift, it always fills in 0s on the left.

<< performs a left-shift (it always files in 0s on the right).

 

Adds. If any of the variables are Strings, it converts the non-Strings to Strings, and concatenates (joins) them.

 

With Objects, == determines whether the variables reference the same object in memory, rather than comparing their contents in a meaningful way. If you assign a=b, then a==b will evaluate to true, where a and b are objects.

 Note that if you construct two Strings with the same String literal, without using the new keyword, e.g.

String a = "Hello"

String b = "Hello"

, then Java creates only one String object, so a==b evaluates as true.

 

Unless it is overridden, the equals() method behaviour in Object, and therefore inherited from it, performs the same reference comparison as the == operator. However, the Boolean and String classes override this with a more meaningful comparison. equals()returns true, in Booleans if the two objects contain the same Boolean value, and in String if the Strings contain the same sequence of characters.

Note that StringBuffer does not override the equals() method, so if you use this method, it will not compare the actual text characters that the StringBuffers contain.

 

Just a quick note on the second two operators: && (AND) and || (OR) are the short circuit operators, which do not evaluate the second operand if it is not necessary. AND is only true if both values are true, therefore if the first is false, the result is false, and there is no need to evaluate the second part. OR is true if either value is true, therefore if the first is true, the result is true, and there is no need to evaluate the second part.

 

Primitives: You cannot assign booleans to any other type. With the exception that you cannot assign a byte to a char, you can assign a variable of type X to type Y (i.e. Y=X) only if Y is 'wider' than X. 'Wider' means that the primitive type can contain a wider range of values. The primitives, in order of 'width' are char/short, int, long, float, double. Note that you cannot assign a char to a short or vice versa.

Objects: You can assign object X to object Y (i.e. Y=X) only if they are of the same class, or X is a subclass of Y (called "upcasting").

 

This objective is not very specific, but the following information may help. In an arithmetic statement, variable may be widened automatically, to evaluate the expression (note the variables themselves aren't change, i.e. byte b is still a byte afterwards, but for its calculations Java uses a widened value). This is called promotion. Bytes, shorts and chars are always converted to ints, in unary (e.g. x++)or binary operations (e.g. x*y). For binary operators, if one operand is wider, the other is widened to the same type.

 

When passed to a method, primitives may be promoted, and objects may be upcast, to the type/class that the method takes, if possible. For example, if a method takes an int as an argument, and you pass it a byte, the value passed to the method is the byte converted to an int. Note that the variable in the calling method is unaffected (passing by value). The rules for when this is allowed are as per the objective "Determine if an assignment is permitted between any two variables of possibly different types" above.

 

 Section Title: Declarations and Access Control

For example, either

int[] x;
or
int x[];

are legal positions for the brackets. To declare a multidimensional array, use mutliple sets of brackets, e.g. int i[][]; declares a two dimensional array.

 

Arrays are objects. Use the new keyword to construct them. For example having declared an array i:

int[] i;

you then construct the array and assign it to i as follows:

i = new int[10];

The size of the array is in the brackets (in this example 10). It is common to do both operations in one statement:

int i[] = new int[10];

 

An example:

int somearray[] = new int[15];

for(int j=0; j<somearray.length;j++){

somearray[j]=j;
}

 

An example:

char c[]= new char[] {'a','b','c','d','e'};

 

If you are usure of this, see a textbook.

 

public - can be accessed by any other class.

abstract - cannot be instantiated, is allowed to contain abstract methods.

final - cannot be subsclassed.

 

private - can only be accessed from inside the class. Private members are not inherited by subclasses. Inner classes can be declared private.

protected - can only be accessed by classes in the same package or subclasses of this class.

public - can be accessed by any other class.

static - belongs to the class rather than any particular instance of the class. For variables, effectively, there is just one copy of this variable for all instances of the class, and if an instance changes the value, the other instances see that new value. For methods, it means the method can be called without having created an instance, but you cannot use the this keyword, or refer to instance variables and methods directly (without creating an instance and referring to the variable/class in that instance). For inner classes, it means they can be instantiated without having an instance of the enclosing class, but as with static methods, the methods of the inner class cannot refer to instance variables or methods of the enclosing class directly.

final - cannot be changed. Variables are constants, methods cannot be overridden, classes cannot be subclassed.

native - a method which is not written in java and is outside the JVM in a library.

abstract - a method which is not implemented.

 

Default constructor takes no arguments e.g. classname() where classname is the name of you class. A default constructor is automatically created only if you do not create any constructors in your class. If you create a non-default constructor (i.e. one that takes an argument), then you may have to create a default one yourself, if you want there to be one. All constructors call the default constructor of its parents class (if there is one), and so on up the hierarchy to Object, unless you specify a different constructor in the parent using super(…) or this(…), which must be the first line in the constructor.

 

static - belongs to the class rather than any particular instance of the class. For variables, effectively, there is just one copy of this variable for all instances of the class, and if an instance changes the value, the other instances see that new value.

final - cannot be changed. Since Java1.1 you can declare the variable without assigning a value. Once you assign a value, you cannot change it.

 

A very technical, but good, reference for these kinds of issues is the Java Language Specification which is available at the following URL:

http://java.sun.com/docs/books/jls/html/index.html

 

 

Section Title: Flow Control and Exception Handling

Consult a text book for the basics of these, if unsure. If you do know the basics, here are two things to watch out for:

Number 1

Be wary where if is used without braces, and with an else statement (this is referred to as the dangling else problem, and occurs in C and C++ aswell). The following example is from Boone (p.154):

 

if (result >=0)

 

 

 

if (result > 0)

 

 

 

System.out.println("positive");

else

 

 

 

System.out.println("negative");

 

The indentations are misleading. It might appear that the above code will print "positive" if result is greater than 0, "negative" if is less than zero, and print nothing if result is equal to 0. In fact, it will print "positive" if result is greater than 0, it will print nothing if is less than zero, and print "negative" if result is equal to 0. This is because the else statement belongs to the second if statement, and only executes if result >=0 but not if result>0, in other words if result equals 0. Using braces (curly brackets) would fix this. The following indentation shows the real relationship, of course the compiler doesn't care about indentation:

if (result >=0)

 

 

 

if (result > 0)

 

 

 

System.out.println("positive");

 

else

 

 

 

System.out.println("negative");

Number 2

After switch/case construct has executed the correct case, it will continue to execute all those after it (including default: if it is there, after the selected case) on to the end of the switch/case block, unless you put in a break, return or throw statement. This is referred to as "falling through". For example:

switch (a) {

XXXcase 1:

XXXXXXSystem.out.println("one");

XXXcase 2:

XXXXXXSystem.out.println("two");

XXXcase 3:

XXXXXXSystem.out.println("three");

XXXdefault:

XXXXXXSystem.out.println("some other number");

}

If a is 1, this will print "one", "two", "three" and then "some other number" in succession. If a is 3, this will print "three" and then "some other number".

In some cases, this kind of behaviour is desirable, but here it isn't. This block of code fixes it:

switch (a) {

XXXcase 1:

XXXXXXSystem.out.println("one");

XXXXXXbreak;

XXXcase 2:

XXXXXXSystem.out.println("two");

XXXXXXbreak;

XXXcase 3:

XXXXXXSystem.out.println("three");

XXXXXXbreak;

XXXdefault:

XXXXXXSystem.out.println("some other number");

}

Note that in switch blocks, it is legal to put default: anywhere in the block, it doesn't have to be the last one.

 

 

The argument for an if() statement must be a boolean or an expression which evaluates to a boolean. A common mistake is to use a single = rather than == to compare values. The following gives a compiler error:

public static void main(String[] args) {

XXXint a=1;

XXXif(a=2) System.out.println("a is two");

}

a=2 assigns the value 2 to a.

The argument for a switch statement must be a byte, a char, a short or an int, or an expression which evaluates to one of those.

 

An example:

for(int i=0;i<3;j++){

XXXSystem.out.println("i is "+i);

XXXfor(int j=0;j<3;j++) {

XXXXXXSystem.out.println("j is"+L);

XXX}

}

Will print:

i is 0

j is 0

j is 1

j is 2

i is 1

j is 0

etc.

 

Note: Don't get thrown if the for loop uses pre-increment instead of post-increment i.e. for(int i=0;i<3;++j) instead of for(int i=0;i<3;j++). This does not make any difference to the behavior of a for loop.

 

break will cause the current loop to be abandoned. continue causes execution to skip the rest of the code in the current iteration of the loop, and start at the top of the loop with the next iteration.

}{submenus}
DISCLAIMER