Bannerco-op Banner Exchange Bannerco-op Banner Exchange
The BannerCo-Op - 1-1 Exchange + Cash

 

 

Sun Certified Programmer Examination Revision Book

©1999 Dylan Walsh

Number of hits:

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.

Useful links:

Suns own certification site, has FAQs, objectives and sample questions: http://suned.sun.com/usa/cert_test.html

The Java Certifcation Study Group, contains a good discussion forum: http://www.woj.com/tech/javacert/

Marcus Greens Site has exams, FAQs, tutorials:http://www.software.u-net.com/

Joes page, has an SCJP tutorial: http://www.geocities.com/SiliconValley/Network/3693/

The JavaRanch, has a nice rules exam, and lots of cows: http://www.javaranch.com/

 

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.

These (unlabeled) versions will only affect the execution of loop that they are in. If you have nested loops, and want to break out of, or skip to the next iteration of, an outer loop, from an inner loop, you used the labeled versions. These jump to the wherever the label is, allowing you to break out of, or skip several nested loops, by placing the label in front of the outer loop.

 

Place code which is likely to throw an exception inside a try { } block. Create one or more catch() { } blocks with code to deal with the types of exceptions that might be thrown in the try block. The type of exception goes inside the round brackets of the catch() statement, as you would when declaring a method.

Exceptions are objects, which belong to a class hierarchy. If the exception thrown is an instance of the class, or a subclass of the class, specified in catch(), that catch block is the one executed. Your catch() block therefore can handle a range of exceptions if they are subclasses of the class specified. If you want to handle one specific subclass one way, and all the other subclasses differently, put a catch statement for the specific subclass first, and a more gereral catch block for the superclass second. Then when an exception is thrown, if the exception is a member of the subclass, that catch block only executes, but if it is a different subclass of the parent class, the general catch block executes. If you put the superclass first, you will get a compiler error.

finally blocks execute no matter what, in other words, whether the code executes without an exception, or an exception is thrown and successfully caught, or an exception is thrown and not caught. This is useful because, except for code in a finally block, if an exception is thrown and not caught, the execution of the rest method is abandoned.

One (probably not important for the exam) thing which could stop a finally clause from executing, is a call to System.exit(0).

If an exception is thrown, then the rest of the code in the try block is not executed. If the exception is not caught correctly, then after the finally block executes, the rest of the code in the method is not executed.

For example:

void mymethod(int i) throws Exception { }

Methods can throw more than one class of exception, you list all the exceptions after the throws keyword, separated by commas.

 

Essentially, a method can throw the same or fewer, but not more, exceptions than the superclass method it is overriding. This has to do with object orientation, if you could broaden the number of exceptions in the subclass method, anything which can deal with the superclass might not be able to deal with the subclass, because the are new exceptions there that it isn't written to handle. You want all members of subclasses to be able to be handled as if there were members of the parent class ("upcasting" or polymorphism).

The hierarchy of exceptions is important here, you can replace a exception class in the overridden method with one or more of its subclasses, but you can't replace it with its superclass. To do this would be to broaden the range of exceptions the method could throw.

 

For example:

throw new SomeKindOfException();

  

Section Title: Overloading, Overriding, Runtime Type, and Object Orientation

Briefly, 'is a' should be implemented using inheritance, 'has a' should be implemented using containment. This objective is conceptual, consult a textbook for more.

 

SomeObject instanceof SomeClass

evaluates as true if SomeObject is an instance of SomeClass, or is an instance of a subclass of Someclass. Otherwise it evaluates as false.

 

SomeObject instanceof SomeInterface

evaluates as true if SomeObject is an instance of a class which implements SomeInterface. Otherwise it evaluates as false.

 

What identifies a method in the Java is not merely the name of the method, rather it is the name of the method and the arguments it takes. You must watch for any differences in the arguments list. If the arguments are different, you are dealing with a separate method. This is overloading. The fact that they have the same name means is only of significance to humans.

The return type is not part of a methods signature. You are only overriding if there is a method in the parent class with same name which takes exactly the same arguments. Then the method replaces the one from the superclass.

You cannot define two methods within a class with the same name and the same arguments.

 

Overloaded methods are really completely different and separate methods, so they can return completely different types.

 

The overriding method must return the same type as the method in the superclass. This is because in the subclass, the overriding method replaces the method in superclass, and polymorphism or "upcasting" would not work they returned different types (i.e. you should get the same return type as you would with the parent class, or else you can’t treat the subclass as the superclass).

 

If the object is an instance of the derived class, then the overridden version defined in the derived class is the one that is envoked. Look at this example:

class Animal {

XXXvoid sayHello() {

XXXXXXSystem.out.println("Hello, I'm an animal.");

XXX}

}

class Dog extends Animal {

XXXvoid sayHello() {

XXXXXXSystem.out.println("Hello, I'm a dog.");

XXX}

}

We are overriding the sayHello method with behaviour more specific to a dog.

The straightforward method calls are as follows:

Animal i = new Animal;

i.sayHello();

prints "Hello, I'm an animal."

 

Dog j = new Dog;

j.sayHello();

prints "Hello, I'm a dog." because we have overridden sayHello, and this instance is a dog.

 

However:

Animal k = new Dog;

k.sayHello();

prints "Hello, I'm a dog." Here we are creating an instance of Dog, but we are assigning it to an Animal reference [referring to an object as the base class is called "upcasting" and is useful as you can write methods that deal with instances of any of the subclasses]. Because the underlying object is really a Dog, the method in the derived class is the one that executes.

Note: This behavior only applies to instance (i.e. not static) methods. Variables and static methods do not "override", instead they "hide" the variable/method in the parent class. This means that the class of the reference, rather than that of the underlying object, that matters.

 

super.someMethod() will call the version of someMethod() in the immediate super class. You cannot use something like super.super.someMethod() to call the method two steps up the object heirarchy.

 

These calls must be at the very start of the code in the constructor, therefore you can only make one of these types of calls. A call to the default constructor in the parent class is made by default, so super(arguments) is useful when you want to call a version of the constructor which takes an argument instead (there may not be a default constructor in parent class, in which case this call is necessary, or the code won't compile).

this() with or without arguments in brackets is used to call any of the other (overloaded) constructors defined in the class, before performing actions specific to current constructor being defined.

 

Place the class definition (for the inner class) inside another class definition (the outer class).

 

An anonymous inner class is defined where is it instantiated (in a method). An anonymous inner class must either implement an interface or extend a class, but the implements or extends keywords are not used. For example the following line causes the method to return an object which is an instance of an anonymous inner class:

return new SomeClass() { //body of the anonymous class goes here };

or the following calls someMethod(), passing an instance of the anonymous inner class:

someMethod(new SomeClass() { //body of the anonymous class goes here });

SomeClass() is not the name of the anonymous class (the class is anonymous!) rather is it the name of the class that you are extending or the interface you are implementing. You might like to think of an anonymous inner class as a really long new statement, which happens to contain a method definition, and so it should have a ";" at the end like the first example, unless it is inside method call brackets, like the second example.

These classes cannot define a constructor, as they do not have a name that you can use to declare the constructor method. If name() is a class, the default constructor of that class is called, if you want to use a non-default constructor instead, you supply arguments e.g.:

return new name(12) { //body of the anonymous class goes here };

will call the name class constructor which take a number.

 

Inner x = new Inner(); constructs an instance of Inner where Inner is an inner class defined in the current class.

 

You must create an instance of the outer class first. Given a class, Outer, containing an inner class Inner:

Outer.Inner y = new Outer().new Inner();

The above creates an instance of Inner called y, but it had to construct an instance of Outer first (which here does not have a name). The following example creates the Outer instance on a separate line, the syntax in the second line is the one you use when you already have an instance of the outer class.

Outer x = new Outer();

Outer.Inner y = x.new Inner();

 

If Inner is static, you can use:

Outer.Inner I= new Outer.Inner();

 

A non-static inner class has access to all member variables and methods of the containing class.

A static inner class is restricted in the same way as a static method: it cannot refer to instance variables and methods of the containing class directly (without creating an instance and referring to the variable/class in that instance).

If the inner class is defined inside a method, it has access to those method (a.k.a automatic or local) variables which are declared final.

 

Section Title: Garbage Collection

How and when garbage collection occurs is left up to the implementation of the JVM, all you can know is that an object becomes eligible for garbage collection when there are no longer any references to it.

finalize()

The finalize method of a class is called before it is garbage collected. The method takes no arguments and must return void, and throws Throwable.

 

An object is eligible for garbage collection when there are no longer any references to it. This can happen if a variable is assigned to a newly created object, but later is assigned to a different object, there is nothing pointing to the object. Or when a method exits, all the variables go out of scope, so all the objects are eligible for garbage collection, unless there is a reference to them somewhere outside the method.

 

Section Title: Threads

Define a class that implements Runnable, which means you must define a run() method in the class e.g.

class MyClass implements Runnable {

XXXpublic void run () {

XXXXXX// Insert the code you want to run in a thread here

XXX}

}

run() must be public, with a void return type, and not take any arguments. Note that if run() is defined to take any arguments, then that is a different method and the Runnable interface hasn't been implemented!

Create an instance of the class, and construct a thread, passing the instance of the class as an argument to the constructor i.e.

MyClass mc=new Myclass;

Thread t=new Thread(mc);

 

To start the thread, use the start() method:

t.start();

Alternatively, you can create a subclass of the Thread class, and override the run() in the subclass:

class MyThread extends Thread {

XXXpublic void run () {

XXXXXX// Insert the code you want to run in a thread here

}

}

Then create an instance of the subclass, and start it running:

MyThread mt=new MyThread(mc);

mt.start();

 

There is only one method in the interface, run(), which must be implemented

in the class.

 

The run() method.

 

Call the start() method on an instance of the Thread class.

 

A thread can be in one of the following states:

a) Running

b) Ready - Waiting for a chance to run on the CPU. All threads enter this state before running. Threads with higher priorities may be preventing the thread from getting a chance to run (this depends on how priorities have been implemented in the particular Java Virtual machine)

c) Various waiting states (Waiting, Sleeping, Suspended & Blocked)

d) Dead - the run() method has completed (the thread can never be restarted)

 

Using the synchronized keyword in the method declaration, requires a thread obtain the lock for this object before it can execute the method.

synchronized void someMethod() { }

You can also make a block of code synchronized by using the synchronized keyword followed by the object or class, for which a thread must obtain the lock before it can execute this block of code:

// .. some code before the synchronized block

synchronized (someObject) {

// code

}

// more code…

 

The wait() method must be used in synchronized code. The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up (i.e. move into Ready state) either through a call to the notify method or the notifyAll method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.

 

notify() moves one thread, that is waiting the this objects monitor, into the Ready state. This could be any of the waiting threads; the choice of which thread is chosen is an implementation issue of the virtual machine.

notifyAll() moves all threads, waiting on this objects monitor, into the Ready state.

 

The use of these methods, and synchronized methods or code blocks, ensure only one thread at a time can access parts of a class, and control how and when threads get this access. If you are unsure of how they interact, consult a textbook.

 

Section Title: The java.lang package

abs()-Returns the absolute value of the argument. Overloaded for ints, longs, floats and doubles.

ceil(double) -Returns the smallest (closest to negative infinity) double value that is not less than the argument and is equal to a mathematical integer.

floor(double)-Returns the largest (closest to positive infinity) double value that is not greater than the argument and is equal to a mathematical integer.

max(value1,value2)-Returns the greater of two values.

min(value1,value2)-Returns the smaller of two values.

random()-Returns a random number between 0.0 and 1.0.

round(double)-Returns the closest long to the argument.

sin(double) -Returns the trigonometric sine of an angle. The angle is in radians.

cos(double) -Returns the trigonometric cosine of an angle. The angle is in radians.

tan(double) -Returns the trigonometric tangent of an angle. The angle is in radians.

sqrt(double) -Returns the square root of a double value.

 

length()-Returns the length of this string.

toUpperCase()-Converts this string to uppercase.

toLowerCase()-Converts this String to lowercase.

[Note that toLowerCase() and toUpperCase() will return a reference to original string object if the it is already in lower case or upper case respectively. This is important for questions on the == operator and strings.]

equals(Object)-Compares this string to the specified object. Returns true if the strings contain the same sequence of characters.

equalsIgnoreCase(String)-Compares this String to another object. Returns true if the strings contain the same sequence of characters, ignoring case.

 

charAt(int)-Returns the character at the specified index. An index ranges from 0 to length() - 1.

 

concat(String)-Concatenates the specified string to the end of this string.

 

indexOf(int)-Returns the index within this string of the first occurrence of the specified character.

indexOf(int ch, int fromIndex) - Returns the index within this string of the first occurrence of the specified character, starting the search at the specified index.
Parameters:
ch - a character.
fromIndex - the index to start the search from.

 

indexOf(String)-Returns the index within this string of the first occurrence of the specified substring.

indexOf(String, int)-Returns the index within this string of the first occurrence of the specified substring, starting at the specified index.

 

lastIndexOf(int)-Returns the index within this string of the last occurrence of the specified character.

lastIndexOf(int ch, int fromIndex)-Returns the index within this string of the last occurrence of the specified character, searching backward starting at the specified index.

Parameters:
ch - a character.

fromIndex - the index to start the search from.

lastIndexOf(String)-Returns the index within this string of the rightmost occurrence of the specified substring.

lastIndexOf(String, int)-Returns the index within this string of the last occurrence of the specified substring.

 

substring(int)-Returns a new string that is a substring of this string. The substring begins at the specified index and extends to the end of this string.

substring(int beginIndex, int endIndex)-Returns a new string that is a substring of this string. The substring begins at the specified beginIndex and extends to the character at index endIndex - 1.

Remember: substring gives you the substring from the first index, to the second index minus one.

 

trim()-Removes white space from both ends of this string.

 

toString()-Returns a string representation of the object. This method is inherited by all classes from Object. By default, the toString method for class Object returns a string consisting of the name of the class of which the object is an instance, the at-sign character `@', and the unsigned hexadecimal representation of the hash code of the object. You can override it in your own classes to produce some useful string eg. debugging info.

For the Strings, toString() returns the String object itself.

 

The + operator to concatenate strings.

 

String objects cannot be changed. They are assigned a sequence of characters when they are constructed. Look at the following code:

String message = "Good";

message= message + " morning";

When the first line executes, a string object containing "Good" is assigned to message.

[a new String object is constructed, unless the literal "Good" was used somewhere else, in which case the exisiting String is re-used. A consequence of this is the behaviour of the == operator which was describe under Language Fundamentals above, here is that information again:

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

On the second line, " morning" is appended. But the String object containing "Good" cannot be changed, so a new String, containing "Good morning" is created and assigned to message.

 

Section Title: The java.awt package - Components and Facilities

The names of these methods are self-explanatory. Note that after you create a frame, there are not visible by default, you must use setVisible(true)before it can be seen.

getSize() returns a dimension object, which contains two integer member variables, height and width.

Obviously setForeground() and setBackground() take a color argument.

 

As there is no mechanism to set the number of columns a list has, I would assume that the above objective contains a typo, and should refer to rows, not columns.

The constructors for a List are as follows:

List(int rows)
Creates a new scrolling list initialized with the specified number of visible lines. By default, multiple selections are not allowed.
List(int rows, boolean multipleMode)
Creates a new scrolling list initialized to display the specified number of rows. If the value of multipleMode is true, then the user can select multiple items from the list. If it is false, only one item at a time can be selected.

 

The constructors for a TextArea are in the next objective.

 

A TextArea object is a multi-line region that displays text. The following constructors allow you to specify the preferred number of rows and columns:

TextArea(int rows, int columns)
Constructs a new empty TextArea with the specified number of rows and columns.
TextArea(String text, int rows, int columns)
Constructs a new text area with the specified text, and with the specified number of rows and columns. This text area is created with both vertical and horizontal scroll bars.
Note: It is the number of rows, then columns. This is counter-intuitive, as usually in programming you specify a horizontal dimension, then a vertical one, so this exception can catch you out.

 

A TextField has a single line of text:

TextField(int columns)
Constructs a new empty TextField with the specified number of columns.
TextField(String text, int columns)
Constructs a new text field initialized with the specified text to be displayed, and wide enough to hold the specified number of characters.

 

The width of a "column" is equal to the width of a character, in the particular font being used. In the case of fixed pitch fonts, where all the characters are the same size, this is straightforward. For proportional fonts, the width of a column is equal to the average of the width of all the characters in the font. This means, for example, if you had text component with a proportional font and a width of 10 columns, if you use a narrow letter such as 'i', more than 10 'i's could be displayed.

 

 

[Sun Certified Programmer for the Java™ 2 Platform

Based on available information, these painting methods are not examined in the Java 2 Platform (Java 1.2) exam, so you do not need to know this objective]

drawString(String str, int x, int y)
Draws the text given by the specified string, using this graphics context's current font and color. The baseline of the first character is at position (x, y) in this graphics context's coordinate system.
drawLine(int x1, int y1, int x2, int y2)
Draws a line, using the current color, between the points (x1, y1) and (x2, y2) in this graphics context's coordinate system.
drawRect(int x, int y, int width, int height)
Draws the outline of the specified rectangle. The left and right edges of the rectangle are at x and x + width. The top and bottom edges are at y and y + height. The rectangle is drawn using the graphics context's current color.

drawImage(Image img, int x, int y, ImageObserver observer)

There are other versions of this method, but the above is the most common. It draws the given image with its top left corner at the given co-ordinates. The ImageObserver is an object which implements the ImageObserver interface. Note that the Component class implements this interface so you can use the component into which you are drawing the Image as the ImageObserver.

drawPolygon(int xPoints[], int yPoints[], int nPoints)

Draws a closed polygon defined by arrays of x and y coordinates. xPoints[]is an array of the x co-ordinates , yPoints[] is an array of the y co-ordinates, and nPoints is the number of points. In other words, the corresponding elements of the arrays combine to give the (x,y) co-ordinate of each point in the polygon.

drawArc(int x, int y, int width, int height, int startAngle, int arcAngle)
Draws the outline of a circular or elliptical arc covering the specified rectangle.
The resulting arc begins at startAngle and extends for arcAngle degrees, using the current color. Angles are interpreted such that 0 degrees is at the 3 o'clock position. A positive value indicates a counter-clockwise rotation while a negative value indicates a clockwise rotation.
The center of the arc is the center of the rectangle whose origin is (x, y) and whose size is specified by the width and height arguments.
The resulting arc covers an area width + 1 pixels wide by height + 1 pixels tall.
Parameters:
x - the x coordinate of the upper-left corner of the arc to be drawn.
y - the y coordinate of the upper-left corner of the arc to be drawn.
width - the width of the arc to be drawn.
height - the height of the arc to be drawn.
startAngle - the beginning angle.
arcAngle - the angular extent of the arc, relative to the start angle.
 

fillRect(), fillPolygon() and fillArc() are filled versions of drawRect(), drawPolygon()and drawArc() respectively.

Note that fillArc()draws a 'pie-piece' rather than a 'chord'. In other words, if for example, the arc is part of a circle (i.e. width and height are equal) the filled area goes from the centre of that circle, out between two lines, to the ends of the arc.

 

Calling the getGraphics() method on the Image object returns a Graphics context from the Image.

 

An Image is an off-screen bitmap. A blank image can be created, or an image can be taken from a GIF or JPEG file. While images can be scaled or filtered, they do not have drawing methods like those of the Graphics class. You must obtain a Graphics context from the Image to do any drawing on the Image. To display an Image you must use a Graphics object (use the drawImage()method).

 

Section Title: The java.awt package - Layout

Note that the second form, as far as the certification exam scope is concerned, is used with BorderLayout. The String is one of "North", "South", "East", "West" or "Center", which specifies which area of the component is to added to. However, the JDK documentation strongly advises the use of the Java 1.1 form. Which is asked in the exam I can’t say, but it is probably wise to be familiar with both. The 1.1 form, which is the only one used in Roberts & Heller (Boone only uses the above form) is as follows:

public void add(Component comp, Object constraints)
Adds the specified component to the end of this container. Also notifies the layout manager to add the component to this container's layout using the specified constraints object.

For BorderLayout, the second parameter is a String as above, or you can use one of the constants defined in the BorderLayout class, BorderLayout.NORTH, BorderLayout.SOUTH etc.

 

You set the layout manager that a container should use. That layout manger then implements the layout.

 

public void setLayout(LayoutManager mgr)
Sets the layout manager for this container.

For example, in the code of an applet:

setLayout(new GridLayout());

creates an instance of the GridLayout class, and makes it the layout manger for the applet.

 

Worth noting are the default layout managers: FlowLayout for applets and panels, BorderLayout for frames. Containers always use these defaults after being created, unless you specify otherwise, they do not get the default layout manager from the containers they themselves are placed in, unlike other properties such as colour, font etc.

 

BorderLayout divides the container into 5 regions, and one component at a time can be placed in each (that component can be another container, which itself can contain multiple components). If you add a component to a region which already contains another component, only the latest component will be displayed. Components in the North and South are placed at the top and bottom respectively, and are allowed to be their preferred heights but are as wide as the container. East and West are on the right and left sides respectively, and are allowed to be their preferred widths. Their heights stretch from the North and South regions (if there is nothing in North or South, they go from the bottom to the top of the container). Center fills the remaining space, left after the other regions, in the middle. The component is stretched to fill this area.

How to add components to the regions of a container using BorderLayout is describe above, in the first object of this section. Note that if you don't specify a region, the component is added to Center. Therefore, for example, if you create a frame (default layout is BorderLayout), and add a button to it using the default add(Component)method, the button will fill the entire frame.

 

FlowLayout always allows components to be their preferred size [This is true even if the component is wider or taller than the container. A centered portion of the component is shown, with as much of the component being made visible as can be]. It places many components as it can on a line, with the first component starting on the left, until there is no more room horizontally, then it starts another line. By default the rows are centred in the container. You can specify how the rows are aligned using this constructor:

new FlowLayout(int alignment)
Constructs a new Flow Layout with the specified alignment and a default 5-unit horizontal and vertical gap. The value of the alignment argument must be one of FlowLayout.LEFT, FlowLayout.RIGHT, or FlowLayout.CENTER

GridLayout divides its area into equally sized rectangles. When components are added to it, they are made the same size as their cell. Two constructors to be aware of are:

public GridLayout(int rows, int cols)
Creates a grid layout with the specified number of rows and columns. All components in the layout are given equal size. One, but not both, of rows and cols can be zero, which means that any number of objects can be placed in a row or in a column.
Remember: it is rows, then columns. If the number of components added is more than the number of cells (i.e. rows ´ columns) then more columns are added as needed, but the number of rows remains the same.
public GridLayout()

Creates a grid layout with a default of one column per component, in a single row.

Sun Certified Programmer for the Java™ 2 Platform 

While it is not mentioned in the objectives, GridBagLayout is examined in SCJP 2.

GridBagLayout

There is a tutorial which includes using GridBagLayout, with AWT, at ftp://ftp.javasoft.com/docs/tut-OLDui.zip

GridBagLayout is like GridLayout, except that components can be different sizes (i.e. take up more than one cell in the grid) and you have a lot more options, hence it is more complex. To use GridBagLayout, you create an instance, and set it as the layout manager for your container, as with the other layout managers. You don't specify the number of cells when constructing an instance of GridBagLayout, the constructor is just the default GridBagLayout().

The twist is that you specify how the component is to be displayed using an instance of GridBagConstraints. The fields in this class contain all the options. For each component, you use the GridBagLayout setConstraints() method:

setConstraints(Component comp,GridBagConstraints constraints)

The values for each component are read from the GridBagConstraints object, so you can change the values after each component, and reuse the same GridBagConstraints instance for the next one. Then you add the component to the container e.g.

MyGridBag.setConstraints(componentX, MyConstraints);

add(componentX);

 

GridBagConstraints Fields:

[The constants (uppercase) listed below for use with certain fields are static field in the GridBagConstraints class, so you refer to them as GridBagConstraints.EAST for example.]

anchor This field is used when the component is smaller than its display area. It determines where, within the display area, to place the component.

(one of CENTER (default), EAST, WEST, NORTH, NORTHEAST, NORTHWEST, SOUTH, SOUTHEAST or SOUTHWEST)

fill This field is used when the component's display area is larger than the component's requested size. It determines whether to resize the component, and if so, how.

(one of NONE (Default), HORIZONTAL, VERTICAL, or BOTH)

gridheight Specifies the number of cells in a column for the component's display area.

(Use REMAINDER to specify that the component be the last one in its column. Use RELATIVE to specify that the component be the next-to-last one in its column.)

gridwidth Specifies the number of cells in a row for the component's display area.

(Use REMAINDER to specify that the component be the last one in its row. Use RELATIVE to specify that the component be the next-to-last one in its row. )

[Here REMAINDER acts somewhat like a carriage return. You add elements to the row, and when you use REMAINDER that marks the end of the line, and then the next components are added to the next row. Look at the examples in the tutorial or in the JavaDocs. Alternatively, you can use gridx and gridy to specify grid position when adding a component.]

gridx, gridy Specifies the position of the component. The constant REMAINDER (which is the default) specifies that this component be placed next to the previously added component. The top left cell has gridx=0, gridy=0.

insets Specifies the external padding of the component, the minimum amount of space between the component and the edges of its display area. This field belongs to the Insets class which uses the following constructor:

Insets(int top, int left, int bottom, int right)
Creates and initializes a new Insets object with the specified top, left, bottom, and right insets.

ipadx Specifies the internal padding of the component, how much space to add to the minimum width of the component.

ipady Specifies the internal padding, that is, how much space to add to the minimum height of the component.

weightx, weighty Specifies how to distribute extra vertical/horizontal space respectively. This is a double, typically between 0 and 1, the default value is 0. If all the weights are zero, and there is extra space, all the components are bunched together in the middle.

 

 

Section Title: The java.awt package - Event Handling

Listener Interfaces

For information and comparison purposes, here is the list of Listener interfaces, and their methods. You do not need to memorize this table. Note the relationship between the Listener interface name, the Event type (which is the argument to the methods) and the 'add' method which belongs to the component classes.

Interface Name

Event

Methods in interface

Add method

ActionListener

ActionEvent

actionPerformed(ActionEvent)

addActionListener()

AdjustmentListener

AdjustmentEvent

adjustmentValueChanged(AdjustmentEvent)

addAdjustmentListener()

ComponentListener

ComponentEvent

componentHidden(ComponentEvent)
componentMoved(ComponentEvent)
componentResized(ComponentEvent)
componentShown(ComponentEvent)

addComponentListener()

ContainerListener

ContainerEvent

componentAdded(ContainerEvent)
componetRemoved(ContainerEvent)

addContainerListener()

FocusListener

FocusEvent

focusGained(FocusEvent)
focusLost(FocusEvent)

addFocusListener()

InputMethodListener

InputMethodEvent

caretPositionChanged(InputMethodEvent)
inputMethodTextChanged(InputMethodEvent)

addInputMethodListener()

ItemListener

ItemEvent

itemStateChanged(ItemEvent)

addItemListener()

KeyListener

KeyEvent

keyPressed(KeyEvent)

addKeyListener()

MouseListener

MouseEvent

mouseClicked(MouseEvent)
mouseEntered(MouseEvent)
mouseExited(MouseEvent)
mousePressed(MouseEvent)
mouseReleased(MouseEvent)

addMouseListener()

MouseMotionListener

MouseEvent

mouseDragged(MouseEvent)
mouseMoved(MouseEvent)

addMouseMotionListener()

TextListener

TextEvent

textValueChanged(TextEvent)

addTextListener()

WindowListener

WindowEvent

windowActivated(WindowEvent)
windowClosed(WindowEvent)
windowClosing(WindowEvent)
windowDeactivated(WindowEvent)
windowDeiconified(WindowEvent)
windowIconified(WindowEvent)
windowOpened(WindowEvent)

addWindowListener()

 

[To save typing, there is the option of using Adapter classes, e.g MouseAdapter for the MouseListener interface. These are classes which have empty methods for all the methods in the Listener. You extend them, and then overwrite the methods you are interested in, saving the effort of typing other methods]

 

The only Event class that has methods for all of the above is MouseEvent.

Affected Component:

There are two methods that fit this description. From looking at the source code, it appears they perform the exact same function.

All ComponentEvent subclasses implement this method:

public Component getComponent()

Returns: the Component object that originated the event
 

All events implement this method:

public Object getSource()
Returns: the object on which the Event initially occurred.
Mouse Position:
MouseEvent implements these methods:

public 
Point getPoint()
Returns the x,y position of the event relative to the source component.
Returns: a Point object containing the x and y coordinates relative to the source component
public int getX()
Returns the horizontal x position of the event relative to the source component.
Returns: x an integer indicating horizontal position relative to the component

public int getY()
Returns the vertical y position of the event relative to the source component.
Returns: y an integer indicating vertical position relative to the component

 

Nature:

All AWTEvent subclasses implement this method:

public int getID()
Returns the event type. This can be compared with the event mask constants defined in the class for the different types of event e.g. MOUSE_EVENT_MASK.

 

Time:

InputEvent subclasses (KeyEvent and MouseEvent) implement this method:

public long getWhen()

Returns the timestamp of when this event occurred.

 

For examples, see a text book, or the sites at the start of this document. Briefly, you create a class which implements one of the listener interfaces listed above. Important listener interfaces for the components mention in this objective are, for example: MouseListener, FocusListener, KeyListener or TextListener

Create suitable methods for the events you are interested, for the rest of the methods in the interface, just create an empty method body. For example, if you have a button, and you just need it to respond to being clicked, in your listener class you would put code in the mouseClicked() method, and implement the rest of the methods with empty bodies.

Then create an instance of the listener class and add it to the component in question using the components appropriate add method, which is the last column in the table above.

 

The argument types are listed in the "Listener Interfaces" table above, under the "Event" heading. The return type for all methods of all listener interface methods is void.

 

Section Title: The java.awt.package - Painting

  1. repaint() [Schedules a call to the update() method, after an interval. This is the recommended method for triggering painting as the scheduling prevents the system being swamped with paint() calls, and falling behind]
  2. update(Graphics g) [Clears the component to the its background colour and calls paint()]
  3. paint(Graphics g) [Paints the component. This method is also called by the system when the component needs to be repaired e.g. after being covered by another window, or the program window is restored after being minimized or when a web browser returns to the page with the applet]

 

Normally, the user thread should invoke repaint().

The paint() method has the following signature:

public void paint(Graphics g) { }

 

 

Section Title: The java.io package

[Sun Certified Programmer for the Java™ 2 Platform 

In spite of its omission in the objectives, Input/Output does come up in the examination, so needs to be learned by anyone taking the Java 2 exam, as well as anyone taking the 1.1 exam.]

 

For this section, you may find the following tables useful. They list the various kinds of Streams and Readers/Writers, along with what they "connect to", typically their constructor arguments.

Low Level Streams

Input Streams

Arguments

Output Streams

Arguments

FileInputStream

File

FileOutputStream

File

ByteArrayInputStream

byte[]

ByteArrayOutputStream

Creates an array

 

High Level Streams

Input Streams

Arguments

Output Streams

Arguments

FilterInputStream

InputStream

FilterOutputStream

OutputStream

DataInputStream

Implements DataInput

InputStream

DataOutputStream

Implements DataOutput

OutputStream

BufferedInputStream

InputStream

BufferedOutputStream

OutputStream

 

Low-level Readers/Writers

Readers

Arguments

Writers

Arguments

FileReader

File

FileWriter

File

CharArrayReader

char[]

CharArrayWriter

Creates an array of chars

StringReader

String

StringWriter

Creates a String

 

High-level Readers/Writers

Readers

Arguments

Writers

Arguments

BufferedReader

Reader

BufferedWriter

Writer

InputStreamReader

InputStream

OutputStreamWriter

OutputStream

 

Methods that support navigation:
boolean exists()-Tests if this File exists.
String getAbsolutePath()-Returns the absolute pathname of the file represented by this object.
String getCanonicalPath()-Returns the canonical form of this File object's pathname.
String getName()-Returns the name of the file represented by this object.
String getParent()-Returns the parent part of the pathname of this File object, or null if the name has no parent part.
String getPath()-Returns the pathname of the file represented by this object.
boolean isDirectory() -Tests if the file represented by this File object is a directory.
boolean isFile()-Tests if the file represented by this File object is a "normal" file.
String[] list() Returns a list (an array of Strings) of the files in the directory specified by this File object. 
Note: The File class does not provide a method to change the current working directory.
Other methods worth being aware of:
mkdir()-Creates a directory whose pathname is specified by this File object.
delete()-Deletes the file specified by this object.
length() Returns the length of the file represented by this File object. 
renameTo(File) Renames the file specified by this File object to have the pathname given by the File argument.
canRead()& canWrite() - Returns true if the file is readable/writeable.
 
The following constructor for InputStreamReader allows you to specify the encoding scheme:

InputStreamReader(InputStream in, String enc)
Create an InputStreamReader that uses the named character encoding.
Parameters:
in - An InputStream
enc - Name of encoding to be used

Encoding scheme string "8859_1" is ASCII.

The constructor for OutputStreamWriter is similar, but the first argument is an OutputStream, obviously.

Readers (such as InputStreamReader) have the following methods for reading characters:

read() -Read a single character.

read(char[] cbuf) -Read characters into an array.

read(char[] cbuf, int off, int len) -Read characters into a portion of an array.

Writers (such as OutputStreamWriter) have the following methods for writing characters:

write(char[] cbuf) -Write an array of characters.

write (char[] cbuf, int off, int len) -Write a portion of an array of characters.

write(int c) -Write a single character.

write(String str) -Write a string.

write(String str, int off, int len) -Write a portion of a string.

 

To avoid corruption, text should be read using the same encoding scheme that it was written with. Therefore, in general platform default encoding may be used if the data is written on the same computer as it is going to be read. However if the text is going to be sent from one computer to another across a network, or if a text file is created on a different computer (for example files that are installed as part of an application), then a specific encoding scheme should be used at both ends.

 

The correct constructor argument for FilterInputStream is an instance of a subclass of InputStream. Similarily, the correct constructor argument for FilterOutputStream is an instance of a subclass of OutputStream.

 

FileInputStream and FileOutputStream, are described in the accompanying I/O tables.

RandomAccessFile is not part of the i/o stream or reader/writer hierarchies. The constructors are:

RandomAccessFile(String file, String mode)

RandomAccessFile(File file, String mode)

Important: For the RandomAccessFile constructor, the mode argument must either be equal to "r" or "rw". Do not be fooled in the exam by credible sounding, but non-existent options like "r+w" or "w".

RandomAccessFile has a pointer which determines where to read/write in the file. getFilePointer() returns the current position in the file, in bytes, and seek(long position) sets the pointer to a specific location. There is also a length() method. This class implements the DataOutput and DataInput interfaces, which are described in the accompanying I/O tables.

 

RandomAccessFile will create an empty file if it is constructed as "rw". Constructing a FileOutputStream can create an empty file.

FileInputStream of course, never causes a file to be created or modified.

 

 

Section Title: The Applets & HTML

While this section is not listed in the objectives for the 1.1 or Java2 Platform (1.2) exams, it does come up in the exam.

Applets: Applet is a subclass of Panel, which is a subclass of Container. For information, here is a list of methods which are commonly overridden when creating your own applet:

init() Called when applet is first instantiated.

start() Called when the web page containing the applet is about to (re-)appear

stop() Called when the web browser is about to move to another web page

repaint() Inherited from Component

update() Inherited from Component

paint() Inherited from Component

 

Required HTML:

This is an example of the minimum HTML required to display an applet in a web page:

<APPLET CODE=MyProgram.class WIDTH=200 HEIGHT=400>

</APPLET>

HTML tags are not case-sensitive.

Passing parameters:

PARAM: This allows you to pass a value to an applet. The tag looks like this:

<PARAM NAME=message VALUE="Hello, World">

This tag is placed between "<APPLET …>" and "</APPLET>". The value is a string, and must be in quotes if it contains any spaces. To use these values in your applet, use the getParameter(String paramname ) method, which returns a string e.g.

String greeting;

greeting=getParameter("message");

The argument for this method is not case-sensitive so for example getParameter("mEsSaGE")would work just as well.

 

Sun Certified Programmer for the Java™ 2 Platform

Section Title: The java.util package

As far as I can gather, and this is implied by the objective itself and the sample examination question on the Sun website, this objective just requires a general knowledge of the classes/interfaces, in other words which to use for a given purpose. If you want a more in-depth treatment of the subject, try the Sun tutorial: http://java.sun.com/docs/books/tutorial/collections/index.html

Set

Implementations: Hashset

A Set is a collection which cannot contain any duplicate elements and has no explicit order to its elements (unlike, for example, an array, where every element exists at a particular index i.e. MyArray[15]).

SortedSet

Implementations: TreeSet

A SortedSet is a Set which maintains its elements in ascending order.

List

Implementations: LinkedList, ArrayList, Vector, Stack

A List is a collection which can contain duplicate elements, and the elements are ordered (like an array, you can add an element at a specific position, and the elements are accessed using their index).

[Stack has come up in the examination, so here is some info. on it.

Stack is a subset of Vector, which contains some extra methods. The idea of a stack is like its name, it acts like a piled up stack of items: When you add an element, it goes to the top of the stack, and when you extract an element, it is taken off the top. In other words, this is a last-in, first-out system. The methods are:

push(object) - Add an element onto the top of the stack.

pop() - Removes the object at the top of this stack and returns that object as the value of this function.

peek() - Looks at (i.e. returns) the object at the top of this stack without removing it from the stack.. ]

 

Map

Implementations: HashMap, Hashtable, WeakHashMap

Maps keys to values. In other words, for every key, there is a corresponding value, and you look up the values using the keys. Maps cannot have duplicate keys, and each key maps to at most one value.

Note: A Map does not implement the Collection interface.

SortedMap

Implementations: TreeMap

A SortedSet is a Set which maintains its mapping in ascending key order.

Object Ordering

Implementations of the SortedSet and SortedMap interfaces sort their elements. To determine what criterion is used to sort the elements you can use either the Comparable or Comparator interfaces. Using Comparable means that the classes that you put in your SortedSet or SortedMap implement the Comparable interface, which just means that they contain a method compareTo() which determines whether the object is "greater" or "less than" another object. To use the Comparator interface, you pass an object which implements Comparator to your SortSet or Sorted map, and it will use the Comparator for ordering.

 

BitSet

For completeness, here is some information on BitSet, which isn't part of the Collections Framework, but may be examinable. A BitSet contains elements which are bits, i.e. of the boolean primitive type. Like, for example, a Vector, and unlike an array, a BitSet does not have a fixed size, and grows as needed when you add elements to it.