The notes/tips given here are primarily intended for SCJP 1.2 exam (310-025), for contents and
resources specific to SCJP 1.4 exam (310-035); please visit SCJP 1.4 Resources page. Although, most of the tips given here should be useful for both the exams.
This is a compilation of notes on various topics required for Java Programmer Certification exam
(commonly referred as SCJP exam). The notes are intended for revision purpose, they are presented as tips
that would help you recall the key-concept of the particular section.
You should already know these concepts properly.
These tips/notes also include how you can avoid potential errors/common mistakes by simply
understanding and remembering few simple points/tips. If you read these tips everyday in the last few days
before taking the mocks as well as the real exam, I believe your score should improve by 5-10%.
I have arranged them in the following sections, not necessarily according to the exam objectives though.
I hope you find these note useful, and score good marks in your SCJP exam. Do let me know your feedback
about this effort.
Two public classes in the same file are not allowed.
Check modifier of the top level class, it shouldn't be "private" or "protected ".
The main() method calling a non-static method directly, or accessing non-static variables, using this reference is a compile time error.
Methods can have same name as the constructor(s), check for return type.
Case statements with values out of permissible range, only integer compatible value are permitted.
Private constructors, watch out for them especially if there is a subclass, if default no-argument constructor is private,
a subclass will not be compiled, if its constructor has to use this default constructor.
If the compiler gives you the default no-args constructor for the class, its accessibility is same as the class.
An assignment statement for boolean data type, which looks like a comparison if (a=true), it is valid but will be always evaluated to true.
main() can be declared final, or native.
Class declarations can come in any order (superclass first, subclass next etc).
Forward references to variables gives compiler error.
-0.0 == 0.0 is *true*.
Multi dimensional arrays can be sparce ie., if you imagine the array as a matrix, every row need not have the same number of columns.
Arrays, whether local or class-level, are always initialized.
Strings are initialized to null, not empty String. And an empty String ("") is *NOT* same as a null string.
A declaration cannot be labeled.
continue must be in a loop (for, do , while). It cannot appear in case constructs.
break can be used to break out of any labeled block.
A constructor can throw any exception.
Constructor must declare all the checked exceptions declared in the base constructor. They may add other exceptions. This behaviour is exactly opposite from that of methods. The overriding method cannot throw any exception other than overridden method. It may throw subclass of those exception.
Initializer blocks are executed in the following order
Static initializers executed first, in the order they are declared. Takes place when the class is loaded, instance creation is not required.
Instance initializers are executed next, Instance initializers get executed ONLY IF the objects are constructed.
The constructor is executed at the last while creating an object.
An instance final variable may be initialized only once, latest in the constructors.
A static final variable may be only initialized once, latest in a static initializer, but not in the constructor
because it can be referenced w/o creating an instance of the class.
All comparisons involving NaN and a non-NaN would always result false,
moreover comparisons involving two NaN values will also result in false, except for !=.
i.e.
Float.NaN == Float.NaN results in false.
Float.NaN != Float.NaN results in true.
Default type of a numeric literal with a decimal point is double.
We can declare array of ZERO elements, it is perfectly valid and is commonly done by main() method if there are no command line arguments.
you can *NOT* use more than '4' digits in case of character constant.
Char constant '\101' is valid as it is representing the value in "octal", which is equivalent to 65.
Values for char constant '\u000A' and '\u000D' is not valid as they represent line breaks, in fact these values can not appear anywhere in the Java source code.
Interface methods can not be native, static, synchronized, final, private, or protected.
Interface fields can't be private or protected. They are by default public static final. The final variable must be initialized.
transient variables can't be members of interfaces.
volatile variables can't be final or members of interfaces.
CONSTANT values up to an int can be assigned (without cast) to variables of lesser size (eg. short to byte) if the value is representable by the variable.(ie. fits into the size of the variable).
native method declarations can not have bodies, as they are implemented outside JVM.
abstract method declarations can not have bodies, because its implementation is differed to the subclass.
Operators
integer (and long ) operations / and % can throw ArithmeticException while / and % will never, even in case of division by zero.
The == gives compiler error if the operands are cast-incompatible.
instanceOf is *NOT* same as instanceof, later is Java operator, former is *NOT*.
instanceof operator always return false for null value.
Class H and class G have no relation (i.e if two class has no relation) with each other so both instanceof and == operator will give you compile time error.
RHS of an instanceof operator must be a Class, Interface or an Array.
The genral rule is that ~i = -i-1 (eg.: ~7 = -7 - 1 = -8)
&& and || oprators are "short-circuit" operators, i.e. they NEVER evaluate RHS operand if LHS operand can determine the result of the operation.
operands of mathematical operators are ALWAYS promoted to ATLEAST int. (ie. for byte * byte both bytes will be first promoted to int.) and the return value will be ATLEAST int.
int i = 5 + 'c'; is perfectly valid, and c will get converted to its numeric value.
char is the only integral which is unsigned, all others are signed.
Compound assignment oprators ( +=, *= etc) behave in this way -
operand1 += operand2;
Gives => operand1 = (TYPE_OF_OPERAND1)(operand1 + operand2);
except that operand1 is evaluated only once.
Example
int x = 4;
x += 3.78; // x becomes 7, but no compiler error
Flow Control And Exceptions
Check for uninitialized variable references with no path of proper initialization.
You an have finally w/o catch block, but try must be followed by either catch or finally.
if there is a System.exit() in try-catch-finally blocks, finally won't complete.
Order of try-catch-finally blocks matters.
The following code will give you compiler error " Unreachable statement "
Conversion sequence for primitives is as follows -
byte --> short --> int --> long --> float --> double
/
char ___/
boolean can not be converyted to any other primitiv, and any other primitive can not be converted to boolean.
objectOfSuperclass = objectOfSubclass is always valid w/o explicit casting.
Primitive array types can never be assigned to each other, even though the primitives themselves can be assigned.
ie. ArrayofLongPrimitives = ArrayofIntegerPrimitives gives compiler error even though longVar = intVar is perfectly valid.
null value can be casted but do remember it is of no use to cast null value except in some cases in which it would help in resolving ambiguity.
e.g.
class A
{
public void foo(Integer x) { //some code }
public void foo(Double x) { //some code }
}
A a = new A();
a.foo((Integer)null);
a.foo((Double)null);
Thanks to Leonardo Bueno for his inputs on this one.
Overriding and Overloading
A class without abstract methods can still be declared abstract.
If a class has an abstract method, it must be declared abstract.
If null is passed as a method parameter to an overloaded method, then most specific method as per the parameter hierarchy will be called. BUT if two methods which are not form the same hierarchy are present than compiler will raise an ambiguity error.
Overriding method must have same signature and return type as the overriden method.
Overriding method can be more accessible (public) than the overriden method, but it can not be more restrictive, otherwise it will result in a compile time error.
The accessibilty (from most restrictive to least restrictive) is as follows - private => package => protected => public
The overriding method *MUST* throw exception which is either same as the exception that the overriden method is throwing, or should be a subclass of it.
It may also choose not to to throw an exception.
Threads
Threads can not be initiated with classes that do not either implement Runnable or extend Thread.
Signature of run() method is - public void run(), any other variation is not allowed and will result in a compile time error if a method by this signature is not present in a class extending Thread or implementing Runnable. This method does not throw any exception.
The default Thread priority is the priority of the thread which started it, it can be changed using method setPriority(int priority).
The methods sleep() and yield() are static methods of the thead class, they ALWAYS work on the thread which is currently executing. sleep() method throws IterruptedException, whereas yield() does not throw any.
The methods wait(), notify(), and notifyAll() are the methods of Oject class, they are inherited in the Thread class and all throw InterruptedException.
The methods wait(), notify(), and notifyAll() *MUST* be called in a synchronized block, otherwise the call will result in IllegalMonitorStateException at Runtime (It is-a RuntimeException).
The instance method setDaemon(bolean on) of Thread class can be used to set a thread as daemon thread, or user thread. This method *MUST* be called before the thread is started, otherwise
IllegalThreadStateException is thrown at Runtime.
The instance method join() can be called on any thread, so that the calling thread waits till this particular thread (on which join() has been called) dies, i.e completes execution of its run() method. The method throws IterruptedException, and its overloaded version take "timeout" paramete in milli-seconds and other in mili-seconds and nano-seconds.
Inner Classes
Inner classes can also be private or protected.
Inner classes can access all the instance variables of the enclosing class.
Local inner classes *CAN NOT* access non-final vars of the enclosing method, it is a compiler error.
You cannot declare a static variable inside a non-static inner class but static final variable is allowed as the compiler will treat it as a constant.
Inner classes do not have same name as the enclosing classes.
java.util Package
Following classes are the implementations of various Collection framework interfaces.
interface Set extends Collection - HashSet
interface SortedSet extends Set - TreeSet
interface List extends Collection - ArrayList, Vector, LinkedList
interface Map - HashMap, HashTable
interface SortedMap extends Map - TreeMap
Set => Unique values, no duplicates, List => Order, Map => key-value pair.
Map *does not* extend Collection.
Dictionary is a class, not an interface.
Collection is an Interface where as Collections is a helper class.
BitSet has nothing to do with sets or collections.
Only Vector and Hashtable class of java.util package are thread safe.
Important bulk operations of Collection with their mathematical equivalent statement.
(Note that methods are called on "a" and a is being modified as a result)
(1) a.containsAll(b) --> b is a subset of a
(2) a.addAll(b) --> a is a union b
(3) a.removeAll(b) --> a is a difference b
(4) a.retainAll(b) --> a is a intersect b
(5) a.clear() --> a is an empty set
The operations performed by methods addAll(b), removeAll(b), retainAll(b)
and clear() *do modify* the original collecton.
java.lang Package
Wrapper classes are all immuatable, the wrapper classes for primitives int and char are Integer, and Character respectively.
void is *NOT* a primitive, so Wrapper class Void *IS NOT* a Primitive Wrapper class.
Math class is not an immutable classes. It's final, non-instantiable (private constructor) class.
Math.abs() will return the argument itself, if it is equivalent to Integer.MIN_VALUE or Long.MIN_VALUE. e.g. Math.abs(-2147483648) return -2147483648. if literal is less than MIN_VALUE then compile time error will occur "Decimal must be in the range of so and so".
In java.lang.Math class -
Math.ceil(-0.5) = -0.0
Math.round(-5.5) = -5
Math.round(5.5) = 6
Math.round(5.49) = 5
Math.round(-5.49) = -5
equals() method of standard Wrapper classes, String and StringBuffer return false if the object classes are different.
It does not flag a compiler error. However, you can not be certain about the other classes if they override this method.
You can not pass primitives to equals() method.
You can use negative argument in indexOf() and lastIndexOf() method of String class.
In such case it will start searching from zero.
There is *no* trim() method in StringBuffer.
There is *no* reverse() or append method in String.
Strings are IMMUTABLE, can not be changed once created. They are immutable, period.
replace() method of String class returns the same object if both the parameters are same, ie. if there is no change.
java.io Package
File class has NO methods to deal with the contents of the file.
File class can delete (delete()) and create new files (createNewFile()).
File class method renameTo() takes File object as param.
To test if file is a directory, method isDirectory() of File class can be used.
getParent() of File class returns name of the parent directory as a String,
whereas getParentFile() returns File object.
RandomAccessFile descends from Object and implements DataInput and DataOutput, for reading and writing all java primitives.
Additionally, also has methods to read/write UTF - readUTF() and writeUTF().
InputStream and OutputStream are abstract classes, while DataInput and DataOutput are interfaces.
Only InputStreamReader and OutputSreamWriter are for customizing the "Encoding", their constructors take encoding as a parameter.
The default encoding used by these classes is defined by the system property - file.encoding
Only InputStreamReader and OutputSreamWriter are the reader/writer classes which take InputStream and OutputStream in their parameters respectively.
Also PrintWriter class can take an OutputStream as a parameter in its constructor.
The Writer class has no write() method with a parameter of type char,
instead has a method that takes an int, only lower 16 bits of this int are written as a character.
Abstract Reader class's subclass must implement are write(char[], int, int) and close() methods.
Most other methods are defined, or are overridden by subclasses.
Abstract Writer class's subclass must implement are write(char[], int, int), flush(), and close().
Most other methods are defined, or are overridden by subclasses.
Abstract Writer class has 2 additional write() methods besides the write trio, which takes String as a parameter. They are -
void write(String str) throws IOException
void write(String str, int offset, int len) throws IOException
Only FileOutputStream and FileWriter can append to a file. They both take boolean parameter "append" as
second parameter in their constructors.
LineNumberReader extends BufferedReader, there is *NO* corresponding LineNumberWriter class.
System.out and System.err are PrintStream.
PrintWriter extends Writer and has all print() and println() methods analogus to the PrintStream.
PrintStream and PrintWriter constructors also have boolean as their second parameter, but the second parameter here
indicates whether it is "autoFlush". By default auto flush is off.
AWT - Layout
The 5 Layouts are
FlowLayout (implements LayoutManager), default for Panel, and Applet.
GridLayout (implements LayoutManager)
CardLayout (implements LayoutManager2)
BorderLayout (implements LayoutManager2), default for Window, hence Frame and Dialog.
GridBagLayout (implements LayoutManager2)
The position/placement & sizing of the components is taken care of by the LayoutManager.
When not explicitly set, component receives certain properties from its container, such as (1) Font (2) Foreground (3) Background etc.
All layouts except GridBagLayout take int hgap and int vgap in their constructors.
The methods of Container class for LayoutManager are -
LayoutManager getLayout();
void setLayout(LayoutManager mgr);
The Methods of Container class for adding components are -
Component add(Component comp);
Component add(Component comp, int index);
void add(Component comp, Objects constraints);
void add(Component comp, Objects constraints, int index);
The Methods of Container class for removing components are -
void remove(int index);
void remove(Component comp);
void removeAll();
FlowLayout always honors component's preferred size, whereas GridLayout does not.
Default alignment of FlowLayout is FlowLayout.CENTER,
the components are arranged in the top row at center, and default hgap and vgap is 5.
The default hgap and vgap for all layouts except FlowLayout is 0 (zero).
In GridLayout either Row or Column can be 0 (zero), but not both.
Once you specify row parameter(first param) for GridLayout, the number of columns is
decided by the layout depending on the number of components you add to it. Thus if you construct
new GridLayout(2,2) and add only 2 components, it will place two components on 2 rows, each
spanning the complete width. Likewise, for this layout if you add 6 components, you will have 2 rows each containing
3 components.
In BorderLayout -
NORTH and SOUTH honor only preferred height of the component.
EAST and WEST honor only preferred width of the component.
CENTER *does not* honor component's preferred size, all the remaining place is given to the component which is placed there.
In BorderLayout by default the components are added at the center.
CardLayout shows only one component at a time.
The methods of CardLayout are (all take Container as a parameter)-
void first(Container parent);
void last(Container parent);
void next(Container parent);
void previous(Container parent);
For a CardLayout, if components are added with add(Component comp,String name), you can use method - void show(Container parent, String name)
AWT - Events and Event Listeners
java.awt and java.awt.event are two different packages.
The super class of all java events is java.util.EventObject, note that it is not from java.awt.event package.
The method Object getSource(); is of EventObject class, it returns the object that generated the event.
All AWT related events inherit from abstract class java.awt.AWTEvent,
note that it belongs to package java.awt.
The important method of AWTEvent class is - int getID(), which specifies
the exact nature of the event, such as - MouseEvent.MOUSE_CLICKED.
The events can be classsified into two categories -
Semantic Events - Consists of a group of low level events performed by the user
in a specific sequence. Such as Button clicked.
ActionEvent - generated by (1) Button (2) List (when list item is double-clicked)
(3) MenuItem (4) TextField (When Enter key is pressed).
The methods include - String getActionCommand() which returns
the text assoiated with it, and int getModifiers() which returns
if any of the special keys, such as SHIFT_MASK, CTRL_MASK is pressed.
ItemEvent - generated by (1) Checkbox (2) CheckboxMenuItem (3)
Choice (4) List. The methods include - Object getItem() which returns the
object that was selected or deselected, and int getStateChange() which returns
a value indicating whether it was selected (ItemEvent.SELECTED) or deselected (ItemEvent.DESELECTED).
AdjustmentEvent - generated by a Scrollbar. The method is
int getValue() which returns the value associated with
that particular position of the scrollbar.
TextEvent - generated by (1) TextField and (2) TextArea when its
text is changed.
Low Level Events - Low level events are raw events, which do not form a
higher event.
ComponentEvent - generated by ALL components when a component is
hidden, shown, moved or reized.
ContainerEvent - generated by ALL containers when a when a component
is added or removed from it.
FocusEvent - generated when a component gets or looses focus. Component
can receive keystrokes nly when it has focus.
KeyEvent - a subclass of (abstract) InputEvent, it is generated when user presses or
releases the key; or does both - i.e. key typed.
MouseEvent - subclass of (abstract) InputEvent, generated when user moves the mouse or
presses a mouse button. The constants defined in this class indicate the nature of the event (which can be
retrieved using getID() method of AWTEvent class, inherited here) are -
All must be prefixed with MouseEvent.
(1) MOUSE_PRESSED (2) MOUSE_RELEASED (3) MOUSE_CLICKED (4) MOUSE_DRAGGED (5) MOUSE_MOVED
(6) MOUSE_ENTERED (7) MOUSE_EXITED.
It also has methods getX(), getY() and getPoint() to get screen co-ordinates where this
event has occured. It also has method getWhen() inherited from InputEvent, which return long
giving the time stamp when the event occurred. The method getClickCount() returns the number of clicks
associated with this event.
PaintEvent - generated when a component should have its paint()/update()
method invoked. Typically handled by AWT and not by the application. Note that there is
*NO* event llistener associated with event.
WindowEvent - generated when an important operation is performed on a window.
There is *NO* MouseMotionEvent, though MouseMotionListener is there. MouseEvent alone handles all the mouse related events.
The Event Listner is an object to which a component has delegated the task of handling
a particular event. Event Listeners are all interfaces which a class must implement to handle
the particular event.
The listeners associated with Semantic Events are -
ActionListener
ItemListener
AdjustmentListener
TextListener
The listeners associated with Low Level Events are -
ComponentListener
ContainerListener
FocusListener
KeyListener
MouseListener
MouseMotionListener - **NOTE**
WindowListener
All listeners for the particular event are notified, but the order in which they are notified
can not be determined.
Adapters are abstract classes which provide empty method body for all the methods of
Low Level Events listeners, so that you do not have to implement all methods.
There are 7 adapters corresponding to 7 Low Level Events listeners shown above
(eg. KeyAdapter, MouseAdapter etc).
While Event processing the order of processing is - processEvent() first, then processXXXEvent()
and then any of the listeners, provided that these two methods call their super implementation at the end. (XXX here stands for the particular event
such as processActionEvent()).
The processEvent() method of a *must* call its super's implementation of processEvent()
in the end, otherwise processXXXEvent() method of the specific component will not be called.
processXXXEvent() method of the specific component *must* call its super's implementation of processXXXEvent()
otherwise the registered listeners will not be notified.
AWT - Components
TextField and TextArea both descend from common superclass TextComponent
TextArea is an important class, its constructors are -
TextArea()
TextArea(String text)
TextArea(int rows, int cols)
TextArea(String text, int rows, int cols)
TextArea(String text, int rows, int cols, int scrollBarPolicy)
scrollBarPolicy is defined as one of these 4 constants defined in TextArea-
(1) SCROLLBARS_BOTH (2) SCROLLBARS_NONE (3) SCROLLBARS_HORIZONTAL_ONLY (4) SCROLLBARS_VERTICAL_ONLY
Few common methods of TextField and TextArea inherited from TextComponent are -
String getText()
void setText(String text)
String getSelectedText()
void setEditable(boolean editable)
The Menu bars may only appear in frames.
A menu may conatin any one of these 4 components -
MenuItem
CheckboxMenuItem
Separator (by Menu.addSeparator() method)
Menu
Only Menu and MenuBar have add() methods.
Non-Technical Tips
Do have proper sleep on the previous night.
Stay calm and alert during the examination, pay special attention to all the access modifiers.
For "type-in" questions (where you are required to type the answer), do not forget to mark the question,
and re-check the answer afterwards, it is always possible to make a typographic error when you are using a unknown keyboard.
Whenever one of the options says "Code does not compile" pay attention to every detail of the question code,
better still mark the question and review it later.
Use pen and paper that is provided to you whenever you need it. It proves very useful in bitwise operator questions,
AWT questions, Garbage Collection questions, and in many other questions.
For GC you can draw an object on paper and refer to it by variables, and modify those references according to the code,
if you see no references to the object it is eligible for GC. Note that if a method returns the object to the the calling code,
that particular object is not eligible for GC.
For AWT and IO, it is not required to know each and every method of those numerous classes. Try understanding the
approach behind them, and know their constructors.
There are 59 questions, 120 mins, so on an average you have 2 mins per question. Usually, time is never an issue.
Utilize all 120 mins available to you; even if you finish it early, review all your answers.