• Post Reply Bookmark Topic Watch Topic
  • New Topic

Study Notes from a person who secured 100%.

asim wagan
Ranch Hand
Posts: 62
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Certification Notes
He sat for the "Sun Certified Programmer for the Java 2 Platform" exam in December 1999 and scored 100%. This document contains his study notes for the exam. The sections on AWT and threads are particularly brief.
* All class-level (member) variables are initialized before they can be used.
All local variables are not initialized until it is done explicitly.
* An array object (as distinct from reference) is always initialized (with
zeroes or nulls)
* Member initialization with the declaration has exception problems:
- cannot call methods that throw a checked exception.
- cannot do error recovery from runtime exceptions.
- If you need to deal with errors you can put the initialization code
along with try/catch statements in either a ctor (for instance fields)
or in a static initialization block for static fields. You can also
have instance (non-static) initialization blocks but ctors are more
* The String class
- Because string is an immutable class, its instance methods that
look like they would transform the object they are invoked upon,
do not alter the object and instead return new String objects.
- String has methods concat(String),trim(),replace(char,char)
- String has static valueOf methods for a whole bunch of primitives
and for Object too (equivalent to Object.toString()).
- in substring(int,int), the second arg is exclusive.
- indexOf methods returns -1 for 'not found'
* String Pool:
A JVM has a string pool where it keeps at most one object of any
String. String literals always refer to an object in the string
pool. String objects created with the new operator do not refer to
objects in the string pool but can be made to using String's intern()
method. Two String references to 'equal' strings in the string pool
will be '=='.
* StringBuffer doesn't override equals.
* Arrays are objects .. the following create a reference for an int array.
int[] ii;
int ii[];
* You can create an array object with new or an explicit initializer:
ii = new int[3];
ii = new int[] { 1,2,3 };
int[] ii = { 1,2,3 ); // only when you declare the reference.
* CAREFUL: You can't create an array object with:
int iA[3];
* If you dont provides values, the elements of obj arrays are
always initialized to null and those of primitive arrays are
always initialized to 0.
Primitive Types
* Primitive types:
- short and char are both 2 bytes.
int and float are both 4 bytes.
long and double are both 8 bytes.
- char is the only unsigned primitive type.
* Literals:
- You can have boolean, char, int, long, float, double and String literals.
You cannot have byte or short literals.
- char literals: 'd' '\u0c20' (the 0c20 must be a 4-digit hex number).
- int literals: 0x3c0 is hex, 010 is octal(for 8).
- You can initialize byte, short and char variables with int literals
(or const int expressions) provided the int is in the appropriate range.
* CAREFUL: can't assign a double literal to a float .. float fff = 26.55;
* The only bit operators allowed for booleans are &^| (cant do ~ or shift ops)
* Primitive wrapper classes
- are immutable.
- override equals.
- the static valueOf(String) methods in primitive wrapper classes return
wrapper objects rather than a primitives.
Conversions and Promotions
* boolean -> anything but boolean or string is not allowed.
* All other primitive conversions are allowed with an explicit cast.
* char/byte/short/int/long -> float/double is a widening conversion even
if some precision is lost (the overall magnitude is always preserved).
* Narrowing conversions require an explicit cast.
- integral narrowing conversions simply discard high-order bits.
- anything->char is a narrowing conversion (inc byte) because its
signed->unsigned and negative numbers get messed up
* Widening primitive and reference conversions are allowed for assignment
and in matching the arguments to a method (or ctor) call.
* For assignment (but not method invocation), representable constant
int expressions can be converted to byte, char or shorts (eg. char c = 65).
* Unary numeric promotions: byte/short/char -> int
* Binary numeric promotions:
- both arguments are made (in order of preference) double/float/long/int.
- include (in)equality operators.
* char/byte/short are promoted to int for nearly every operator ... be
careful not to assign the uncast int return value to a narrower type,
bytesum = byte1 + byte2; // won't compile without a cast.
bytesum += byte2; // is ok.
- applies to bitshift operators (as a unary promotion on each arg).
- applies to unary + and - (eg. byte b = +anotherByte; needs a cast).
- there are no promotions for ++, --, += etc.
* A switch argument can be any type that can implicit-cast to an int
(byte/char/short/int but not boolean or long).
- The argument and cases can also be compile-time constant expressions.
* Explicit Casting:
- Impossible casts are detected at compile time.
Other bad casts cause runtime exceptions rather than messes.
* Array casts:
- The only implicit conversion for arrays is: Base[] base = new Der[5];
- a runtime exception is thrown if you try to add anything but Derived
- There are no implicit casts for arrays of primitives.
- You can make an explicit array cast:
String[] strs = (String[]) ObjectArray;
Bitshift operators
- The left-hand argument to a bitshift operator can be an int, long
or any type that can be implicit cast to int (byte,char,short).
- char, byte, or short arguments will be promoted to int before the shift
takes place, and the result will be an int (so has to be cast to get back
to the original type).
- You can't shift futher than the number of bits in the left-hand argument
(int or long). Only the five (six) low-order bits of the right-hand
argument will be used to shift an int (long).
- Each left-shift (signed-right-shift) for positive numbers is equivalent
to multiplication (division) by 2. The division is rounded down.

Object-oriented concepts
* The signature of a method is its name, argument type and argument order.
- an overload is legal provided the two methods have different signatures.
- an override must have the same signature and return type, throw no new
checked exceptions and be at least as accessible as the method it is
* Fields do not act polymorphically:
- whenever you access a field from outside the class, the declared type of
the reference is used rather than the type of the object it refers to.
- regardless of the type of the reference, a method will always access its
own fields rather than those of a derived class.
* Private method calls are statically bound ... a method will call
the private method in the class where it is defined .. even if the
calling method is inherited by a derived class and the derived
class defines a method with the same signature as the private method.
* Calls to public and protected methods in the same class are dynamically
bound ... even for constructors (and from private methods). This is
different to C++.
* Re-using a static method's name in a derived class:
- A static method cannot be overriden by a non-static method
- A static method can be overriden by a static method but does not
dynamically bind (therefore static methods can't be abstract)
- You can overload a static method with a non-static method.
* note also that a static method can be inherited.
* note that a static var can be 'overriden' by a non-static var.
* It's legal to assign any reference type including an Interface reference
to an Object reference .. which makes sense because the interface ref
must point to an Object (or null).
Nested classes
-> from the Java Language Specification
-> from Sun's Java Tutorial
*** A nested class is a class that is defined inside another class.
* There are two distinct types of nested classes:
- static nested classes (or top-level nested classes)
- inner classes (which are always associated with an instance of
an enclosing class).
* (Nested) inner class types:
- member classes,
- local classes (method or code block),
- anonymous classes.
* Top-level classes (all classes are either top-level or inner)
- static nested classes,
- package member classes.
* Access to enclosing class:
- all outer-class members (inc. private) are accessible to an inner
class [Usually without scope modifiers, but if they are hidden by
an inner class name, you can use Outer.this.outerVar]
- static nested classes cannot acccess instance variables from enclosing
classes (there is no instance), but can access their static variables
(and classes i would think).
* Instantiation:
- For accessible inner classes: Outer.Inner i = new Outer().new Inner();
Even if you are in Outer's scope, you need to have an Outer instance.
- For accessible static nested classes:
Outer.Nested nested = new Outer.Nested();
* Local inner classes cannot access non-final local variables or method
* Nested classes generally have the same options with regard to
modifiers as do variables declared in the same place.
* Unlike class-level nested classes, local classes are executed in the
method's sequence of execution so you can't create an instance of the
local class before it is declared.
* The static keyword marks a top-level construct (class, method or
field) and can never be subject to an enclosing instance.
- no inner class can have a static member.
- no method can have a static member.
* Interfaces automatically attach 'public static final' to field and
class members (thus making them top-level nested rather than member
inner classes).
* A nested class cannot have the same simple name as any of its
enclosing classes (note: there is no similar restriction on method
or variable names).
* Know where the basic thread methods are:
- wait, notify and notifyAll are Object instance methods.
- start, stop, suspend, resume and interrupt are Thread instance methods.
- sleep and yield are Thread static methods
* Thread states:
- Bruce Eckel lists 4 thread states: new, runnable, blocked, dead.
* Blocking
- There are 5 ways a thread can be blocked - sleep, wait, suspend,
synchronization, io blocking.
- sleep and suspend do not release locks held by the thread.
* Deprecated methods
- stop is unsafe because it releases all locks and may leave objects in
an inconsistent state.
- suspend is deprecated because its failure to release locks makes it
prone to deadlock. Calling wait in a sync block is safer.
* The isAlive method returns false for new threads as well as dead threads.
* Threads inherit their priority from the thread that calls their ctor.

* Non-runtime exceptions are called checked exceptions.
* Even if a method explicitly throws a runtime exception, there is no
obligation for the caller to acknowledge the exception. One consequence
of this is that the restriction on exceptions thrown by an overriding
method only applies to checked exceptions.
* A try block's finally clause is called unless the JVM is exited (i think).
- a return in try or catch does not prevent finally from being executed.
* A try block's finally statement will be executed (unless the thread dies)
before control leaves the try/catch/finally scope. It will be executed
before unhandled exceptions (from try or catch) are passed back up the
calling stack.
* If you return from a try and finally does not return ... 1) the return
value is calculated, 2) finally executes and 3) the method returns with
the value calculated prior to executing finally.
* If you have a return in both try and finally, the finally's value
is always returned.
* If try/catch excludes continuation following finally, it is a compile
error to have any statements there.
* Primitive floating point operations do not throw exceptions. They use
NaN and infinity instead.
* A constructor can throw any exception.
* System.in is an InputStream and out and err are PrintStreams.
* Beware of instances of the abstract OutputStream and InputStream.
* Some OutputStreams:
- write(int) writes the eight low-order bits to the underlying stream
- write(byte[]) write(byte[],int off,int len)
- flush()
- close()
- has two ctors: (OutputStream) (OutpuStream, int size)
- writes primitives and strings to a byte-based stream.
- writes primitives, strings and serializable objects (inc arrays).
- is not a FilterOutputStream (seems strange).
- two ctors: (OutputStream) (OutputStream, boolean autoflush)
- never throws IOExceptions (sets internal flag instead)
- print and println for primitives and strings.
- print(Object) prints Object.toString().
- System.out and System.err are printstreams.
- 4 constructors: (File) (FileDescriptor) (String)
(String, boolean append)
- two ctors: () (PipedInputStream)
- method to connect(PipedInputStream)
- 2 ctors: () (int size)
* Some Writers
- OutputStreamWriter
- StringWriter, CharArrayWriter - like ByteArrayOutputStream
- FileWriter, BufferedWriter, PrintWriter, FilterWriter
- There is no ObjectWriter, DataWriter.
- PrintWriter can be constructed with an OutputStream or Writer.
* Some Readers:
- LineNumberReader doesn't attach numbers, it has getLineNumber().
- CharArrayReader is ctd with the char[] that it reads from and
optional int start position and length args.
* RandomAccessFile
- does not extend File or any type of stream.
- two ctors: ( File or String name, String mode="r","rw" )
- checks for read/write access at construction (unlike File).
- has read/write methods for primitives and strings (and a couple of
- has a (byte) file-pointer: seek(long), long length().
* FileDescriptor
- just a handle to a sink/source of bytes.
- only has two methods: sync() and valid()
* File
- represents an abstract file or dir pathname (file/dir doesnt have
to exist).
- 3 ctors: (File or String parent, String child) (String pathname)

* The Collection interface is extended by Set and List (and SortedSet).
- a set contains no duplicates.
- a list is a sequence and can have duplicates.
* The Map interface does not extend Collection and is extended by SortedMap.
* There are abstract classes for each of the main interfaces (Collection,
Set, List and Map) and implementations extend these.
* Set implementations
- HashSet
- TreeSet (implements SortedSet)
* List implementations
- ArrayList
- LinkedList
* Map implementations
- HashMap
- TreeMap (implements SortedMap)
* Vector and Hashtable (extends Dictionary) are older collection classes.
- Vector has been made to extend AbstractList and is like a sync'd ArraySet.
- Hashtable still extends Dictionary but it implements Map.
- In contrast to other collection types, Vector and Hashtable are
* There are Collections and Arrays classes to provide static methods for
general algorithms on collections and arrays.
* Stack extends Vector
- it has methods push(Object), pop, peek and search(Object).
- Push is identical to addElement but also returns the added Object.
- The top of a stack is the last element in the vector (and has index 1 as
far as the search method is concerned).

Math methods
* most act on and return double values
- note that floor(double), ceil(double) and rint(double) return doubles
not ints
* abs, max and min can take double, float, int or long arguments and the
return type matches the argument type.
* There are three rounding methods:
- int round( float ); // note both are 32-bit
- long round( double ); // note both are 64-bit
- double rint( double );
* log returns natural log.
* trig functions take double arguments in radians.
* Component is abstract ... Container is not abstract.
* Checkbox has 5 ctors: no-arg + four with String as first arg and
combinations of boolean initialState and CheckboxGroup.
* CheckboxMenuItem has nothing to do with Checkbox or CheckboxGroup.
- i think they generate both Item- and ActionEvents.
* Listeners:
- InputEvent (super for MouseEvent and KeyEvent) has a 'long getWhen()'
- MouseEvent has 'int getX', 'int getY' and 'Point getPoint' methods.
- ActionEvent and ItemEvent are not ComponentEvents so have to use
- MenuItems (inc. menus) can produce ActionEvents but not ItemEvents.
- ActionListener, ItemListener and TextListener only have one method and
therefore dont have Adapters.
- KeyListener: Pressed/Released/Typed
- FocusListener: Lost/Gained
- ComponentListener: Shown/Hidden Moved Resized
- ContainerListener: component- Added/Removed
- WindowListener: Opened/Closing/Closed
Activated/Deactivated ... keyboard focus.
- MouseListener: Pressed/Released/Clicked
- MouseMotionListener: Dragged/Moved
* BorderLayout is the default layout for Window/Frame/Dialog.
- add( component, BorderLayout.NORTH ) == add( "North", component )
- adding a component without an explicit position is identical to
adding a component at BorderLayout.CENTER.
- if more than one component is added to the same position, the most
recently added component is displayed there.
- north,south,east and west components only expand on one axis.
* FlowLayout is the default layout for Panels (including Applets).
- if the panel is bigger than its components, they are centered
horizontally and at the top (ie. north position).
* GridLayout with container larger than components expands to fill its
container provided that the number of components matches the rows*columns.
- Empty rows are given space, while empty rows are not.
- If there arent enough components, it will try to fill its rows first.
* Ctors for Border-, Flow- and GridLayout can take int hgap and vgap args.
- FlowLayout(int align, hgap, vgap)
* Be careful with nested layout questions ... eg Button->panel->frame, the
panel fills the whole frame, but the button will be its preferred size
at north position in the panel (and thus the frame).
* GridBagLayout
- There are two ways to set the constraints for a component in a gbl:
container.add( Component c, Object gbc ) or
gbl.setConstraints( Component c, GridBagConstraints gbc )
- weightx and weighty are doubles (0->maxDouble, default 0) and determine
where extra width or height is added if a row or column is smaller than
the container.
- gridwidth and gridheight are ints (1->maxInt) ... RELATIVE, REMAINDER.
- gridx and gridy are ints (0->maxInt) ... RELATIVE
- RELATIVE can apply to gridx/gridy (=next) or
gridwidth/gridheight (=second last)
* A Component added to a null layout won't display unless you set its
bounds ... this is the only place where a component can control its
parent's layout directly.
* Illegal arguments (eg. adding a container's parent to the container, adding
a window) get through the compiler but throw an exception at runtime.
* A class type's name is valid as an identifier, eg. int Boolean = 5;
* Modifiers:
- Automatic variable = local variable = variable declared in a method.
- Transient fields are not written out when a class is serialized.
- Transient and Volatile can only be applied to fields.
- Native can only be applied to methods.
- You can have a static synchronized method .. it is synchronized on the
class object.
- static transient is legal but doesn't effect anything.
* The right-hand-side of an assignment can be a reference to null.
- You can println a null reference (and add it to another string).
- What you can't do with a null reference is ... nullRef.aMethod();
* Order of Operation
- arithmetic before &^|
- & then ^ then |
* Garbage Collection
- unreachable objects can become reachable (if their finalize method
causes another object to have a reference to them) .. but i think
finalize if guaranteed to not run again.
- objects referenced by block-level variables are probably not available
for garbage collection until their enclosing method's scope is exited.
* The compiler never object to creating a local instance of the
the class being constructed in its constructor. If the call produces
an infinite loop, a runtime error will occur.
* Labelled break and continue statements:
- The label referred to by a labelled break statement is attached to
a statement block, which could be a loop or switch but doesnt have
to be.
- The label referred to by a labelled continue statement must be
attached to a loop.

Things to look out for
*** Read the answers before going through code samples.
* if (...)
statement2; //...always executed
* Beware of an otherwise legal override having a more restrictive
access modifier.
* Beware of missing return statements.
* Look for static modifiers and make sure they dont contain refs to
instance vars.
* Beware of standard methods (eg. main, paint, run) with the wrong
args or return type.
* With array declarations, look out for "int intArray[5] = ..."
* Beware of adding a primitive to a Vector.
- more generally, you can't use a primitive where an Object is
required (eg. the equals method).
* System.out.println( aReferenceToNull ); // is fine
* Beware of local vars from a try block used in its catch block
(out of scope).

suman bingi
Posts: 21
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
also u can find materials and scjp dedicated articles from a man who has scored perfect hundred at http://www.anilbachi.8m.com
Sahir Shah
Ranch Hand
Posts: 158
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Good work Asim.

Randall Twede
Ranch Hand
Posts: 4520
Java Python Scala
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
thanks asim i found your notes quite helpful. I would like to point out 2 errors though in the Layouts section.
1)FlowLayout is the default layout for Panels (including Applets).
Panels yes, but BorderLayout is the default for Applets.
2)GridLayout....Empty rows are given space, while empty rows are not.
I think it is columns are not.
asim wagan
Ranch Hand
Posts: 62
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
i) first of all these are not my notes..
ii) Applets are direct childs of panel class and this is true there default layout is Flow Layout try adding some buttons to an applet and see what happens.
Randall Twede
Ranch Hand
Posts: 4520
Java Python Scala
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
it does seem odd that applets have a different default layout since as you say they extend panel. however i am 100% certain on the fact that their default layout is BorderLayout.
bill bozeman
Ranch Hand
Posts: 1070
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Randall, sorry to disagree with you, but the default for applets is FlowLayout not BorderLayout.
Defaults are:
Panel: FlowLayout
Applet: FlowLayout
Frame: BorderLayout
Dialog: BorderLayout
Check it out in RHE or compile the code and run it in a browser:

Randall Twede
Ranch Hand
Posts: 4520
Java Python Scala
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
hmm. "Thinking in Java" says it is BorderLayout. I cant seem to find anything already compiled to prove one way or the other so I will have to "ask" the compiler. I cant afford to miss a question like that. Thanks
Randall Twede
Ranch Hand
Posts: 4520
Java Python Scala
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I compiled and ran bill's code and the default is indeed FlowLayout. This is a serious error in bruce eckels book as he stated the default was BorderLayout several times.
asim wagan
Ranch Hand
Posts: 62
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi! Randell always remember the inheritence hirarchy that helps you buid your concepts. As panel is parent of applet so it should take something from panel. and one of them is default layout.
lakshmi nair
Ranch Hand
Posts: 63
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think Bruce Eckel (Thinking In Java) talks about JApplets whose default is BorderLayout
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!