You are on page 1of 101

TESTING OBJECTIVES FOR THE NEW SUN

CERTIFIED PROGRAMMER FOR JAVA 2 PLATFORM

Section 1 :  Declarations and Access Control

 Write code that declares, constructs, and initializes arrays of any base type using any
of the permitted forms both for declaration and for initialization.
 Declare classes, inner classes, methods, instance variables, static variables, and
automatic (method local) variables making appropriate use of all permitted modifiers
(such as public, final, static, abstract, and so forth). State the significance of each of
these modifiers both singly and in combination, and state the effect of package
relationships on declared items qualified by these modifiers.
 For a given class, determine if a default constructor will be created, and if so, state
the prototype of that constructor.
 State the legal return types for any method given the declarations of all related
methods in this or parent classes.

Section 2 : Flow Control and Exception Handling

 Write code using if and switch statements and identify legal argument types for
these statements.
 Write code using all forms of loops including labeled and unlabeled use of break and
continue, and state the values taken by loop control variables during and after loop
execution.
 Write code that makes proper use of exceptions and exception handling clauses (try,
catch, finally) and declares methods and overriding methods that throw exceptions. 

Section 3  : Garbage Collection

 State the behavior that is guaranteed by the garbage collection system, and write
code that explicitly makes objects eligible for collection. 

Section 4  : Language Fundamentals

 Identify correctly constructed source files, package declarations, import


statements, class declarations (of all forms including inner classes), interface
declarations and implementations (for java.lang.Runnable or other interface
described in the test), method declarations (including the main method that is used
to start execution of a class), variable declarations and identifiers.
 State the correspondence between index values in the argument array passed to a
main method and command line arguments. Identify all Java Programming
Language keywords and correctly constructed identifiers.
 State the effect of using a variable or array element of any kind when no explicit
assignment has been made to it.
 State the range of all primitive data types and declare literal values for String and
all primitive types using all permitted formats, bases, and representations.

Section 5 :  Operators and assignments

 Determine the result of applying any operator, including assignment operators,


instanceof, and casts to operands of any type, class, scope, or accessibility, or any
combination of these.
 Determine the result of applying the boolean equals (Object) method to objects of
any combination of the classes java.lang.String, java.lang.Boolean, and
java.lang.Object.
 In an expression involving the operators &, |, &&, ||, and variables of known values
state which operands are evaluated and the value of the expression.
 Determine the effect upon objects and primitive values of passing variables into
methods and performing assignments or other modifying operations in that
method.

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

 State the benefits of encapsulation in object oriented design and write code that
implements tightly encapsulated classes and the relationships "is a" and "has a".
 Write code to invoke overridden or overloaded methods and parental or overloaded
constructors; and describe the effect of invoking these methods.
 Write code to construct instances of any concrete class including normal top level
classes, inner classes, static inner classes, and anonymous inner classes.

Section 7 : Threads

 Write code to define, instantiate, and start new threads using both
java.lang.Thread and java.lang.Runnable.
 Recognize conditions that might prevent a thread from executing.
 Write code using synchronized, wait, notify, or notifyAll, to protect against
concurrent access problems and to communicate between threads. Define the
interaction between threads and between threads and object locks when executing
synchronized, wait, notify, or notifyAll.

Section 8 :  The java.awt Package

 Write code using component, container, and LayoutManager classes of the java.awt
Section 9 : The java.lang Package

 Write code using the following methods of the java.lang.Math class: abs, ceil, floor,
max, min, random, round, sin, cos, tan, sqrt.
 Describe the significance of the immutability of String objects.

Section 10 : The java.util Package

 Make appropriate selection of collection classes/interfaces to suit specified behavior


requirements.

Section 11 : The java.io Package

 Write code that uses objects of the file class to navigate a file system.
 Write code that uses objects of the
classes InputStreamReader and OutputStreamWriter to translate between
Unicode and either platform default or ISO 8859-1 character encoding and
Distinguish between conditions under which platform default encoding conversion
should be used and conditions under which a specific conversion should be used.
 Select valid constructor arguments
for FilterInputStream and FilterOutputStream subclasses from a list of classes
in the java.io.package.
 Write appropriate code to read, write and update files using FileInputStream,
FileOutputStream, and RandomAccessFile objects.
 Describe the permanent effects on the file system of constructing and
using FileInputStream, FileOutputStream, andRandomAccessFile objects.

Complete Java 2 Certification Study Guide 


by Philip Heller, Simon Roberts.

I think this is by far the best book for those who are preparing for the SCPJ2
exam. Everything essential to pass the exam has been covered in a very lucid
language. It would not, perhaps, be an exaggeration to say that if you want
to read only one book for the certification then this is the book you should go  
for.

A Programmer's Guide to Java (tm) Certification  


by Khalid Azim Mughal, Rolf Rasmussen

If  you want to make absolutely sure that you will miss nothing in the exam,
you must read this book. Though this book covers much more material than
is absolute necessary for the certification, it tends to make obscure areas
clear to you. One will certainly find the exercises in this book on the tougher
side. It may even make you postpone the date of your appearance in the
exam :-). Written to deal a blow to your confidence :-)), but a great book no
doubt.

 
Java 2 Exam Cram   
by Bill Brogden, William B. Brogden
 
 
This book is what the title suggests. Written in a notes like style and perhaps
meant to be last minute preparation for the exam. One of the better books in  
the market.  
 

Core Java 2, Volume I: Fundamentals 


by Gary Cornell, Cay S. Horstmann, Cay S. Forstmann

I would call this book "The Book". Not only great for understanding the basic
concepts thoroughly but also a collector's item, since it will prove to be
invaluable in the long time to come after you get the certification. This book
is primarily meant for programmers. The emphasis is on the practical side of  
Java Programming. While studying for the certification myself, I used to keep
referring to this book to understand the complex concepts of Java
programming. I found this book to be the most useful for myself.

This book, by Ivor Horton, is also a must for java programmers. The name of
the book is a bit deceptive since this book would prove to be useful for Java
professionals too. I use this book to look up the solutions to my programming
problems.

Section 1 :Declaration and Access Control


 

 
Write code that declares, constructs, and initializes arrays of any base type using
any of the permitted forms both for declaration and for initialization.
 

 
The declaration of an array provides some information to the compiler such as the type of
the data the array will hold and its name. To indicate that a variable of type array is being
declared, a pair of brackets is used. For example:
               
            float [] temperature ;
 
This statement does not creates any array, it only creates a name, which can be used to
store reference to an array. The arrays are implemented as objects in Java and hence the
name of the array does not stores the array, instead it stores a reference to array.
 
If you wish to declare a multi-dimensional array, you use more than one pair of brackets.
 
            float [][] temperature;
 
The size of the array is indicated while creating the array using the new operator.
 
            temperature = new float [6];
 
Here an array is created which would hold six items of type float. This array will be referred
to by the name temperature. You can also use any expression that evaluates to an integral
type exceptlong at runtime, to denote the size of the array. So, instead of 6, you can write
2*3, or even an expression containing variables whose values will be known only at
runtime. The value returned by the dimension expression must be of integral type, or a
compile time error occurs. Each expression, undergoes unary numeric promotion. The
promoted type must be int, or a compile time error occurs. This means specifically that the
type of a dimension expression must not be long .
 
These two statements are generally combined in a single statement:
 
            float [] temperature = new float [6];
 
Once an array is created, its length never changes. To make an array variable refer to an
array of different length, a reference to different array (which must be of the same type)
must be assigned to the variable. After this array is created, its data can be accessed by
index values. The elements of an array are accessed by using non negative integer index
value. The first element of an array is referred to as temperature [0], since indexing in Java
mostly begins with 0.
 
Unless all the elements of an array are explicitly initialized, they are initialized automatically
with the default values of the element type of the array. In the above example, the default
values of all the six items of data will be 0.0, since it is the default value for float.
 
To initialize an array, each of the individual elements is initialized separately.
 
           temperature [0] = 34.6;
           temperature [1] = 35.6; and so on.
Or you can use a loop to initialize the elements of an array.
 
If the values of the elements of an array are known at compile time, an alternative way of
declaring and initializing an array can be used.
 
            float [] temperature = {34.6,35.6,36.6,37.5,32.9,30.8};
 
There is no restriction on the order of pair of brackets and the variable name. So, the
following code is perfectly valid:
 
            float temperature [] = {34.6,35.6,36.6,37.5,32.9,30.8};
 
The component type of an array may be one of the basic types such as char, byte,
short, int, long, float, double or boolean, or it may be a reference type. It may be an array
itself.
 
While creating a multidimensional array, dimensions must be created left to right.
So, int [] [] array = new int [] [4]; is not valid.

Declare classes, inner classes, methods, instance variables, static variables, and
automatic (method local) variables making appropriate use of all permitted
modifiers (such as public, final, static, abstract, and so forth). State the
significance of each of these modifiers both singly and in combination, and state
the effect of package relationships on declared items qualified by these modifiers.

Access Modifiers

abstract 
 
This applies to classes and methods.
 
A class must be declared abstract if any of the following conditions is true :
 The class has any abstract methods.
 The class inherits any abstract methods but does not implement them.
 The class declares that it implements an interface but does not implement all of its
methods.
In a way, abstract is the opposite to final. A final class cannot be sub-classed but
an abstract class must be sub-classed. An abstract class can have non-abstract methods.
 
When applied to a method, it means that it has not been implemented in its class. Any other
class extending this class must either implement the inherited abstract method or itself be
declaredabstract.
 
final
 
This applies to classes, methods and variables.
 
A variable can be declared as final. Doing so prevents its contents being changed. This
means a final variable must be initialized when it is declared. It is common coding
convention to choose all uppercase identifiers for ‘final’ variables. Final variables do not
occupy memory on a per-instance basis. Thus, it is essentially a constant. If a final variable
is a reference to an object, it is the reference that must stay the same, not the object. It
means that the reference cannot be assigned to some other object, but data of the object
can be changed.
 
A final class cannot be sub-classed.
 
A final method cannot be overridden.
 
static
 
This can be applied to variables, methods and initializer blocks.
 
When applied to a variable, the variable belongs to the class itself and not to its objects. All
the objects of the class share the variable. If you modify the value of a static variable in one
object, the value gets changed for all the objects of the class since there is only one
variable being shared among all the objects.
 
A static initializer block is executed when the class is loaded.
 
Methods declared static have several restrictions:
 They can only call other static methods.
 They must only access static data.
 They cannot refer to ‘this’ or ‘super’ in anyway.
 A static method cannot be overridden to be non static.
 
native
 
It can be applied to methods only.
It indicates that the method body is to be found elsewhere i.e. outside the JVM, in a library.
Native code is written in a non java language and compiled for a single target machine type.
 
transient
 
It applies only to variables. A transient variable is not stored as part of its object’s
persistent state. Many objects, especially those implementing Serializable or Externalizable
interfaces, can have their states serialized and written to some destination outside the JVM.
This is done by passing the object to the writeObject() method of the ObjectOutputStream
class. If the stream is chained to a file output stream, then the object’s state is written to a
file. If the stream is chained to a socket’s output stream then the object’s state is written to
the network. In both cases, the object can be reconstituted by reading from an object input
stream.
 
There will be times when an object will contain extremely sensitive data. Once an object is
written to a  destination outside JVM, none of the Java’s elaborate security mechanisms is in
effect. If you declare a variable transient, it’s value will not be written out during
serialization.
 
volatile
 
It is applied only to variables. It indicates that such variables might be modified
asynchronously, so the compiler takes special precautions. Volatile variables are of interest
in multi-processor environments.
 
public
 
A class, method or variable declared public can be accessed by any other code in a
program.
 
private
 
This member can only be accessed by other members of its class.
 
default
 
when a member does not have an explicit access specification, it is visible to subclass as
well as to other classes in the same package.
 
protected
 
This allows access from everywhere but except for different package non-subclass.
 
Note: You cannot combine some of these modifiers together. Some of the cases are:
 No two access modifiers can be combined. Such
as public private, protected public or private protected.
 abstract and final.
 Native methods cannot be abstract, or strictfp.
 An abstract method cannot be static, final, synchronized, native, private, or strictfp. 
 For a given class, determine if a default constructor will be created, and if
so, state the prototype of that constructor.

 If there are no constructors defined in a class, Java provides a default constructor.


This constructor is a no-args constructor and it simply sets all the fields of the object
to their default values. So, all numeric data contained in the fields would be zeroed
out, all boolean values would be set to false, and all reference variables set to null.

If there is even a single constructor defined in a class, Java will not create the
default constructor. The signature of this default constructor is like this:
 public ClassName () { }

where ClassName is the name of the class for which this constructor has been
provided.
 State the legal return types for any method given the declarations of all
related methods in this or parent classes.

 A method is related to other methods in its own class in case of overloading and with
methods in its parent classes in case of overriding.
 In case of overloading, the return type does not matter. So, all the overloaded
methods in a class can have different return types.
 But in case of overriding, the return type of the overriding method must be same as
that of the overridden method in the parent class.

Flow Control and Exception Handling

Write code using if and switch statements and identify legal argument types for
these statements.

The if statement

The legal argument type for if statements is a boolean value i.e. true, false or any
expression which evaluates to these values. In Java true and false are not represented by
integers like in C or C++.

Only one statement can appear after if or else. If you want to include more statements, you
will need to create a block using {}. You can also include the curly braces when using the if,
even if there is only one statement in each clause. This makes it easy to add another
statement at a later time, and you do not have to worry about forgetting the braces.

Nested if statements

When you nest if statements, the main thing to remember is that an else statement always
refers to the nearest if statement that is within the same block as the else and that is not
already associated with an else.

The if-else-if ladder

The if statements are executed from the top down. As soon as one of the conditions
controlling the if is true, the statement associated with that if is executed, and the rest of
the ladder is bypassed. If none of the conditions is true, then the final else statement will be
executed. The final else acts as a default condition; that is, if all other conditional tests fail,
then the last elsestatement is performed. If there is no final else and all other conditions are
false, then no action will be taken.

The switch statement

It is Java’s multi-way branch statement. It provides an easy way to dispatch execution to


different parts of your code based on the value of an expression. As such, it often provides
a better alternative than a large series of if-else-if statements.

The switch expression must be of type byte, short, int, or char; each of the values specified


in the case statements must be of a type compatible with or assignable to the expression.
Each case value must be a constant, not a variable. Duplicate case values are not allowed.
A break statement is used inside the switch to terminate a statement sequence. When
a break statement is encountered, execution branches to the first line of code that follows
the entire switch statement. This has the effect of jumping out of the switch.

The break statement is optional. If it is omitted, execution will continue on into the next


case. It is sometimes desirable to have multiple cases without break statements between
them.

Nested switch statements

You can use a switch as part of the statement sequence of an outer switch. Since
a switch statement defines its own block, no conflicts arise between the case constants in
the  inner switch and those in the outer switch.

The important features of switch statement:

 The switch differs from the if in that switch can test for equality, whereas if can


evaluate any type of boolean expression.
 No two case constants in the same switch can have identical values. Of course,
a switch statement enclosed by an outer switch can have case constants in common.
 A switch statement is usually more efficient than a set of nested ifs.

Write code using all forms of loops including labeled and unlabeled use of break
and continue, and state the values taken by loop control variables during and after
loop execution.

The do-while loop

This loop is especially useful when you process a menu selection, because you will usually
want the body of a menu loop to execute at least once.

The for loop variations

The three sections of the for loop can be used for any purpose you desire.

 One of the most common variations involves the conditional expression. Specifically,
this expression does not need to test the loop control variable against some target
value. In fact, the condition controlling the for loop can be any boolean expression.
 Either the initialization or the iteration expression or both can be absent. There can
be times when this type of approach makes sense. For example, if the initial
condition is set through a complex expression elsewhere in the program or if the loop
control variable changes in a non-sequential manner determined by actions that
occur within the body of the loop, it may be appropriate to leave these parts of
the for loop empty.
 You can intentionally create an infinite loop if you leave all three parts of the for loop
empty. Because, then there is no condition under which it will terminate.
Although there are some programs, such as operating system command processors, that
require an infinite loop, most infinite loops are really just loops with special termination
requirements.

The break statement

It has three uses:

 It terminates a statement sequence in a switch statement.


 It can be used to exit a loop.

By using break, you can force immediate termination of a loop, bypassing the


conditional expression and any remaining code in the body of the loop. When
a break is encountered inside a loop, the loop is terminated and program control
resumes at the next statement following the loop. When used inside a set of nested
loops, the break statement will only break out of the innermost loop. Two more
points to remember: first, more than one break statements can appear in a loop.
But, too many break statements have the tendency to de-structure your code.
Second, the break that terminates a switch statement, affects only
that switch statement and not any enclosing loops.

 It can be used as a civilized form of goto.

This statement was not developed to provide the normal means by which a loop is
terminated. The loop’s conditional expression serves that purpose. The break statement
should be used to cancel a loop only in special cases.

The break statement cannot be used to break out of an if statement.

Using break as a form of goto

Java does not support goto statement, because it provides a way to branch in an arbitrary
and unstructured manner. This usually makes goto-ridden code hard to understand and
hard to maintain. It also prohibits certain compiler optimizations. There are, however, a few
places where goto is a valuable and legitimate construct for flow control. For example, the
goto can be useful when you are exiting from a deeply nested set of loops. To handle such
situations, Java provides labeled break statement. By using this you can break out of the
one or more blocks of code. These blocks need not be part of a switch or a loop. Further,
you can specify precisely where execution will resume, because this form of break works
with a label.

When this form of break executes, control is transferred out of the named block of the code.
The labeled block of code must enclose the break statement, but it need not be the
immediately enclosing block. This means that you can use a labeled break statement to exit
from a set of nested blocks. But you cannot use break to transfer control to a block of code
that does not enclose a break statement.

A label is any valid Java identifier followed by a colon. Once you have labeled a block, you
can then use this label as the target of a break statement. Doing so causes execution to
resume at the end of the labeled block.
Keep in mind that you cannot break to any label which is not defined for an enclosing block
i.e. if the labeled block/loop does not enclose a break statement, it is not possible to
transfer control to that block.

The continue statement:

Sometimes it is useful to force an early iteration of a loop. You might want to continue
running the loop, but stop processing the remainder of the code in its body for this
particular iteration. Inwhile and do-while loops continue statement causes control to be
transferred directly to the conditional statement that controls the loop. In a for loop, control
first goes to the iteration portion of the for statement and then to the conditional
expression. For all three loops, any intermediate code is bypassed.

As with the break statement, continue may specify a label to describe which enclosing loop


to continue.

Good uses to continue are rare. One reason is that Java provides a rich set of loop
statements which fit most applications. However, for those special circumstances in which
early iteration is needed, the continue statement provides a structured way to accomplish it.

The return statement:

This is explicitly used to return from a method. It causes program control to transfer back to
the caller of the method. The return statement immediately terminates the method in which
it is executed.

class ReturnTest{
          public static void main (String [] args){
                   boolean t= true;
                   System.out.println (“Before the return.”);
                   if (t) return;
                   System.out.println (“This will not execute.”);
          }

In this program, the if (t) statement is necessary. Without it, the java compiler would flag
an “unreachable code” error, because the compiler would know that the last println()
statement would never be executed. To prevent this error, the if statement is used here to
trick the compiler for the sake of this demonstration.

In addition to these jump statements, Java supports one other way that you can change
your program’s flow of execution: through exception handling.

Write code that makes proper use of exceptions and exception handling clauses
(try, catch, finally) and declares methods and overriding methods that throw
exceptions.
An exception is an abnormal condition that arises in a code-sequence at runtime. A Java
exception is an object that describes an exceptional condition that has occurred in a piece of
code. When an exceptional condition arises, an object representing that exception is created
and thrown in the method that caused the error. That method may choose to handle the
exception itself, or pass it on. Either way, at some time, the exception is caught and
processed. Exceptions thrown by the java runtime system relate to fundamental errors that
violate the rules of Java language or the constraints of the Java execution environment.
Manually generated exceptions are typically used to report some error condition to the caller
of the method.

Program statements that are monitored for exceptions are contained within a ‘try’ block. An
exception thrown from the ‘try’ block is caught, using ‘catch’ block and handled in some
rational way. System generated exceptions are automatically thrown by the Java runtime
system. To manually throw an exception, use the keyword ‘throw’. Any exception that is
thrown out of a method must be specified as such by a ‘throws’ clause. Any code that
absolutely must be executed before a method returns is put in a ‘finally’ block.

Exception handling provides a powerful mechanism for controlling complex programs that
have many dynamic runtime characteristics. It is important to think
of try, catch and throw as clean ways to handle errors and unusual boundary conditions in
your program’s logic. Whenever a method can fail, have it throw an exception.

Java’s exception handling statements should not be considered a general mechanism for
non-local branching. If you do so, it will only confuse your code and make it hard to
maintain.

Types of Exception :

All exception types are subclasses of the class Throwable. Immediately below Throwable are
two subclasses that partition exceptions into two distinct branches. One branch is headed by
Exception. This class is used for exceptional conditions that user programs should catch.
This is also the class that you will subclass to create your own custom exception types.
There is an important subclass of Exception, called RuntimeException. Exceptions of this
type are automatically defined for the programs that you write, and include things such as
division by zero and invalid array indexing.

The other branch is topped by Error, which defines exceptions that are not expected to be
caught under normal circumstances by your programs. Exceptions of type Error are used by
Java runtime system to indicate errors having to do with the runtime environment itself.
Stack overflow is an example of such an error.

Uncaught exceptions:

Whenever an exception object is created and thrown by the runtime system, execution of
the program stops, because once an exception has been thrown, it must be caught by an
exception handler and dealt with immediately. If you do not supply any exception handlers,
the exception is caught by the default handler provided by the Java runtime system.

The default handler displays a string describing the exception, prints a stack-trace from the
point at which the exception has occurred, and terminates the program. The stack trace will
always show the sequence of method invocations that led up to the error.
Effect on a thread

If an exception is thrown and it is not handled, the execution jumps to the end of the
current method. The exception then appears in the caller of that method, and execution
jumps to the end of the calling method. This continues until execution reaches  the top of
the affected thread, at which point the thread dies.

‘try’ and ‘catch’

The default exception handler in JVM is useful for debugging. It is best to handle the
exceptions yourself. Doing so provides two benefits. First, it allows you to fix the error.
Second, it prevents the program from automatically terminating.

Once an exception is thrown, the program control transfers out of the ‘try’ block into the
‘catch’ block. Catch block is not called, so execution never returns to the try block
from catch. Once thecatch statement has executed, program control continues with the next
line in the program following the entire try/catch block.

A try and its catch statement form a unit. The scope of catch clause is restricted to those


statements specified by the immediately preceding try block. A catch statement cannot
catch an exception thrown by another try statement (except in the case of
nested try statements). The statements that are protected by ‘try’, must be enclosed within
curly braces. That is they must be within a block. You cannot use try on a single statement.

The goal of most well constructed catch blocks should be to resolve the exceptional


condition and then continue as if the error had never happened.

Multiple catch clauses:

In some cases, more than one exception could be raised by a single piece of code. To
handle this type of situation, you can specify two or more catch blocks, each catching a
different type of exception. When an exception is thrown, each catch statement is inspected
in order, and the first one whose type matches that of the exception is executed. After
one catch statement executes, the others are bypassed, and execution continues after
the try/catch block.

When you use multiple catch blocks, it is important to remember that exception subclasses


must come before any of their superclasses. This is because a catch statement that uses a
superclass will catch exceptions of that type plus any of its subclasses. Thus a subclass
would never be reached if it came after its superclass. Further, in Java, unreachable code is
an error.

Nested try statements:

Each time a try statement is entered, the context of that exception is pushed on the stack.
If an inner try statement does not have a catch handler for a particular exception, the stack
is unwound and the next try statement’s catch handlers are inspected for a match. This
continues until one of the catch statements succeeds, or until all of the
nested try statements are exhausted. If no catch statement matches, then the Java runtime
system will handle the exception.
Nesting of try statements can occur in less obvious ways when method calls are involved.
You can enclose a call to a method within a try block. Inside that method is
another try statement. In this case, the try statement within the method is still nested
inside the outer try block, which calls the method.

Displaying a description of an exception

Throwable overrides the toString() so that it returns a string containing a description of the
exception. You can display this description in a println() statement by simply passing the
exception as an argument.

finally

when exceptions are thrown, execution in a method takes a rather abrupt, non-linear path
that alters the normal flow through the method. Depending upon how the method is coded,
it is even possible for an exception to cause the method to return prematurely. This could
be a problem in some methods. For example, if a method opens a file upon entry and closes
it upon exit, you will not want the code that closes the file to be bypassed by the exception-
handling mechanism. The ‘finally’ clause creates a block of code that will be executed
whether or not an exception is thrown. If an exception is thrown, the finally block will
execute even if no catch statement matches the exception. Any time a method is about to
return to the caller from inside a try/catch block, via an uncaught exception or an
explicit return statement, the ‘finally’ clause is also executed just before the method
returns. This can be useful for closing file handles and freeing up any other resources that
might have been allocated at the beginning of a method with the intent of disposing them
before returning. The ‘finally’ clause is optional. However, each try statement requires at
least onecatch or a finally clause.

If an exception arises with a matching catch block, then the finally block is executed after


the catch block. If no exception arises, the finally block is executed after the try block. If an
exception arises for which there is no catch block, then the finally block is executed after
the try block.

The circumstances that can prevent execution of finally block are :

 The  death of the thread.


 The use of System.exit()
 Interruption of power supply to the CPU.
 An exception arising in the finally block itself.

Any exception arising in the finally block can be handled via a try-catch. If no catch is found
then control jumps out of the method from the point at which the exception is raised,
perhaps leaving the finally block incompletely executed.

Catching multiple exceptions

A catch block handles exceptions of the class specified in its definition, as well as exceptions
that are subclasses of the one specified. If you wish to catch multiple exceptions which are
related to each other by super class/ sub class relation, then the following points should be
kept in mind :
 The catch block specifying super class must come after the catch block which intends
to catch the sub class.
 Out of many catch blocks, you might have defined, only one catch block, which is the
first applicable one, will be executed.

If exceptions are not related by super-sub relation then the order of catch blocks is not
important. 

The throw statement

It is possible for a program to throw an exception explicitly using the ‘throw’ statement (e.g.
throw object;). The object to be thrown must of type Throwable or a subclass of it. Simple
types such as int or char as well as non-Throwable classes, such as String or Object, cannot
be used as exceptions. There are two ways you can obtain a Throwable object: using a
parameter into a catchclause or creating one with the ‘new’ operator.

The flow of execution stops immediately after the ‘throw’ statement; any subsequent
statements are not executed. The nearest enclosing ‘try’ statement is inspected to see if it
has a catchstatement that matches the type of the exception. If it does find a match,
control is transferred to that statement. If not, the next enclosing try statement is inspected
and so on. If no matchingcatch block is found, then default exception handler halts the
program and prints the stack trace.

All of Java’s built in runtime exceptions have two constructors: one with no parameters and
one that takes a String parameter. When the second form is used, the argument specifies a
string that describes the exception. This string is displayed when the object is used as an
argument to print() or println(). It can also be obtained by a call to getMessage(), which is
defined by Throwable.

A throw statement should be conditional in some way so that it has a way to complete


successfully.

The throws statement

If a method is capable of causing an exception that it does not handle itself, it must specify
this behavior so that the callers of the method can guard themselves against that exception.
It can be done by including a ‘throws’ clause in the method’s declaration. A throws clause
lists the types of exceptions that a method might throw. This is necessary for all exceptions,
except those of type Error or RuntimeException, or any of their subclasses. All other
exceptions that a method can throw must be declared in the ‘throws’ clause. If they are not,
a compile time error will result. If  a method declares that it throws more than one
exception, class hierarchy of exceptions is important in the declaration - subclass coming
before a super class.

Checked exceptions

The checked exceptions are problems that can arise in a correct program. These are
concerned with difficulties with the environment such as user mistakes or I/O problems.
Since these conditions can arise at anytime, a program must be able to handle and recover
from them. The compiler checks whether a program has defined what is to be done when
such conditions arise.
Exceptions and Overriding 

A method which overrides a method in a super class can only be declared to throw checked
exceptions of classes which were either declared to be thrown by the method in super class
or which are subclasses of those exceptions declared in the method of super class.

This restriction is because Java allows use of super class references as references to objects
of subclass. If an overriding method were allowed to throw exceptions of super class of
those declared for the overridden method, then overriding methods would be able to bypass
the enforced checks for checked exceptions.

Java’s built in exceptions:

Inside the standard package java.lang, Java defines several exception classes. The most
general of these are subclasses of RuntimeException. Since, java.lang is implicitly imported
to all Java programs, most exceptions derived from RuntimeException are automatically
available. They need not be included in any method’s throws list. They are called unchecked
exceptions because the compiler does not check to see if a method handles, or throws these
exceptions. Checked exceptions are those defined by java.lang that must be included in a
method’s throws list if that method can generate one of these exceptions and does not
handle it itself.

RuntimeException subclasses (unchecked):

 ArithmeticException
 ArrayIndexOutOfBoundsException
 ArrayStoreException
 ClassCastException
 IllegalArgumentException
 IllegalMonitorStateException
 IllegalStateException
 IllegalThreadStateException
 IndexOutOfBoundsException
 NegativeArraySizeException
 NullPointerException
 NumberFormatException
 SecurityException
 StringIndexOutOfBoundsException
 UnsupportedOperationException

Checked Exceptions defined in java.lang:

 ClassNotFoundException
 CloneNotSupportedException
 IllegalAccessException
 InstantiationException
 InterruptedException
 NoSuchfieldException
 NoSuchMethodException

Creating new Exception subclasses:

Although Java’s built-in exceptions handle most common errors, you may want to create
your own exception types to handle situations specific to your applications. To do this, just
define a subclass of Exception. Your subclasses do not need to implement anything actually
– it is their existence in the type system that allows you to use them as exceptions.

The Exception class does not define any methods of its own. It does inherit those methods
provided by Throwable. Thus all exceptions, including those that you create, have the
methods defined by Throwable available to them. You may also wish to override one or
more of these methods in exception classes that you create.

Methods defined in Throwable:

 Throwable fillInStackTrace ()
 String getLocalizedMessage ()
 String getMessage ()
 void printStackTrace ()
 void printStackTrace (PrintStream stream)
 void printStackTrace (Printwriter stream)
 String toString ()

Section 3 : Garbage Collection


 

 
State the behavior that is guaranteed by the garbage collection system, and write
code that explicitly makes objects eligible for collection. 
 

 
Java, they say, scores over other languages like C or C++ in memory management. In Java
you need not worry about memory management since its garbage collection mechanism 
takes care of memory leaks. When an object cannot be referenced in a program or if it
cannot be accessed anymore, maybe due to its reference being assigned to another object
or its reference being set to null, it becomes eligible for garbage collection. The built in
garbage collector mechanism then reclaims the memory which had been allocated to the
object.
The storage allocated to an object is not recovered unless it is definitely no longer in use.
Even though you may not be using an object any longer, you cannot say when, even if at
all, it will be collected. Even  methods like System.gc() and Runtime.gc() cannot be relied
upon in general, since some other thread might prevent the garbage collection thread from
running.
An important consequence of the nature of automatic garbage collection is that there can
still be memory leaks. If live, accessible references to unneeded objects are allowed to
persist in a program, then those objects cannot be garbage collected. Therefore it is better
to explicitly assign null to a variable when it is not needed any more. This is particularly
important when implementing a collection.
 
Object lifetime
 
The lifetime of an object is from the time it is created to the time it is garbage collected. The
finalization mechanism does provide a means for resurrecting an object after it is no longer
in use and eligible for garbage collection, but finalization is rarely used for this purpose.
 
Cleaning up
 
Objects that are created and accessed by local references in a method are eligible for
garbage collection when the method terminates, unless references to those objects are
exported out of the method. This can occur if a reference is returned or thrown as an
exception.
 
Object finalization
 
protected void finalize() throws Throwable;
 
A finalizer can be overridden in a method in a subclass to take appropriate action before the
object is destroyed. A finalizer can catch and throw exceptions like other methods. However,
any exception thrown but not caught by a finalizer when invoked by the garbage collector is
ignored. The finalizer is only called once on an object, regardless of being interrupted by
any exception during its execution. In case of finalization failures the object  still remains
eligible for garbage collection at the discretion of garbage collector unless it has been
resurrected.
 
Finalizer chaining
 
Finalizers are not implicitly chained like constructors for subclasses, therefore a finalizer in a
subclass should explicitly call super class finalizers as its last action.
 
A finalize method may make the object accessible again, thus avoiding it being garbage
collected. One simple technique is to assign its this reference to a static variable, from
which it can later be retrieved. Since a finalizer is called only once on an object, an object
can be resurrected only once.
 
finalize () method:
 
Sometimes an object will need to perform some action when it is destroyed by the garbage
collector. For example, if an object is holding some non java resources such as a file handle
or window character font, then you might want to make sure these resources are freed
before an object is destroyed. By using finalization, you can define specific actions that will
occur when an object is just about to be reclaimed by the garbage collector. To add a
finalizer to a class, you simply define a finalize() method. This method has the general
form:
 
                   protected void finalize ();
 
You might find that the storage for an object never gets released because your program
never nears the point of running out of storage. If your program completes and the garbage
collector never gets around to releasing the storage for any of your objects, that storage will
be returned to the operating system en masse as the program exits. This is a good thing,
because garbage collection has some overhead, and if you never do it you never incur that
expense.

Finalizers are guaranteed to be called before the memory used by an object is reclaimed.
However there is no guarantee that any memory will ever be reclaimed. Hence there is no
guarantee that finalize( ) will ever be called. There is a promise that barring catastrophic
error conditions, all finalizers will be run on leftover objects when the Java virtual machine
exits. However this is likely too late if your program is waiting for a file handle to be
released. Besides it is not convincing that it happens anyway. Therefore it is vital that you
never rely on a finalizer to free finite resource, such as file handles, that may be needed late
by your program.
 

Section 4 : Language Fundamentals


 
 

 
Identify correctly constructed source files, package declarations, import
statements, class declarations (of all forms including inner classes), interface
declarations and implementations (for java.lang.Runnable or other interface
described in the test), method declarations (including the main method that is
used to start execution of a class), variable declarations and identifiers.
 

Source Files

A source file should generally contain at most one top level public class definition. If a public
class is present, the class name should match the unextended file name. A source file may
contain an unlimited number of non public class definitions.

This is not a language requirement, but an implementation requirement of many compilers


including the reference compilers from sun. It is therefore unwise to ignore this convention
since doing so limits the portability of your source files ( but not, of course, your object
files).

There are 3 top level elements that may or may not appear in a file. If they are present
then the order must be

 package declaration
 import statements
 class definitions
White spaces and comments may appear before or after any of these elements. 

Keywords and Identifiers 

Keywords and reserved words may not be used as identifiers. An identifier must begin with
a letter, a dollar sign ($), an underscore ( _ ) or digits. You can use embedded keywords.

main method 

This method is declared public by convention. However it is a requirement that it


be static so that it may be executed without the necessity of constructing an instance of the
corresponding class.Its return type must be void. These conditions are necessary because
when a Java program starts running, JVM looks for this method as the code to start
execution of the program is placed in this method only.

Variables and Initialization

In Java, variables have two different lifetimes :

 A member variable of a class is created when the instance is created and is


accessible from any method in the class.
 A local variable of a method is created on entry to the method, exists only during
execution of the method, and is accessible only within the method.

A member variable may be initialized in its own declaration line : when this technique is
used, non-static instance variables are initialized just before the class constructor is
executed. Static variables are initialized at class load time.

Local variables are not initialized by the system – every such variable must be explicitly
initialized before being used.

Section 4 : Language Fundamentals


 
 

 
State the correspondence between index values in the argument array passed to a
main method and command line arguments. Identify all Java Programming
Language keywords and correctly constructed identifiers.
 

 
Command line arguments and the main () method :
 
Whatever arguments are passed as command line arguments while executing a Java
program are placed in the String [] array parameter of the main method. When there are no
arguments, the String array is an empty array. If you pass a single argument, it is placed at
the array index 0. So, args[0] corresponds to this argument. Thus the number of arguments
becomes the length of the array and the arguments are accessed in the program in the
usual way of accessing elements of an array.
 
Java keywords :
 
 
abstract double int strictfp
boolean else interface super
break extends long switch
byte final native synchronized
case finally new this
catch float package throw
char for private throws
class goto protected transient
const if public try
continue implements return void
default import short volatile
do instanceOf static while
 
Apart from these 48 keywords, there are three more words : null, true and false. Many
authors list these words as keywords too. But, Java Language Specification says that these
are not keywords but literals.

State the effect of using a variable or array element of any kind when no explicit
assignment has been made to it.

All the instance and static variables of a class are automatically initialized to their default
values before use even if there has not been explicit assignment to them. This is, however,
not true for local variables ( variables declared inside a method ). As a result of this, when
you try to use a variable without initializing it first, you get their default value. For example,
an int variable will be initialized to zero, float will be initialized to 0.0, a boolean will be
initialized to false and so on. A reference variable gets initialized to null by default. In case
of a local variable, however, your code will not compile if you do not initialize the variable
before trying to use it.

All the elements of an array get initialized to their default values, whether the array is an
instance or static member of a class, or a local variable of a method. If you try to use an
array before initializing it, the compiler will not complain. But you will get a
NullPointerException at the runtime, as the array itself will get initialized to null value
automatically. If you do initialize the array by using new operator, you will not get this
exception at runtime. However, if you have not initialized its elements, all you will get is the
default values of its elements.

Section 4 : Language Fundamentals


 
 
State the range of all primitive data types and declare literal values for String and
all primitive types using all permitted formats, bases, and representations.
 

 
Primitive data types

The char type ( 16 bit ) is integral but unsigned. If the most significant nine bits of
a char are all zero, then the encoding is same as seven bit ASCII. 

Range of primitive types

Data
Width Min. Value  Max. Value
Type 

byte 8 -128 127

short 16 -32,768 32767

int 32 -2,147,483,648 2,147,483,647

long 64 -9,223,372,036,854,775,808 9,223,372,036,854,775,807

char 16 0x0 (Unicode value) 0xffff (Unicode value)

float 32 1.4012984643248170e-45 3.40282346638528860e+38

4.94065645841246544e-
double 64 1.79769313486231570e+308
324

Literals 

char literals : A literal representing a character is placed in single quotes e.g. 'c'.

Integer literals : Any integer literal defaults to int. To represent a long value, the numerical
expression must contain either L or l as suffix.

Floating point literals : In order to be interpreted as a floating point literal a numerical


expression must contain one of the following :

 A decimal point.
 The letter E or e : 55.21 E
 The suffix F or f for float
 The suffix D or d for double
A floating point literal with no F or D suffix defaults to a 64 bit double literal. 

String Literals
 
String literals are represented in double quotes e.g. " Java ".
 

Section 5 : Operators and Assignments

Determine the result of applying any operator, including assignment operators,


instanceof, and casts to operands of any type, class, scope, or accessibility, or any
combination of these.

Evaluation Order  

All operands are evaluated left to right, even if the order of execution of the operations is
something different. This is most noticeable in the case of assignments. For assignments,
associativity is right to left.

Unary Operators

Increment/Decrement operators : Both x++ and ++x cause the same result in x. However,
the apparent value of the expression itself is different.

Arithmetic operators 

Division and Multiplication

If you multiply first and then divide there is a risk of overflow. Dividing first and then
multiplying almost definitely loses precision. It is better to multiply first, because it at least
might work perfectly if the representation is long enough. 

Modulo ( % )

If you use negative operands the result’s sign is entirely determined by the sign of the left
hand operand. Simply drop any negative sign from either operand and calculate the result.
Then if the original left hand operand was negative, negate the result. The sign of the right
operand is irrelevant.

When the modulo operator is applied to floating point types the result might well have a
fractional part.

This operator can throw Arithmetic Exception if applied to integral types and the second
operand is zero. 
NaN

Float.NaN and Double.NaN  are considered to be non-ordinal for comparisons i.e. for any
value of x, including NaN itself any comparison with NaN will return false.

In fact, Float.NaN != Float.NaN will return true.

The most appropriate way to test for a NaN result from a calculation is to
use static methods like Float.isNaN(float) or Double.isNaN(double).

The shift operators

These can be applied to arguments of integral types only. In fact, they should generally be
applied to only operands of either int or long types.

The left shift <<  

This moves all of the bits in the specified value to the left by the number of bit positions
specified by num. For each shift left, the high order bit is lost and a zero is brought in on
the right. This means that when a left shift is applied to an int operand, bits are lost
once they are shifted past bit position 31. If the operand is ‘long’ then bits are lost after
bit position 63.
Java’s automatic type promotions produce unexpected results when you are
shifting byte or short values. These values are promoted to int when an expression is
evaluated and the result is alsoint. This means that the outcome of a left shift on
a byte or short value will be an int, and the bits are not lost until they are past position
31. Furthermore, a negative byte or short will be sign-extended when it is promoted
to int. Thus, the high order bits will be filled with 1s. For these reasons, to perform a left
shift on a byte or short implies that you must discard the high order bytes of
the int result. The easiest way to do this is to simply cast the result back to
a byte or short.

Each left shift has the effect of doubling the original value. But, if you shift a 1 bit into a
high order position (31 or 63) the value will become negative. 

The right shift >> 


Each time you shift a value to the right, it divides that value by two and discards the
remainder. You can take advantage of this for high performance integer division by 2. Of
course, you must be aware that you are not shifting any bits off the right end.

When you are shifting right, the top bits exposed by the right shift are filled in with the
previous contents of the top bit. This is called sign-extension and serves to preserve the
sign of negative numbers.
There is a feature of the arithmetic right shift that differs from simple division by two. If
you divide –1 by 2, the result will be zero. However, it is interesting to note that if you
shift –1 right, the result is always –1. the result of right shift operator applied to –1 is –
1.
There is a feature of the arithmetic right shift that differs from simple division by two. If you
divide –1 by 2, the result will be zero. However, the result of right shift operator applied to
–1 is –1.

Arithmetic promotion of operands

Arithmetic promotion of operands takes place before any binary operator is applied so that
all numeric operands are at least int type. This has an important consequence for the
unsigned right shift operator when applied to values that are narrower than int. Take
a byte for example. First it is promoted to int, which is done treating the byte as a signed
quantity. Next, the shift occurs, and zero bits are propagated into the top bits of the result –
but these bits are not part of the original byte. When the result is cast down to a byte again,
the high order bits of that byte appear to have been created by a signed shift ( >> ), rather
than an unsigned one.

This is why logical right shift operator generally should not be used with operands smaller
than an int. It is unlikely to produce a result one expects.

The unsigned right shift (>>>) :


The >> operator automatically fills up the high order bit with it previous contents each
time a shift occurs. This preserves the sign of the value. However, sometimes it is
undesirable. For example, if you are shifting something that does not represent a
numeric value, you may not want sign extension to take place. This situation is common
when you are working with pixel based values and graphics. In such cases, you want to
substitute the high order bit with zero, no matter what the initial value was. In such
cases use unsigned shift.

The >>> operator is only meaningful for 32 and 64 bit values. Remember, smaller values
are automatically promoted to int in expressions. This means that sign extension occurs and
that shift will take place in a 32 bit rather than 8 or 16 bit value. That is one might expect
an unsigned right shift on a byte value to zero fill beginning at bit 7. But this is not the case
since it is a 32 bit value that is actually shifted.

The comparison/Relational operators

These operators return a boolean result. There are three types of comparison. Ordinal
comparisons test the relative value of numeric operands. Object type comparisons
determine if the runtime type of an object is of a particular type or a subclass of that
particular type. Equality comparisons test if two values are the same and may be applied to
values of non-numeric type.

Ordinal comparisons with <,<=,>,>=

These are applicable to all numeric types and to char and produce a boolean result.
Arithmetic promotions are applied when these operators are used. Although it would be an
error to assign, say, a float value to a char, it is perfectly in order to compare the two. In
this case char is promoted to float and then compared.

instanceof operator
This is used to test the class of an object at runtime. The left hand operand can be any
object reference expression, usually a variable or an array element, while the right hand
operand must be a class, interface or array type. Java.lang.Class object or its string name
cannot be used as right hand operand.

This operator can also be used to test whether a reference refers to an array. Since arrays
are themselves objects in Java, this is natural enough, but the test actually checks two
things : First it will check if the object is an array and then it will check if the element type
of that array is some subclass of the element type of the right hand operand.

If the left hand operand is a null value, this operator simply returns false. It does not cause
an exception.

Equality comparison operators ( == and != )

For variables of object type, these operators compare the references themselves rather than
the contents of the objects. To achieve a content or semantic comparison, one should use
equals() method. To function properly, the equals() method must have been defined for the
class of the objects being compared. If it is not, then equals() too behaves like == operator.

For x.equals(y) the test y instanceof x must be true. If this is not the case, then equals()
must return false.

If you define equals() in your own classes, you should be careful to observe two rules: 1.
First the argument to the equals() method is an object. You must avoid the temptation to
make the argument specific to your own class you are defining. If you do this, you have
overloaded this method, not overridden it. This means that functionality in the other parts
of the Java API that depends on the equals() method will fail. Most significantly, perhaps,
lookup methods in containers, such as containsKey() and get() in the HashMap, will fail. 2.
The second rule you must observe is that if you define an equals() method, you should also
define a hashCode() method. This method should return the same value for objects that
compare equal using the equals() method. Again, this behavior is needed to support the
containers, and other classes.

The bitwise operators : &, ^, and |

These operators manipulate the bits within an integer. All the integer types are
represented by binary numbers of varying bit widths. Java uses an encoding known as
two’s complement, which means that negative numbers are represented by inverting all
of the bits in a value, then adding 1 to the result. For example, 

42 = 00101010
-42 = (11010101) +1 = 11010110 

This addition of 1 is applied even when changing negative to positive.


The reason Java ( and most other languages ) uses two’s complement is easy to see
when you consider the issue of zero crossing. Assuming a byte value, zero is 0000 0000.
in one’s complement, simply inverting all the bits gives 1111 1111 which creates
negative zero. The trouble is that negative zero is invalid in integer math. This problem
is solved by using two’s complement to represent negative values. When using two’s
complement, 1 is added to the complement, producing 1 0000 0000. This produces a 1
bit too far to the left to fit back into the byte value, resulting in the desired behavior,
where negative zero is same as 0, and 1111 1111 is the encoding for –1.
Because Java uses two’s complement to store negative numbers - and because all
integers are signed values in Java – applying bitwise operators can easily produce
unexpected results. For example, turning on the high order bit will cause the resulting
value to be interpreted as a negative number, whether this is what you intended or not.
To avoid unpleasant surprises, just remember that the high order bit determines the
sign of an integer no matter how that high order bit gets set. 

Collections of bits are sometimes used to save storage space where several boolean values
are needed or to represent the states of a collection of binary inputs from physical devices.

These operators are applicable to integral types. Collections of bits are sometimes used to
save storage space where several boolean values are needed or to represent the states of a
collection of binary inputs from physical devices.

The bitwise operators calculate each bit of their results by comparing the corresponding bits
of the two operands on the basis of these three rules :

 For AND operators, 1&1 produces 1. Else zero.

 For XOR, 1^0 produces 1 as does 0^1. Else zero.

 For |,  0|0 produces 0. Else 1.

It is also permitted to apply these operators to boolean operands.

The short circuit logical operators : && and ||

These are applicable to only on boolean types, and not integral types. Although these
shortcuts do not affect the result of the operation, side effects might well be changed. If the
evaluation of the right hand operand involves a side effect, then omitting the evaluation will
change the overall meaning of the expression. This behavior distinguishes these operators
from the bitwise operators applied to boolean types.

The ternary operator    ?:

This operator provides a way to code simple if-else conditions into a single expression. The
(boolean) expression left of the ? is evaluated. If true, the result of the whole expression is
the value of the sub-expression to the left of the colon, otherwise it is the value of the sub-
expression to the right of the colon. The sub-expressions on either side of the colon must be
of the same type.

Determine the result of applying any operator, including assignment operators,


instanceof, and casts to operands of any type, class, scope, or accessibility, or any
combination of these.
 
 
Converting and Casting 
 
 
Automatic, non-explicit (done by compiler or Java) type changing is known as conversion.
On the other hand explicitly changing the type of a value is called casting. Both are
governed by certain rules. 
 
Primitives and conversion 
 
All conversion of primitive data type takes place at compile time. This is because all the
information, needed to determine whether or not conversion is legal, is available at compile
time.
 
Assignment
 
Assignment conversion happens when you assign a value to a variable of a different type
from the original value. The general rules are:
 
 A boolean may not be converted to any other type.
 A non boolean may be converted to another non boolean type, provided the
conversion is a widening conversion.
 A non boolean may not be converted to another non boolean type, if the conversion
is narrowing.
 
You cannot convert a byte to a char or a char to a short, even though it seems reasonable
to do so.
 
Method call: 
 
Another kind of conversion is method-call-conversion. This happens when you pass a value
of one type as an argument to a method that expects a different type. Here too, widening
conversions are permitted, not narrowing.  
 
Arithmetic promotion:
 
These too, are widening conversions.
 
Unary operators:
 
 If the operand is a byte, a short or a char, it is converted to an int.
 If the operand is of any other type, it is not converted.
 
Binary operators:
 
 If one of the operands is double, the other operand is converted to a double.
 Else if one of the operand is a float, the other operand is converted to a float.
 Else if one of the operand is long, the other operand is converted to a long.
 Else both operands are converted to int.
 
Primitives and casting 
 
Casting means explicitly telling Java to make a conversion. A casting may widen or narrow
its argument. But casting is required when you want to perform a narrowing conversion.
Narrowing runs the risk of losing information; the cast tells the compiler that you accept the
risk. During casting the lower order bits are preserved and higher order bits are discarded
depending on the operands. The rules are:
 
 Any non  boolean can be cast to any non boolean.
 A boolean cannot be cast to a non boolean and vice versa.
 
Note that while casting is ordinarily used when narrowing, it is perfectly legal to cast when
widening. The cast is unnecessary, but provides clarity.
 
*** if you cast a negative number to a char, ? is printed in S.o.p(); also any number less
than 0 and greater than 255 gives the same output.
 
Object reference conversion 
 
Reference conversion, like primitive conversion, takes place at compile time, because the
compiler has all the information it needs to determine whether the conversion is legal.
 
Object reference assignment conversion: 
 
There are generally three kinds of object reference type:
 A class type
 An interface type
 An array type
Assignment conversion looks like this:
 
OldType x = new OldType();
NewType y = x; // reference assignment conversion.
 
In general, object reference conversion is permitted when the direction of the conversion is
‘up’ the inheritance hierarchy; that is old type should inherit from the new type. The rules
are:
 An interface type may only be converted to an interface type or to Object. If the new
type is an interface, it must be a super interface of the old type.
 A class type may be converted to a class type or to an interface type. If converting
to a class type, the new type must be a superclass of the old type. If converting to
an interface type, the old type must implement the interface.
 An array may be converted to the class Object, to the interface Cloneable, or to an
array. Only an array of object reference types may be converted to an array, and the
old element type must be convertible to the new element type.
 
 
  OldType is a OldType is OldType is an array
class an interface
OldType must NewType
NewType is
a class
be a subclass must be NewType must be Object
of NewType. Object
OldType must OldType
NewType
implement must be a NewType must be
is an
interface sub-interface Cloneable/Serializable
interface
NewType of NewType
OldType must be an array of
NewType Compiler Compiler some object reference type that
is an array Error Error can be converted to whatever
NewType is an array of.
 
 
Object method call conversion:  Rules are same as above.
 
To see how the rules make sense in the context of method calls, consider the extremely
useful Vector class. You can store anything you like in a Vector (anything non-primitive) by
calling the method
 
          addObject (Object ob);
 
whatever you pass to the above method, will be converted to Object. The automatic
conversion means that the people who wrote the Vector class did not have to write a
separate method for every possible type of object that anyone might conceivably want to
store in a Vector.
 
Object reference casting:
 
Object reference casting is like primitive-casting: by using a cast, you convince the compiler
to let you do a conversion that otherwise might not be allowed.
 
Any kind of conversion that is allowed for assignments or method calls is allowed for explicit
casting, though it is not needed (done by compiler implicitly). The power of casting appears
when you explicitly cast to a type that is not allowed by the rules of implicit conversion.
 
It is important to understand the difference between objects and object reference variables.
Every object (almost) is constructed via the ‘new’ operator. The argument to the ‘new’
determines for all time the true class of the object. Java programs do not deal directly with
the objects but with references to objects. The objects themselves live in memory
somewhere in JVM. The reference variable contains something similar to the address of the
object. This address is known as reference to the object. References are stored in variables,
and variables have types that are specified by the programmer at compile time.
 
While an object’s class is unchanging, it may be referenced by variable of many different
types.
 
The type of a reference variable is obvious at compile time. However, the class of an object
referenced by such a variable cannot be known until runtime. This lack of knowledge is not
a shortcoming of Java: it results from a fundamental principle of computer science.
 
The rules for casting are a bit broader than those for conversion. Some of these rules
concern reference type and can be enforced by the compiler at compile time. Other rules
concern object class and can only be enforced during runtime. The table below
demonstrates compile time rules.
 
  OldType is OldType is a OldType is OldType is an
a non-final final class an interface array
class
NewType OldType OldType must Always OK NewType must
is a non- must extend extend be Object
final class NewType or NewType
vice versa
NewType NewType OldType and NewType Compiler Error
is a final must extend NewType must
class OldType must be the implement
same class interface
OldType
NewType Always OK OldType must Almost OldType must be
is an implement always OK Object
interface interface
NewType
NewType OldType Compiler Compiler OldType must be
is an array must be error Error an array of some
Object type that can be
cast to whatever
NewType is an
array of.
 
Assuming that a desired cast survives compilation, a second check must occur at runtime.
The second check determines whether the class of the object being cast is compatible with
the new type.
 
Compile time rules:
 
1. When both OldType and NewType are classes, one must be a subclass of the other.
2. When both are arrays, both arrays must contain reference types, and it must be
legal to cast an element of OldType to an element of NewType.
3. You can always cast between an interface and a non-final object.
 
Runtime rules:
 
Remember that the conversion to NewType must actually be possible.
1. If NewType is a class, the class of the expression being converted must be NewType
or must inherit from NewType.
2. If NewType is an interface, the class of the expression being converted must
implement NewType.
 
Determine the result of applying the boolean equals (Object) method to objects of
any combination of the classes java.lang.String, java.lang.Boolean, and
java.lang.Object.

The equals method defined in class Object returns true if and only if x and y refer to the
same object in the following expression:

            x.equals (y);

In case of equals method defined in Boolean class it returns true only and only if the
argument is not null and is a Boolean object that represents the same value as this object.

In case of String class, this method returns true if and only if the argument is not null and is
a String object that represents the same sequence of characters as this object.

For any non-null reference value x, x.equals(null) will always return false.

 
In an expression involving the operators &, |, &&, ||, and variables of known
values state which operands are evaluated and the value of the expression.

 
Let us take an expression :
 
            (expression1 op expression2);
 
where op is any one of the above operators and the two operands are boolean expressions.
 
The operators && and || are known as short cut logical operators. In the above expression,
if op is one of these operators then there may be instances when only the first expression
will be evaluated and not the second expression. If the evaluation of the first expression
itself determines the result of the overall expression, then the second or right hand
expression will not be evaluated.
 
For example, if the operator is && and if the first expression evaluates to false, then it is
clear that whatever the result of evaluating the right hand expression, the overall
expression will evaluate to false only. In such cases, there is no need to evaluate the second
expression. But, if the first expression evaluates to true, then the overall result of the
complete expression will depend on the second expression. In such cases, the second
expression will be evaluated.
 
Operators & and | always evaluate both the operands.

 
Determine the effect upon objects and primitive values of passing variables into
methods and performing assignments or other modifying operations in that
method.

Argument passing:

Call by value: 

This method copies the value of an argument into the formal parameter of the sub-routine.
Therefore, changes made to the parameter of the sub-routine have no effect on the
argument used to call it. In Java when a simple type is passed, it is passed by value.

Call by reference:

In this method, a reference to an argument (not the value of the argument) is passed to the
parameter. Inside the sub-routine, this reference is used to access the actual argument
specified in the call. So, the changes made to the parameter will affect the argument used
to call the sub-routine. When you pass an object to a method, it is passed by reference.

When an object reference is passed to a method, the reference itself is passed by value.
However, since the value being passed refers to an object, the copy of that value will still
refer to the same object that its corresponding argument does.

Objects as parameters:

One of the most common uses of object parameters involve constructors. Frequently you
will want to construct a new object which is initially the same as some existing object. To do
this you must define a constructor that takes an object of its class as a parameter. You will
also require this when you want to initialize an object of a class with an object of another
class (possibly of super class).

Section 6 :  Overloading, Overriding, Runtime


Type, and Object Orientation 
State the benefits of encapsulation in object oriented design and write code that
implements tightly encapsulated classes and the relationships "is a" and "has a".
Benefits of Object oriented implementation 

These benefits accrue from two particular features. The first of these and perhaps the most
important is the notion of abstract data type. The second of these is the extensibility
provided by inheritance. 

Abstract data type 

An abstract data type simply means a well encapsulated aggregate of data and behavior.
The primitive data types defined in any programming language are in fact abstract data
types, albeit not user defined. The state of an object should be represented only with
variables of private accessibility. All behavior should be accessed only via methods. By
insisting that the variables inside an object are not accessible outside the object, you ensure
that the nature of those variables is irrelevant outside the object. This in turn means that
you can change the nature of the storage, for maintenance purposes, for performance
improvement, or for any other reason freely. This freedom is one of the greatest benefits of
encapsulation.

Inheritance:  For this please see the next section on overloading and overriding.

"is a" and "has a"

An object can perform many functions and may contain different types of data. The source
of these data and behavior may come from two sources. The first source is from inheritance
from its parent classes and the other source is any object it may contain as its state.

Each class in Java, except Object class, is a subclass of another. In any class hierarchy, any
class can be called by the name of any class which is above it in the hierarchy. Let us
consider a class called Vehicle. One of its subclasses can be called Car. Cars can of different
models like Ford or Mercedes. Now any Ford can be called a Car. It is also a vehicle. This
relationship is known as "is a" relationship.

A car has many components, each of which can belong to a different hierarchy of classes.
For example, let us consider brakes. Brakes can be of different types (classes). There can
be a whole hierarchy of brakes. Since a car has brakes, this relationship is known as "has a"
relationship.

 
 

 
Write code to invoke overridden or overloaded methods and parental or
overloaded constructors; and describe the effect of invoking these methods.
 
 
Overloading

Method overloading is one of the ways that java implements polymorphism. When an
overloaded method is called, java uses the type and/or number of arguments to decide
which version of the overloaded method to actually call. Overloaded methods may or may
not have different return types. When java encounters a call to an overloaded method, it
simply executes the version of the method whose parameters match the arguments used in
the call.

However, this match need not always be exact. In some cases java’s automatic type
conversions can play a role in overload resolution. Java will employ its automatic type
conversion only if no exact match is found.

The important points to note:


 A difference in return type only is not sufficient to constitute an overload and
is illegal.
 You should restrict your use of overloaded method names to situations where
the methods really are performing the same basic function with different
data.
 The language treats methods with overloaded names as totally different
methods and as such they can have different return types. However, since
overloaded methods perform the same job with different data sets, they
should produce same return type normally. There is one particular condition,
however, under which it is sensible to define different return types. This is the
situation where the return type is derived from the argument type and is
exactly parallel with the arithmetic operators.
 Overloaded methods may call one another simply by providing a normal
method call with an appropriately formed argument list. 
 
Overriding 
 

In a class hierarchy, when a method in a subclass has the same name and type signature as
a method in its superclass, then the method in the subclass is said to override the method
in the superclass. When an overridden method is called from within a subclass, it will always
refer to the version of that method defined by the subclass. The version in the superclass
will be hidden. If you wish to access the superclass’ version of an overridden method, you
can do so by using ‘super’. 

 
In order for any particular method to override another correctly :

 The return type, method name, type and order of arguments must be
identical to those of a method in a parent class.
 The accessibility must not be more restrictive than original method.
 
The method must not throw checked exceptions of classes that are not possible for the
original method.
 
Parental Constructors:

Whenever a subclass needs to refer to its immediate superclass, it can do so by use of the
keyword ‘super’. This keyword has two general forms. The first calls the superclass
constructor. The second is used to access a member of the superclass that has been hidden
by a member of a subclass.  

1. Constructor call: The call to the superclass’ constructor must always be the first
statement executed inside a subclass’ constructor.

2. The second form of ‘super’ acts like ‘this’, except that it always refers to the
superclass of the subclass in which it is used (e.g. super.member). This form of
super is most applicable to situations in which member names of a subclass hide
members by the same name in the superclass.

In a class hierarchy, constructors are called in order of derivation from superclass to


subclass. Further, since super () must be the first statement executed in a subclass’
constructor, this order is the same whether or not super () is used. If super () is not used,
then the default or no-arguments constructor of each superclass will be executed. This is
because a superclass has no knowledge of any subclass, any initialization it needs to
perform is separate from and possibly prerequisite to any initialization performed by the
subclass. Therefore it must be executed first.

Overloaded Constructors:

These behave as overloaded methods.

Write code to construct instances of any concrete class including normal top level
classes, inner classes, static inner classes, and anonymous inner classes.
 

Inner classes 

The mechanism of inner classes relates to scope and access, particularly access to variables
in enclosing scopes. If a class is nested inside another, the two classes’ full names are
OuterOne and OuterOne.InnerOne This format is similar to a class called InnerOne in a
package called OuterOne. But it is illegal for a package and a class to have same name, so
there can be no ambiguity. Although the format OuterOne.InnerOne works for the
declaration of the type of an identifier, it does not reflect the real name of the class which is
OuterOne$InnerOne on the disk and from the point of view of the Class class and class
loaders. So if you try to load this class (OuterOne.InnerOne) using the Class.forName()
method, the call will fail. The dollar separated name is also used if you print out the class
name using methods getClass().getName() on an instance of the inner class. 

The enclosing this reference and construction of inner class 

When an instance of an inner class is created, there must be normally a preexisting instance
of the outer class acting as context. This instance of outer class will be accessible from the
inner object. The accessibility of the members of the outer class is crucial and very useful. It
is possible because the inner class actually has a hidden reference to the outer class
instance that was the current context when the inner class object was created. In effect this
ensures that the inner class and the outer class belong together, rather than the inner class
instance being just another member of the outer instance. 

Sometimes you might want to create an instance of  an inner class from a static method, or
in some other situation where there is no ‘this’ object available. This situation arises in a
main() method or if you need to create the inner class from a method of some object of an
unrelated class. You can achieve this by using the new operator as though it were a
member method of the outer class. Of course, you still must have an instance of the outer
class. 

OuterOne.InnerOne i=new OuterOne.new InnerOne(); 

If you attempt to use the new operator to construct an inner object without a preexisting


reference to an outer object, then the implied prefix ‘this’ is assumed. Since an instance of
inner class must be created in context of an instance of the enclosing class, it follows that
inner classes cannot have static members. Multiple objects of the inner classes can be
associated with an object of an enclosing class at runtime. Though an implicit reference to
the enclosing object is always available in every method and constructor of an inner class, it
is possible to explicitly refer to the members in enclosing class, but this requires special
usage of ‘this’ reference. 

InnerOne () {this.string = OuterOne.this.msg;} 

This use of ‘this’ construct is useful in cases where inner class members’ names are same as
names of members of outer class. 

Inheritance in inner classes 

Inner classes can extend other classes and can themselves be extended. Therefore
inheritance and containment hierarchy both must be considered when dealing with member
access. In cases where the outer class and the class which inner class extends have
members with same name, ambiguity arises because members of both can be accessed
from the inner class. In such cases, the standard form of ‘this’ can be used to access
members which are inherited. The keyword ‘super’ would be another alternative. To access
the members from the enclosing context, the special form of ‘this’ together with the
enclosing class name should be used. 
Static inner class or interface 

A static inner class does not have any reference to an enclosing object ( like, inside
a static method there is no this reference ). Because of this methods of static inner class
cannot access instance variables of the enclosing class. The net result is that a static inner
class is really just a top level class with a modified naming scheme. In fact, you can
use static inner classes as an extension to packaging. It can be instantiated without any
reference to any instance of the enclosing class. 

Interfaces are implicitly static. Nested interfaces can optionally be prefixed with static and


have public accessibility. There are no non static inner, local or anonymous interfaces.

The full name of a static nested class or interface includes the name of the enclosing class.
A nested class cannot have the same name as an enclosing class or package. 

A static inner class can define both static and non static members, but its code can only
directly access static member of enclosing class. Such classes can have any accessibility. 

Classes defined inside methods( local classes) 

A local class cannot be specified ‘static’. However, if the context is static, then the local
class is implicitly static, otherwise, it is non static. Like an inner class, an instance of a
non static local class is passed a hidden reference designating an instance of its enclosing
class in its constructors, and this gives it much of the same capacity as non static inner
classes. There are some restrictions:

 Local classes cannot have static members.


 They cannot have any access modifiers. This applies to local variables, and is also
enforced for local classes.

Two particular aspects should be considered. First, an object created from an inner class
within a method can have access to variables of the enclosing method. Second, it is possible
to create an anonymous class. 

Any variable, either a local variable or a formal parameter ( of the method ) can be
accessed by methods within an inner class, provided that variable is marked final.
A final variable is effectively a constant, so this is perhaps a quite severe restriction, but the
point is simply this : an object created inside a method is likely to outlive the method
invocation. Since local variables and method arguments are conventionally destroyed when
their method exits, these variables would be invalid for access by inner class methods after
the enclosing method exits. By allowing access only tofinal variables, it becomes possible to
copy the values of those variables into the object itself, thereby extending their lifetime. The
other possible approaches to this problem would be to writing to two copies of the same
data every time it got changed or putting local variables onto the heap instead of the stack.
Either of these approaches would significantly degrade performance. 
Access rules for local classes

 Can access members defined within the class.


 Can access final local variables, final method parameters and final catch block
parameters in the scope of the local context. Such final variables are also read only in the
local class.
 A non static local class can access members defined in enclosing class. However,
a static local class can only access static member of enclosing class, but not
non static members.
 A non static local class can directly access members inherited by the enclosing class.
However, a static local class can only directly access static members inherited by the
enclosing class.
 A local class can access members inherited from its super class in the usual way.

 Instantiating local classes 

Classes outside the context of a local class cannot access or create these classes directly,
because after all they are local. A local class can be instantiated in the block in which it is
defined. A method can return an instance of the local class. The local class type must them
be assignable to the return type of the method. It cannot be the same as the local class
type, since this type is not accessible outside of the method. Often a super type of the local
class is specified as the return type. 

Creation of an object of non static local class requires an instance of the enclosing context.


An instance of a static local class can be created by invoking either the class name or
through an instance of the class, but no ‘this’ is passed in its constructor, as no outer object
is involved.

As references to a local class cannot be declared outside of the local context, the
functionality of the local class is only available through super type references.  

Anonymous classes (defined in a method) 

You cannot use new in the usual way to create an instance of an anonymous class since you
do not know its name. Anonymous classes should be small. If the class has methods other
than those of a simple, well known interface such as an AWT event listener, it probably
should not be anonymous.  

Similarly, if the class has methods containing more than one or two lines of straightforward
code, it probably should not be anonymous. The point here is that if you do not give the
class a name, you have only the self documenting nature of the code itself to explain what it
is for. 

 An anonymous class cannot have a constructor.


 An anonymous class can be a subclass of another explicit class, or it can
implement a single explicit interface. It cannot do both.
 If an anonymous class extends an existing class, rather than implementing
an interface, then arguments for the super class constructor may be placed in
the argument part of the newexpression, like this :          new button
(“Press Me”){// some code};
 For anonymous classes implementing interfaces the parent class is Object,
constructor for which takes no arguments, so it is impossible to use any
arguments in the new part for these classes.

Since an anonymous class cannot define a constructor, an instance initializer can be used to
achieve the same effect as a constructor.  No ‘extends’ clause is used in the construct.
 
As references to such a class cannot be declared, the functionality of the class is only
available through super class references.
 
An anonymous class can provide a single interface implementation and no arguments are
passed. The anonymous class implicitly extends Object class. No implements clause is used
in the construct.
 
Like local classes, anonymous classes cannot have static members, and they cannot specify
any accessibility modifiers.

Threads
 

 
Write code to define, instantiate, and start new threads using both
java.lang.Thread and java.lang.Runnable.
 

 
A thread is an object of type Thread, defined in java.lang package. Multi-threading
functionality in Java is supported in four places:
 Thread class
 Runnable interface
 Object class
 Java virtual machine
There are two ways to create threads:
 Extend the Thread class itself.
 Implement the Runnable interface.
Extending Thread:
 
The  Thread class implements Runnable interface, which defines run() method. To create a
thread, Thread class can be extended and the run() method must be overridden. In this
method, the code to be executed by the thread is defined. 
Thread class defines many other methods too, which may or may not be overridden. In
general, Thread should be extended to create a new thread only if methods other than run()
are to be extended. Otherwise, it is probably better to implement Runnable interface.
 
Implementing Runnable:
 
It is the simplest way to create a new thread. This interface defines only run() method. To
implement Runnable, a class need only implement run(), which is declared as public and
void in Runnable. After the class that implements Runnable is created, it can be passed in
the constructor of Thread to instantiate an object of Thread. 
 
Starting threads:
 
Thread class defines start() method, which must be called on the thread object to start
execution of run() method. 
 
When a thread is created by extending Thread class, it inherits run() from Thread and
overrides it. To execute the code defined in its run() method, its start() method needs to be
called. This registers the thread with Thread Scheduler. Calling start() does not immediately
cause the thread to run; it just makes it eligible to run. The thread must still contend for
CPU time with all other threads.
For example, if class MyThread has extended Thread, this is how the thread is started:
 
      Thread t=new MyThread ();
      t.start();
 
Though, you can override start() too, but that will defeat the purpose of extending Thread,
since start() basically initiates a call to run(). If you override start(), you unwittingly might
interfere with this process.
 
If a thread has been created by implementing Runnable, you still need to instantiate an
object of type Thread. Say, for example, that MyThread implements Runnable. In this case,
this is how you create and start a thread.
 
     MyThread m=new MyThread ();
     Thread t=new Thread (m);
     t.start ();
 
This will cause the code defined in run () method of MyThread to be executed. 
 
 
Recognize conditions that might prevent a thread from executing.
 

 
The following conditions may prevent a thread from executing:
 The run () method has completed and returned.
 An unchecked exception has been thrown from within the run () method and it is
unhandled.
 The JVM has exited due to any reason.
 A deadlock has occurred.
 The thread has been stopped from executing by the program itself.
Write code using synchronized, wait, notify, or notifyAll, to protect against
concurrent access problems and to communicate between threads. Define the
interaction between threads and between threads and object locks when
executing synchronized, wait, notify, or notifyAll.
 

 
Synchronization: 

When two or more threads need access to a shared resource, they need some way to
ensure that the resource will be used only by one thread at a time. The process by which
this is ensured is called Synchronization.

Key to synchronization is the concept of the monitor (also called Semaphore). A monitor is
an object that is used as a mutually exclusive lock, or mutex. Only one thread can own a
monitor at a given time. When a thread acquires a lock, it is said to have entered the
monitor. All other threads attempting to enter the locked monitor will be suspended until
the first thread exits the monitor. A thread that owns a monitor can reenter the same
monitor if it so desires. There are two ways to synchronize your code: 

 Using synchronized methods

Synchronizing is easy in Java because all objects have their own monitor associated
with them. To enter an object’s monitor, just call a method that has been modified
with thesynchronized keyword. While a thread is inside a synchronized method, all
other threads that try to call it ( or any other synchronized method) on the same
instance have to wait. To exit the monitor and relinquish control of the object to the
next waiting thread, the owner of the monitor simply returns from the synchronized
method.

When there is no synchronization, nothing exists to stop all the threads from calling
the same method on the same object at the same time. This is known as a race
condition, because the threads are vying with each other to complete the method. In
most situations, a race condition is less predictable, because you cannot be sure
when the context switch will occur. This can cause a program to run right one time
and wrong the next.

To fix this problem you must serialize access to a method. That is, you must restrict
its access to only one thread at a time. To do this, qualify the method with
‘synchronized’ keyword. Anytime that you have a method, or a group of methods
that manipulate the internal state of an object in a multi-threaded situation, you
should use the ‘synchronized’ keyword to guard the state from race conditions. Once
a thread enters any synchronized method on an instance, no other thread can enter
any other synchronized method on the same instance. However, non- synchronized
method on that instance will continue to be callable.

 The synchronized statement
If you want to synchronize access to objects of a class that was not designed for
multi-threaded access i.e. the class does not use synchronized methods or if you do
not access to the source code of the class, then simply put calls to the methods
defined by this class inside a synchronized block

           synchronized ( object){

                  // statements to be synchronized.

            }

Here object is a reference to the object being synchronized. If you want to


synchronize only a single statement, curly braces are not needed.
A synchronized block ensures that a call to a method that is a member of object
occurs only after the current thread has successfully entered object’s monitor. 

Inter-thread communication: 

Multithreading replaces event loop programming by dividing your tasks into discreet and
logical units. Threads also provide a secondary benefit: they do away with polling. Polling is
usually implemented by a loop that is used to check some condition repeatedly. Once the
condition is true, appropriate action is taken. This wastes CPU time.

To avoid polling, Java includes an elegant inter-process communication via wait(), notify()
and notifyAll(). These methods are implemented as final methods in Object, so all classes
have them. All these three methods can be called only from within a synchronized method. 

The method wait() tells the calling thread to give up the monitor and go to sleep until some
other thread enters the monitor and calls notify(). Additional forms of wait() exist that allow
you to specify a period of time to wait. 

The method notify() wakes up the first thread that called wait() on the same object. 

The method notifyAll() wakes up all the threads that called wait() on the same object. The
highest priority thread will run first. 

Deadlock 

A special type of error in multitasking is deadlock, which occurs when two threads have a
circular dependency on a pair of synchronized objects. For example, suppose one thread
enters the monitor on object x and another  thread enters the monitor on object y. If the
thread in x tries to call any synchronized method on y, it will block as expected. However, if
the thread in y, in turn, tries to call any synchronized method on x, the thread waits
forever, because to access x, it would have to release its own lock on y so that the first
thread could complete.

Deadlock is a difficult error to debug because:

 In general, it occurs only rarely, when the two threads time-slice in just the right
way.
 It may involve more than two threads and two synchronized objects.

Some Important Concepts


 

Why multi-threading:

Multi-threading makes a program more efficient by minimizing the idle CPU time. It is
especially relevant in an interactive program, or in any program that has to wait for some
event to occur or for some resource, to proceed further. While one thread of the program
waits, another thread can continue executing code that is not dependent on that event to
occur.

Thread priorities:

Thread priorities are integers that specify the relative priority of one thread to another.
These are used by the thread scheduler to decide when each thread should be allowed to
run. (Thread scheduler is a piece of system code . The scheduler might be part of JVM or
host operating system. It determines which thread is actually running on each available CPU
at a given time.) A thread’s priority is used to decide when to switch from one running
thread to the next. This is called a context-switch. The rules that determine when a context
switch takes place are:

 A thread can voluntarily relinquish control. This is done by explicitly yielding,


sleeping or blocking on pending I/O. In this scenario, all other threads are examined,
and  the highest priority thread that is ready to run is given the CPU.
 A thread can be preempted by a higher priority thread. In this case, a lower priority
thread that does not yield the processor is simply preempted – no matter what it is
doing – by a higher priority thread. This is called preemptive multithreading.

In cases where two threads with the same priority are competing for CPU cycles, the
outcome is system dependent. In operating systems like windows, equal priority threads are
time-sliced automatically in round robin fashion. If there is more than one waiting thread,
scheduler chooses one of them. There is no guarantee that the longest waiting thread will
be chosen. For other types of operating systems, such as Solaris, threads of equal priority
must voluntarily yield control to their peers. If they do not, other threads will not run. 

The Java specification states that threads must have priorities, but it does not dictate
precisely what the scheduler do about priorities. This vagueness is a problem: algorithms
that rely on manipulating thread priorities might not run consistently on all platforms. If you
want smooth multi-tasking, you should not rely on priorities of threads. Also some types of
tasks are CPU intensive. Such threads dominate the CPU. For these types of threads, it is
better to yield control occasionally, so that other threads can run too.

The value of thread priorities must be within the range MIN_PRIORITY (value=1) and
MAX_PRIORITY (value=10). The default is NORM_PRIORITY (value=5). 

All newly created threads have their priority set to that of the creating thread.
Main thread:

When a Java program starts up, one thread begins running immediately. This thread is the
one that is executed when your program begins. The main thread is important for two
reasons:

 It is the thread from which other child threads will be spawned.


 It must be the last thread to finish execution. When the main thread stops, your
program terminates.

The main thread is created automatically when a program is started. It can be controlled
through a Thread object. To do so, you must obtain a reference to it by calling the method
currentThread(), which is a public, static member of Thread.

Thread t=Thread.currentThread();

When t is used as an argument to println(), it displays the name of the thread, its priority
and the name of its group in that order.

A thread group is a data structure that controls the state of a collection of threads as a
whole. This process is managed by the particular runtime environment.

Return of run (): 

When the run() returns, the thread has finished its task and is considered dead. There is no
way to restart it. If you want the thread’s task to be performed again, you have to construct
and start a new thread instance. The dead thread continues to exist; it is an object like any
other object, and you can still access its data and call its methods. You just cannot make it
run again.

Instead of using stop() of thread class, if a thread might need to be killed from another
thread, then you should send it an interrupt() from the killing method.

Thread states: 

When you call start() on a thread, the thread does not run immediately. It goes into a
ready-to-run state and stays there until the scheduler moves it to the “running state”. Then
the run() is called. In the course of executing run(), the thread may temporarily give up the
CPU and enter some other state for a while. The thread states are:

 Running
 Waiting
 Sleeping
 Suspended
 Blocked
 Dead

  
Controlling threads

Yielding  

A call to the yield() method causes the currently executing thread to move to the ready
state if the scheduler is willing to run any other thread in its place. There are two possible
scenarios. If any other threads are in the ready state, then the thread that just yielded
might have to wait a while before it gets to execute again. However, if there are no other
waiting threads, then the yielding thread gets to continue executing immediately. Most
thread schedulers do not stop the yielding thread from running in favor of a lower priority
thread. The yield() always causes the currently executing thread to yield. Yielding allows a
time consuming thread to permit other threads to execute.

Suspending 

Suspending a thread is a mechanism that allows any arbitrary thread to make another
thread un-runnable for an indefinite period of time. The suspended thread becomes
Runnable when some other thread resumes it. It is very easy to cause deadlock in a
program using these methods, since a thread does not have any control over when it is
suspended and it might be in a critical section, holding an object lock at the time. The exact
effect of suspend() and resume() is much better implemented using wait() and notify().

Sleeping 

A sleeping thread passes time without doing anything and without using the CPU. A call to
sleep() requests the currently executing thread to cease executing for (approx) a specified
amount of time. The method sleep(), like yield(), is static. Both operate on currently
executing thread.

When a thread has finished sleeping, it does not continue execution. It moves to a ready
state and waits for the scheduler’s permission.

The Thread class has a method called interrupt(). A sleeping thread that receives an
interrupt() call moves immediately into ready state; when it gets to run, it will execute its
InterruptedException handler.

Blocking 

Many methods that perform input/output have to wait for some occurrence in the outside
world before they can proceed; this behavior is known as blocking. In general, if a method
needs to wait an indefinite time until some I/O takes place, then a thread executing that
method should graciously step out of the Running state. All Java I/O methods behave this
way. A thread that has stepped out in this fashion is said to be blocked.

Generally, if you see a method with a name that suggests that it might do nothing until
something becomes ready, you should expect that the caller thread might be blocked
becoming un-runnable and losing the CPU, when the method is called.

A thread can also become blocked if it fails to acquire the lock for a monitor or if it issues a
wait() call. Internally, most blocking for I/O, is implemented using wait() and notify().
Important  Exceptions:

IllegalThreadStateException: thrown to indicate that a thread is not in an appropriate state


for the requested operation. 

IllegalMonitorStateException: thrown to indicate that a thread has attempted to wait on an


object’s monitor without owning the specified monitor. 

Why stop (), suspend () and resume () are deprecated?  

stop () is inherently unsafe. Stopping a thread causes it to unlock all the monitors that it
has locked. (the monitors are unlocked as the ThreadDeath exception propagated up the
stack.) If any of the objects previously protected by these monitors were in an inconsistent
state, other threads may now view these objects in an inconsistent state. Such objects are
said to be damaged. When threads operate on damaged objects, arbitrary behavior can
result. This behavior may be subtle and difficult to detect, or it may be pronounced. Unlike
other unchecked exceptions, ThreadDeath kills threads silently; thus, the user has no
warning that his program may be corrupted. The corruption can manifest itself at any time
after the actual damage occurs, even after hours or days in the future. Most uses of stop ()
should be replaced by code that simply modifies some variable to indicate that the target
thread should stop running. The target thread should check this variable regularly, and
return from its run method in an orderly fashion if the variable indicates that it is to stop
running. To ensure prompt communication of the stop () request, the variable must
bevolatile (or access to the variable must be synchronized. 

suspend () is inherently deadlock-prone. If the target thread holds a lock on the monitor
protecting a critical system resource when it is suspended, no thread can access this
resource until the target thread is resumed. If the thread that would resume the target
thread attempts to lock this monitor prior to calling resume (), deadlock results. Such
deadlocks typically manifest themselves as frozen processes. 

resume () exists solely for suspend (). Therefore it has been deprecated too.

API for Thread class


Constructors:  

 Thread ()
 Thread (Runnable obj, String name)
 Thread (Runnable obj)
 Thread (String name)
 Thread (ThreadGroup tg, Runnable obj)
 Thread (ThreadGroup tg, Runnable obj, String name)
 Thread (ThreadGroup tg, String name)

ThreadGroup versions throw SecurityException if the current thread cannot create a thread
in the specified group. 
static methods:  

 int activeCount ()

Returns the current number of active threads in this thread's thread group.

 Thread currentThread ()

Returns a reference to the currently executing thread object.

 void dumpStack ()
 int enumerate (Thread [] t)
 boolean interrupted ()

Tests whether the current thread has been interrupted. The interrupted status
of the thread is cleared by this method. In other words, if this method were to
be called twice in succession, the second call would return false (unless the
current thread were interrupted again, after the first call had cleared its
interrupted status and before the second call had examined it).

 void sleep (long millis) throws InterruptedException


 void sleep (long millis, int ns) throws InterruptedException

sleep () causes the currently executing thread to sleep (temporarily cease


execution) for the specified number of milliseconds (and ns nanoseconds if
specified). The thread does not lose ownership of any monitors. Throws
InterruptedException if another thread has interrupted the current thread.
The interrupted status of the current thread is cleared when this exception is
thrown.

 void yield ()

Causes the currently executing thread object to temporarily pause and allow
other threads to execute. 

Instance methods:  

 void checkAccess ()
 void destroy ()

Destroys this thread, without any cleanup. Any monitors it has locked remain
locked. (This method is not implemented.)

 String getName ()
 void setName (String name)
 int getPriority ()
 void setPriority (int priority)
 ThreadGroup getThreadGroup ()
 void interrupt ()
 boolean isAlive ()
 boolean isDaemon ()
 boolean isInterrupted ()

Tests whether this thread has been interrupted. The interrupted status of the
thread is unaffected by this method.

 void join ()
 void join (long millis)

Waits at most millis milliseconds for this thread to die. A timeout of 0 means
to wait forever. Throws InterruptedException if another thread has
interrupted the current thread. The interrupted of the current thread is
cleared when this exception is thrown.

 void join (long millis, int ns)


 void run ()

If this thread was constructed using a separate Runnable object, then that
Runnable object’s run method is called; otherwise, this method does nothing
and returns.

 void setDaemon (boolean on)

Marks this thread as either a daemon or a user thread. The JVM exits when
the only threads running are all daemon threads. This method must be called
before the thread is started.

 void start ()

Causes this thread  to begin execution; the JVM calls the run method of this
thread. The result is that two threads are running concurrently: the current thread
(which returns from the call to the start () method) and the other thread (which
executes its run () method). Throws IllegalThreadStateException if the thread was
already started.

 void resume () Deprecated


 void stop ()  Deprecated
 void suspend ()  Deprecated

Section 8 : The java.awt Package


Write code using component, container, and LayoutManager classes of the
java.awt package to present a GUI with specified appearance and resize behavior,
and distinguish the responsibilities of layout managers from those of containers.

 
 
Painting in Java
 
Painting on a component is accomplished by making calls to a graphics context, which is an
instance of the Graphics class. A graphics context knows how to render onto a single target.
The three media a graphics context can render onto are:
 
1. Components
2. Images
3. Printers
 
Any kind of component can be associated with a graphics context. The association is
permanent – a context cannot be reassigned to a new component. Although you can use
graphics contexts to paint onto any kind of component, it is unusual to do so with
components that already have an appearance. Buttons, Choices, checkboxes, labels,
scrollbars, and text components do not generally require programmer level rendering. There
are four classes of blank components that have no default appearance and will show up as
empty rectangles unless they are sub-classed and given paint() methods:
 
1. Applet
2. Canvas
3. Frame
4. Panel
 
The four major operations provided by the Graphics class are:
 
1. Selecting a color
2. Selecting a font
3. Drawing and filling
4. Clipping
 
Selecting a color
 
Calling g.setColor() does not change the color of anything that has already been drawn. It
only affects the subsequent operations.
 
Selecting a font
 
Setting the font of a graphics context is like setting the color – subsequent string drawing
operations will use the new font, while previously drawn strings are not affected. Before you
can set a font, you have to create one. The constructor for the Font class is
 
Font(String fontName, int style, int size);
 
The first parameter is the name of the font. Font availability is platform dependent. You can
get a list of available font names, returned as an array of strings, by calling getFontList()
method on your toolkit.
 
String [] fontNames = Toolkit.getDefaultToolkit().getFontList();
 
There are three font names that you can always count on, no matter what platform you are
running on:
 
1. Serif
2. SansSerif
3. Monospaced
 
The style parameter of  the Font constructor should be one of the three:
 
 Font.BOLD
 Font.PLAIN
 Font.IATLIC
 
You can specify a bold-italic font by passing Font.BOLD+Font.ITALIC  as a style parameter.
 
Drawing and filling
 
Every component has its own coordinate space with the origin in the component’s upper left
corner.
 
drawString()
         
          The parameters x, y specify the left edge of the baseline of the string. Characters
with the descenders (g, j, p, q, y etc.) extend below the baseline. By default a graphics
context uses the font of  the associated component. However, you can set a different font
by calling the graphics context’s setFont() method.
 
Clipping
 
Clipping is simply restricting the region that a graphics context can modify. Every graphics
context – that is every instance of the Graphics class – has a clip region, which defines all or
part of the associated component. When you call one of the drawXXX() or fillXXX() methods
of the Graphics class, only those pixels that lie within the clip region are modified. The
default clip region for a graphics context is  the entire associated component. There are
methods that retrieve and modify a clip region.
 
To set a rectangular region for a graphics context, you can call the setClip(x, y, width,
height) method, passing in four ints that describe the position and size of the desired clip
region. Clipping also comes into play when the environment needs to repair exposed
portions of a component.
 
If a frame or an applet contains components that have their own paint() methods, then all
the paint() methods will be called by the environment when necessary.
 
The GUI thread and the repaint() method
 
The runtime environment creates and controls its own threads that operate behind the
scenes, and one of these threads is responsible for GUI management. The GUI thread is the
environment’s tool for accepting user input events and for calling the paint() method of
components that need painting. Calls to paint() are not generated by the run time. Java
programs can make their own calls, either directly (which is not recommended) or indirectly
( via the repaint() method).
 
Spontaneous painting
 
Some painting happens all by itself, with no impetus from the program. For example, when
a browser starts up an applet, shortly after init() method completes, a call is made to the
paint() method. Also, when part or all of a browser or a frame is covered by another window
and then becomes exposed, a call is made to the paint(). It is the GUI thread that makes
these calls to paint(). Every applet, and every application, that has a GUI, has a GUI thread.
The GUI thread spontaneously calls paint() under four circumstances, two of which are
applicable to applets:
 
1. After exposure
2. After de-iconification
3. Shortly after init() returns (applets only)
4. When a browser returns to a previously displayed page containing an applet,
provided the applet is at least partially visible.
 
When the GUI thread calls paint() it must supply a graphics context. Every graphics context
has a clip region. The GUI thread makes sure that the graphics contexts that get passed to
paint() have their clip regions approximately set. Most often, the default clip region is
appropriate. However, when a component is exposed, the clip region is set to be just that
portion of the component that requires repair. If only a small region of the component was
exposed, then the clip region insures that no time is wasted on drawing pixels that are
already correct color.
 
The repaint() method
 
There are times when the program, not the runtime, should initiate painting. This usually
happens in response to input events. It is a good rule of thumb to do all drawing operations
in paint(), or in methods called from paint(), so that the GUI thread expects paint() to be
able to correctly reconstruct the screen at any arbitrary moment. The way to give the GUI
thread what it expects is to remove all drawing code from event handlers. Event handlers
should store information in instance variables, then cause a call to paint(). The paint()
should use the values of the instance variables as instructions on what to draw.
 
There is a method update(Graphics g) of Component class, which clears the component to
its background color and then calls paint(). You can override this method and simply call
paint() inside update() so that it does not clear the previously drawn figures.
 
The repaint() method schedules a call to update(). All this means is that a request flag is set
in the GUI thread. Every 100 milliseconds the GUI thread checks the flag. If the flag is set,
the GUI thread calls update() and clears the flag. No matter how many requests are made
during any 100 ms period, only a single call is made to update().
 
Images
 
Images are off–screen representations of rectangular pixel patterns. You can create, modify
and draw them to the screen or to other images. There are three ways to create an image:
 
1. Image img = createImage( int width, int height); // creates an empty image.
2. GetImage( URL fileUrl);
3. GetImage( URL dirUrl, String path);
 
The last two methods create an image based on the information in a gif or jpeg file. The
Applet and Toolkit classes both have getImage().
 
Images have graphics contexts. So, to modify an image get a graphics context for the
image to be modified and call methods like getGraphics().
 

Write code using component, container, and LayoutManager classes of the


java.awt package to present a GUI with specified appearance and resize behavior,
and distinguish the responsibilities of layout managers from those of containers.

 
 
Layout Managers
 
There are two reasons for Java using layout managers.
 
Firstly, precise layout is a repetitious and often performed task. Therefore, according to the
principles of OOP, layout functionality ought to be encapsulated into one or more classes to
automate the task.
 
The second and practical reason stems from Java’s platform independence. Java
components borrow their behavior from the window system of  the underlying hardware on
which JVM is running. The problem here is that buttons and other components have
different sizes when instantiated on different platforms. If Java encouraged precise pixel
level sizing and positioning, there would be a lot of Java GUIs that looked exquisite on their
platform of origin and terrible on others. Java deals with this problem by delegating
precision layout work to layout managers.
 
Containers and Components
 
When a container is constructed, it is given a default layout manager. A container confers
with its layout manager to determine where components will be placed and (optionally) how
they will be resized. If the container subsequently gets resized, the layout manager again
lays out the components. 
 
Component size and position
 
A component’s size and position can be changed by calling its setBounds() method.
Generally, this call proves to be useless since layout managers usually have the last word. It
is they who decide the size and position of the component, since their call to the
component’s setBounds() occurs after any calls to this method by the program. If you wish
to have control over the size then probably it is best to use FlowLayout.
 
Layout policies
 
Every Java component has a preferred size. The preferred size expresses how big the
component would be without intervention by a layout manager. Preferred size is the
smallest size necessary to render the component in a visually meaningful way. Preferred
size is platform dependent, since component boundary decorations vary from system to
system.
 
When a layout manager lays out its container’s child components, it has to balance two
considerations: the layout policy and each component’s preferred size. First priority goes to
enforcing layout policy. If honoring preferred size would mean violating the layout policy,
then the layout manager overrules the preferred size.
 
FlowLayout
 
This layout manager always honors a component’s preferred size.
 
It arranges components in horizontal rows. It is the default manager for Panels and Applets.
It fits as many components as possible into the top row, left to right in the order they were
added, and spills the remainder into second row.
 
Within each row the components are centered and evenly spaced. The justification of the
clustering can be controlled by passing a parameter (FlowLayout.LEFT, FlowLayout.RIGHT
and FlowLayout.CENTER)  to FlowLayout constructor.
 
The default gap between components is 5 pixels in both the horizontal and vertical
directions. This gap can be changed using another of its constructors.
 
1. FlowLayout()
2. FlowLayout(int justification)
3. FlowLayout(int justification, int hGap, int vGap)
 
GridLayout
 
This layout manager always ignores a component’s preferred size.
 
The GridLayout class is a layout manager that lays out a container's components in a
rectangular grid. The container is divided into equal-sized rectangles, and one component is
placed in each rectangle.
 
Components appear in the order they were added, from left to right, row by row.
 
1. GridLayout()
2. GridLayout(int rows, int columns)
3. GridLayout(int rows, int columns, int hgap, int vgap)
 
BorderLayout
 
This is default manager for Frames. It divides its territory into 5 regions:
BorderLayout.NORTH, BorderLayout.SOUTH, BorderLayout.EAST, BorderLayout.WEST, and
BorderLayout.CENTER. Each region can contain one component. This layout is not affected
by the order in which components are added. Instead you must specify which of the five
regions will receive the component you are adding. 
 
The manager honors the preferred height of components in the north and south and forces
them to be exactly as wide as the container. The north and south regions are useful for
toolbars, status lines and any other controls that ought to be as wide as possible, but no
higher than necessary.
 
In east and west, a component gets to be its preferred width but the height extends from
bottom of the north component (if there is one) or to the top of the container (if there is no
North component), to the top of the South component (if there is one) or to the bottom of
the container (if there is no south component).
 
The fifth region is Center which is simply the part of a container that remains after north,
south, east and west have been allocated. When adding a component to center, it is legal to
omit the second parameter to the add() call; the layout manager assumes  that you meant
center.
 
GridBagLayout
 
This is the most complicated layout manager. It divides its container into an array of cells,
but different cell rows can have different heights, and different cell columns can have
different widths. A component can occupy a single cell or it can span many cells. This
manager requires a lot of information to know where to put a component. A helper class
GridBagConstraints is used hold the layout information. When you add a component, you
use the add(component, object) version of the add() method, passing an instance of the
GridBagConstraints as object parameter.
 
To provide the layout information different fields of the GridBagConstraints class are
required to be set. These fields are:
 
int anchor 
          This field is used when the component is smaller than its
display area.
static int BOTH 
          Resize the component both horizontally and vertically.
static int CENTER 
          Put the component in the center of its display area.
static int EAST 
          Put the component on the right side of its display area,
centered vertically.
 int fill 
          This field is used when the component's display area is larger
than the component's requested size.
 int gridheight, gridwidth
          gridheight specifies the number of cells in a column for the
component's display area and gridwidth specifies the number of
cells in a row for the component's display area. The default is 1 for
both and both should be non negative.
 int gridx 
          Specifies the cell at the left of the component's display area,
where the leftmost cell has gridx=0. Default value is RELATIVE.
 int gridy 
          Specifies the cell at the top of the component's display area,
where the topmost cell has gridy=0. Default value is RELATIVE.
static int HORIZONTAL 
          Resize the component horizontally but not vertically.
 Insets insets 
          This field specifies the external padding of the component,
the minimum amount of space between the component and the
edges of its display area. If any of the values used for insets is
negative, this has the effect of allowing the component to expand
outside its display area.
 int ipadx 
          This field specifies the internal padding of the component,
how much space to add to the minimum width of the component.
 int ipady 
          This field specifies the internal padding, that is, how much
space to add to the minimum height of the component.
static int NONE 
          Do not resize the component.
static int NORTH 
          Put the component at the top of its display area, centered
horizontally.
static int NORTHEAST 
          Put the component at the top-right corner of its display area.
static int NORTHWEST 
          Put the component at the top-left corner of its display area.
static int RELATIVE 
          Specify that this component is the next-to-last component in
its column or row (gridwidth, gridheight), or that this component be
placed next to the previously added component (gridx, gridy).
static int REMAINDER 
          Specify that this component is the last component in its
column or row.
static int SOUTH 
          Put the component at the bottom of its display area,
centered horizontally.
static int SOUTHEAST 
          Put the component at the bottom-right corner of its display
area.
static int SOUTHWEST 
          Put the component at the bottom-left corner of its display
area.
static int VERTICAL 
          Resize the component vertically but not horizontally.
 double weightx specifies how to distribute extra horizontal space
and weighty specifies how to distribute extra vertical space.
The layout manager calculates the weight of a column to be the
maximum weightx of all the components in a column. If the
resulting layout is smaller horizontally than the area it needs to fill,
the extra space is distributed to each column in proportion to its
weight. A column that has a weight of zero, all the extra space
appears between the grids of the cell and the left and right edges.
The default value is zero.
Same is true for weighty which handles rows.
static int WEST 
          Put the component on the left side of its display area,
centered vertically.
 
 
CardLayout
 
It lays out its components in time rather than in space. At any moment, a container using
this manager is showing one or another of its components; all the other components are
unseen. A method call to the layout manager can tell it to display a different component. All
the components (which are usually panels) are of its components; all the other components
are unseen. A method call to the layout manager can tell it to display a different
component. All the components (which are usually panels) are resized to occupy the entire
container. The result is similar to a tabbed panel without the tabs.
 
No layout manager
 
To use no layout manager, just call setLayout(null);
If a container has no layout manager, it honors each component’s x, y, width and height
values. So you can call setBounds() on a component, add it to a container and have the
component end up where you want it to be. The problem with this approach is that if your
container resides in a larger container that gets resized, your layout may need to be redone
to save components from being overlaid or clipped away. People who do this find that they
have to write code to detect when the container resizes and more code to do the right
things when resizing occurs. This ends up being more complicated than creating your own
layout manager.
 
 

Write code using component, container, and LayoutManager classes of the


java.awt package to present a GUI with specified appearance and resize behavior,
and distinguish the responsibilities of layout managers from those of containers.

 
 
Components
 
 
Java’s components are implemented by many subclasses of the java.awt.Component and
java.awt.MenuComponent superclasses. There are several methods that are implemented
by all the visual and container components, by virtue of inheritance from Component. The
menu components extend from MenuComponent, so they do not inherit the same super
class functionality.
 
getSize()
Returns Dimension, which has public data members width and height.
 
void setBackground() and setForeground()
if you do not explicitly set a component’s foreground and background colors, the component
uses the colors of its immediate container. Some components on some platforms resist
having their colors changed.
 
void setFont(Font f)
if you do not explicitly set a component’s font, the component uses the font of its container.
 
void setEnabled(boolean flag)
if the argument is true, then the component has its normal appearance, otherwise the
component is grayed out and does not respond to user inputs.
 
setSize(int x, int y), setSize(Dimension d), setBounds(x, y, width, height),
setBounds(Rectangle r)
the size and position that you attempt to give a component is overruled by a layout
manager. In fact, these two methods exist mostly for the use of layout managers. The
major exception to this rule is the Frame class, which is not under the thumbs of a layout
manager and is perfectly willing to have you set its size or bounds.
 
void setVisible(boolean flag)
 
The visible components
 
Button (generates ActionEvent)
 
Its constructors are:
 
 Button()
 Button(String label)
 
Some of the methods are:
 
 String getActionCommand()
 void setActionCommand()
 String getLabel()
 void setLabel()
 EventListener[] getListeners(Class listenerType)
 void processActionEvent(ActionEvent ae)
 void processEvent(AWTEvent e)
 void addActionListener(ActionListener l)
 void removeActionListener(ActionListener l)
 
 
Canvas (generates Mouse, MouseMotion, and Key events)
 
Its constructors are:
 Canvas()
 Canvas(GraphicsConfiguration config)
 
A canvas is a component that has no default appearance or behavior. It represents a blank
rectangular area of the screen onto which the application can draw or from which the
application can trap input events from the user. You can subclass Canvas to create custom
drawing regions, work areas, components and so on.
The default size of a canvas is uselessly small. One way to deal with this problem is to  use
a layout manager that will resize the canvas. Another way is  to call setSize() on the canvas
yourself. Canvases are a rare case where this will actually work.
 
An application must subclass Canvas to get useful functionality such as creating a custom
component. The paint() method must be overridden in order to perform custom graphics on
the canvas.
 
Checkbox  (generates Item event)
 
A checkbox is a two state button: true(checked) and false(unchecked).
Its constructors are:
 Checkbox()
 Checkbox(String label)
 Checkbox(String label, boolean state)
 Checkbox(String label, boolean state, CheckboxGroup group)
 Checkbox(String label, CheckboxGroup group, boolean state)
 
The default state is false. If you pass null for group in 4th or 5th constructor, it will mean that
the checkbox does not belong to any group.
Unlike many window systems which implement radio groups as components in their own
right, in Java CheckboxGroup class is not a component. It is simply a non-visible class that
organizes checkboxes. This means that Java imposes no restrictions on the spatial
relationships among members of a checkbox group.
 
Some of its methods are:
 CheckboxGroup getCheckboxGroup();   Returns null if there is none.
 String getLabel();
 void setLabel(String s);
 EventListener[] getListeners(Class listenerType);
 Object [] getSelectedObject();
 void setCheckboxGroup(CheckboxGroup g); if this checkbox is already in a different
group, it is first taken out of that group.  
 
Choice  (generates Item event)
 
A choice is a pull down list or pop-up menu of choices. The current choice is displayed as
the title of the pop-up menu (choice). It provides only the no-args constructor. To create a
choice, first call the constructor, and then populate the choice by repeatedly calling
addItem(String s).
 
Some of its methods are:
 
1. void add(String item)
2. void addItem(String item)
3. String getItem(int index)
4. int getItemCount()
5. int getSelectedIndex()
6. String getSelectedItem()
7. Object [] getSelectedObjects()
8. void insert(String item, int index)
9. void remove(int position)
10. void remove(String item)
11. void removeAll()
12. void select(int index)
13. void select(String item)
 
FileDialog
 
This class extends Dialog. It represents a file open or file save dialog. The appearance of
these dialogs vary from platform to platform. A file dialog is modal. This means that input
from the dialog’s parent frame will be directed exclusively to the dialog, as long as the
dialog remains visible on the screen. The dialog is automatically removed when the user
specifies a file or clicks the Cancel buttons.
 
Its constructors are:
1. FileDialog(Frame parent)
2. FileDialog(Frame parent, String title)
3. FileDialog(Frame parent, String title, int mode)
First and second constructors are for loading a file. If the value of mode in the third
constructor is FileDialog.LOAD, then the file dialog is finding a file to read. If the value is
FileDialog.SAVE, the file dialog is finding a place to write a file.
 
Label
 
Labels do not respond to user inputs, and they do not send any events. The default
alignment for the labels is to the left.
 
List (on selection ItemEvent, on double-clicking ActionEvent is generated)
 
A list is a collection of text items, arranged vertically. If a list contains more items than it
can display it acquires a vertical scrollbar. The constructors are:
 List()
 List(int rows)
 List(int rows, boolean multiselect)
 
Some of its methods are:
1. void add(String text)
2. void add(String text, int index)
3. String getItem(int index)
4. int getItemCount()
5. int getRows()
6. int getSelectedIndex()
7. int [] getSelectedIndexes()
8. String getSelectedItem()
9. String [] getSelectedItems()
10. void remove(int position)
11. void remove(String item)
12. void removeAll()
13. void replaceItem(String newValue, int index)
14. void select(int index)
15. void setMultipleMode(boolean flag)
 
ScrollPane  (extends Container. Generates Mouse and MouseMotion events)
 
A scrollPane can contain a single component, which may be taller or wider than the scroll
pane itself ( then it acquires scrollbars). The initial size of this container is 100x100, but can
be reset using setSize(). There are two constructors:
 ScrollPane()
 ScrollPane(int scrollbarPolicy)
 
scrollbarPolicy should be one of the following:
1. ScrollPane.SCROLLBARS_AS_NEEDED
2. ScrollPane.SCROLLBARS_ALWAYS
3. ScrollPane.SCROLLBARS_NEVER
 
Scrollbar  (Adjustment event)
 
There are three constructors:
 Scrollbar()
 Scrollbar(int orientation)
 Scrollbar(int orientation, int initial value, int sliderSize, int minValue, int maxValue)
 
Orientation can  be one of the following:
 Scrollbar.HORIZONTAL
 Scrollbar.VERTICAL
 
The defaults are:
Orientation – vertical, unit increment – 1, block increment – 10, value – 0 which controls
the location of the scrollbar bubble, minimum – 0, maximum – 100.
 
The piece of the scroll bar that slides is called slider. The slider size parameter controls the
size of the slider, but not in pixel units. The units of slider size parameter are the units
defined by the spread between the minimum and maximum value of the scroll bar.
 
TextField and TextArea  (TextEvents, ActionEvents on receipt of Enter keystroke)
 
Both classes extend from TextComponent, which extends Component. Constructors are:
 
TextField ()
TextField (int nColumns)
TextField (String text)
TextField (String text, int nColumns)
 
TextArea ()
TextArea (int rows, int columns)
TextArea (String text)
TextArea (String text, int rows, int columns)
TextArea (String text, int rows, int columns, int scrollBarPolicy)
 
The last parameter should be one of the following:
TextArea.SCROLLBARS_BOTH
TextArea.SCROLLBARS_NONE
TextArea.SCROLLBARS_HORIZONTAL_ONLY
TextArea.SCROLLBARS_VERTICAL_ONLY
 
For both classes , there are some surprising issues to the number of columns parameter.
First, vColumns is a measure of width in terms of columns if text, as rendered in a particular
font. Next, there is the problem of proportional font. For a fixed width font, the column
width is obvious. For a proportional font, the column width is average of all the font’s
character widths. Some of the space is taken up by leading and inter-character white space.
So, five column wide component may not show five characters.
 
A final issue arises when a user types beyond the rightmost column. The visible text scrolls
to the left. The insertion point remains in place, at the rightmost column.
Text areas support scroll bars, text fields can be scrolled by using the arrow keys.
 
The common methods inherited by these from TextComponent:
 
 String getSelectedText()
 String getText()
 void setEditable(boolean editable)
 void setText(String text)
 boolean isEditable()
 void selectAll()
 
Additional methods for text field are:
 
 boolean echoCharSet()
 int getColumns()
 char getEchoChar() // gets the character that is to be used for encoding.
        // If the character is 0, user input is echoed unchanged.
 void setColumns(int number)
 void setEchoChar(char c)
 
Additional methods for text area are:
 
 int getColumns()
 void insert(String s, int position)
 void setColumns(int number)
 void setRows(int number)
 void append(String s)
 
 
The container components
 
Applet
 
Applets, by virtue of inheriting from Component, have setSize() and setBounds() methods.
They only exist in browsers. Changing the size of an applet is permitted or forbidden by the
browser, and during the development cycle you cannot know the browser which will be
running the applet. Appletviewer allows resizing of applets. It is common for an applet to
have a temporary setSize() call in its init() method, because this provides an easy way to
play with different sizes. If you use this technique, you should delete the setSize() call
before final delivery, and set size in your html pages.
 
Frame
 
A frame is an independent, top level window with a title bar and a border, decorated by the
underlying window system and capable of being moved around on the screen independent
of other GUI windows. Its size includes the size of the window. The dimensions of the border
can be obtained by getInsets() method, but since these dimensions are platform dependent,
a valid insets value cannot be obtained until the frame is made displayable by calling either
pack() or show().
 
Any application that requires a GUI must use one or more frames to contain desired
components.
The constructors are:
 Frame()
 Frame(String title)
 
When a frame is constructed it has no size and is not displayed on the screen. To give a
size, call one of inherited methods setSize() or setBounds(). To display it, call
setVisible(true). To remove an unwarranted frame from the screen, call setVisible(false).
This does not destroy the frame or damage it; you can display it again by setVisible(true).
 
When you are finished with a frame, you need to recycle its non-memory resources, which
are system dependent; suffice it to say that it takes a lot to connect a Java GUI to an
underlying window system. To release the non-memory resources of a frame, just call its
dispose() method.
 
When a frame is displayed in an applet, it normally carries a warning. The rationale behind
it is that the applet might have been loaded from the internet, so any sensitive information
entered into the frame’s components might possibly be transmitted to parties of dubious
moral fiber.
 
Some of the methods are:
1. Image getIconImage()
2. void setIconImage(Image image)
3. MenuBar getMenuBar()
4. String getTitle()
5. boolean isResizable()
6. void setResizable(boolean flag)
7. void setMenuBar(MenuBar m)
8. void setTitle(String s)
 
If image parameter is null, then image is set to platform dependent default image.
 
 
Panel
 
Applets and frames serve as top-level or outermost GUI components. Panels provide an
intermediate level of spatial organization for GUIs. You are free to add all the components of
a GUI directly into an applet or a frame, but you can provide additional levels of grouping by
adding components to panels and adding panels to a top level applet or frame.
 
Constructors are:
 Panel()
 Panel(LayoutManager)
 
 
Dialog
 
It is a pop up window with a title bar and a border, that accepts user input. It must have a
frame or another dialog defined as its owner when it is constructed. When owner is hidden
or minimized, the dialog is automatically hidden and is visible again with the owner. Dialogs
may optionally be made modal or modeless(default). A modal dialog is one which blocks
input to all other top level windows in the app context, except for the windows created with
the dialog as their owner. The Dialog class is the superclass of the FileDialog class. The
default layout manager for this class is BorderLayout.
 
Constructors:
1. Dialog(Dialog owner)
2. Dialog(Dialog owner, String title)
3. Dialog(Dialog owner, String title, boolean modal)
4. Dialog(Frame owner)
5. Dialog(Frame owner, String title)
6. Dialog(Frame owner, boolean modal)
7. Dialog(Frame owner, String title, boolean modal)
 
All the seven constructors construct an initially invisible Dialog.
 
Methods are:
 void dispose()
 String getTitle()
 void setTitle(String s)
 void hide()
 boolean isModal()
 boolean isResizable()
 void setModal(boolean flag)
 void setResizable(boolean flag)
 void show()
 
Note : pack() defined in Window causes the window to be sized to fit the preferred size and
layout of its subcomponents. If the window and / or its owner are not yet displayable, both
are made displayable before calculating the preferred size. The window will be validated
after the preferred size is calculated.
 
The Menu components
 
There are two types pop up and pull down. Pull down menus are accessed via a menu bar,
which may contain multiple menus. Menu bars may appear only in frames.
To create a frame with a menu bar containing a pull down menu:
 Create a menu bar and attach it to frame.
 Create and populate the menu.
 Attach the menu to the menu bar.
To create a menu bar, instantiate MenuBar class. To attach it to frame, pass it into the
frame’s setMenuBar().
To create a menu, instantiate Menu class. The most common constructor takes a string that
is the menu’s label. There are four kinds of elements that can be mixed and matched to
populate a menu:
 MenuItems
o A menu item is an ordinary textual component available on a menu. The basic
constructor is
MenuItem(String text) where text is the label of the menu item.
A menu item is very much like a button that happens to live in a menu. Like
buttons, menu items generates action events.
 Checkbox MenuItems
o A checkbox menu item looks like a menu item with a checkbox to the left of
its label. When a checkbox menu item is selected, the checkbox changes its
state. The basic constructor isCheckboxMenuItem (String label);. You can
read and set an item’s state by calling getState() and setState(). These
generate ItemEvents.
 Separators
o A separator is just a horizontal mark used for visually dividing a menu into
sections. To add a separator to a menu, call the menu’s addSeparator()
method().
 Menus
o When you add a menu to another menu, the first menu’s label appears in the
second menu, with a pull-right icon. Pulling the mouse to the right causes the
sub-menu to appear.
 
After a menu is fully populated, you attach it to a menu bar by calling menu bar’s add()
method. If you want the menu to appear in the Help menu position to the right of all other
menus, call instead setHelpMenu().
 
The hierarchy of java.awt package is like this:
 
Object
 Layout Mangers (Layout classes)
 CheckboxGroup
 Graphics
 GraphicsEnvironment
 GridBagConstraints
 Font
 Image
 Insets
 Toolkit
 Component
o Button
o Canvas
o Checkbox
o Choice
o Container
 Panel
 Applet
 Window
 Dialog
o FileDialog
o JDialog
 Frame
 ScrollPane
o Label
o List
o Scrollbar
o TextComponent
 TextArea
 TextField
 MenuComponent
o MenuBar
o MenuItem
 CheckboxMenuItem
 Menu
 PopupMenu
 
 EventObject
o AWTEvent
 ActionEvent
 AdjustmentEvent
 ComponentEvent
 ContainerEvent
 FocusEvent
 InputEvent
o MouseEvent
o KeyEvent
 PaintEvent
 WindowEvent
 ItemEvent
 TextEvent
 

Write code to implement listener classes and methods, and in listener methods,
extract information from the event to determine the affected component, mouse
position, nature, and time of the event. State the event classname for any
specified event listener interface in the java.awt.event package.

 
Events
 

Java’s original outward rippling event model proved to have some shortcomings. A new
Delegation event model was introduced with JDK 1.1. Both models are supported in Java2
but all methods of old event model are deprecated. The two models are mutually
incompatible. A java program that uses both models is likely to fail, with events being lost
or incorrectly processed.

The major problem was that an event could only be handled by the component that
generated that event or by one of the containers that contained the generating component.
This restriction violated one of the fundamental principals of OOP: functionality should
reside in the most appropriate class. Often the most appropriate class for handling an event
is not a member of the originating component’s containment hierarchy.

Another drawback of the original model was that a large number of CPU cycles were wasted
on uninteresting events. An event in which a program had no interest would ripple all the
way through the containment hierarchy, before eventually being discarded. The original
model provided no way to disable processing of irrelevant events.

In the event delegation model, a component may be told which object or objects should be
notified when the component generates a particular type of event. If a component is not
interested in an event type, then events of that type will not be propagated.

The event class hierarchy


 

The top most super class of all the new event classes is java.util.EventObject

Its most important method is

          Object getSource();

One sub class of EventObject is java.awt.AWTEvent, which is the super class of all the
delegation model event classes. Again there is only one method of interest:

          int getID(); which returns ID of the event.

An event’s id is an int that specifies the exact nature of the event. The hierarchy is as
follows:

Java.util.EventObject

·         Java.awt.AWTEvent
o ActionEvent
o AdjustmentEvent
o ComponentEvent
 ContainerEvent
 FocusEvent
 InputEvent
 KeyEvent
 MouseEvent
 PaintEvent
 WindowEvent
o ItemEvent
o TextEvent
 

 
The InputEvent super class has a long getWhen() method that returns the time when the
event took place.

Event Listeners
 

An event listener is an object to which a component has delegated the task of handling a
particular kind of event. When the component experiences input, an event of the
appropriate type is constructed and passed as the parameter to a method call on the
listener. A listener must implement the interface that contains the event handling method.
The standard formula for giving an action listener to a component is:

1. Create a listener class that implements the appropriate interface.


2. Construct the component.
3. Construct an instance of listener class.
4. Call addTypeListener() on the component, passing in the listener object.
 

A component may have multiple listeners for any event type. There is no guarantee that
listeners will be notified in the order in which they were added. There is also no guarantee
that all listener notification will occur in the same thread; thus listeners must take
precautions against corrupting shared data.

An event listener may be removed from a component’s list of listeners by calling a


removeXXXListener() method, passing in the listener to be removed.

Listener interfaces and their methods


 

ActionListener
 ActionPerformed (ActionEvent)
 

AdjustmentListener
 AdjustmentValueChanged (AdjustmentEvent)
 

ComponentListener
1. ComponentHidden (ComponentEvent)
2. ComponentMoved (ComponentEvent)
3. ComponentResized (ComponentEvent)
4. ComponentShown (ComponentEvent)
 
ContainerListener
1. ComponentAdded (ContainerEvent)
2. ComponentRemoved (ContainerEvent)
 

FocusListener
1. FocusGained (FocusEvent)
2. FocusLost (FocusEvent)
 

ItemListener
 ItemStateChanged (ItemEvent)
 

KeyListener
1. KeyPressed (KeyEvent)
2. KeyReleased (KeyEvent)
3. KeyTyped (KeyEvent)
 

MouseListener

1. MousePressed (MouseEvent)
2. MouseReleased (MouseEvent)
3. MouseClicked (MouseEvent)
4. MouseEntered (MouseEvent)
5. MouseExited (MouseEvent)
 

MouseMotionListener
1. MouseMoved (MouseMotionListener)
2. MouseDragged (MouseMotionListener)
 

TextListener
 textValueChanged (TextEvent)
 

WindowListener
1. windowActivated (WindowEvent)
2. windowClosed (WindowEvent)
3. windowClosing (WindowEvent)
4. windowDeactivated (WindowEvent)
5. windowDeiconified (WindowEvent)
6. windowIconified (WindowEvent)
7. windowOpened (WindowEvent)
 

 
 
Explicit event enabling
 
There is an alternative to delegating a component’s events. It is possible to sub class the
component and override the method that receives events and dispatches them to listeners.
For example, Components that originate action events have a method
called processActionEvent (ActionEvent), which dispatches its action events to each action
listener.

Class MyButton extends Button{

          Public MyButton(String label){

                   super(label);

                   enableEvents(AWTEvent.ACTION_EVENT_MASK);

          }

          public void processActionEvent(ActionEvent ae){

                   System.out.println(“Processing an action event”);

                   super.processActionEvent(ae);

          }

The AWTEvent class defines 11 constants that can be used to enable processing of events.
Event processing is automatically enabled when event listeners are added, so if you restrict
yourself to the listener model. You never have to call enableEvents(). The call to super
class’s version is responsible for calling actionPerformed() on the button’s action listeners.
Without this call, action listeners would be ignored.

You van also make a component sub class handle its own events, by making the sub class
an event listener of itself. The only difference between this strategy and the enableEvents()
strategy is the order in whicg event handlers are invoked. When you explicitly call
enableEvents(), the component’s processActionEvent() method will be called before any
action listeners are notified. When the component sub class is its own event listener, there
is no guarantee as to order of notification.

Each of the 11 listener types has a corresponding XXX_EVENT_MASK constant defined in the
AWTEvent class, and corresponding processXXXEvent() methods.
 

The strategy of explicitly enabling events for a component can be summarized as follows:

1. Create a subclass of the component


2. In the subclass constructor call enableEvents(AWTEvent.XXX_EVENT_MASK)
3. Provide the subclass with a processXXXEvent() method. This method should call the
superclass’ version before returning.
 

Methods
 

protected final void enableEvents (long eventsToEnable)

This method enables the events defined by the specified mask, to be delivered to this
component. It only needs to be invoked by subclasses of Component which desire to have
the specified event types delivered to processEvents() regardless of whether or not a
listener is registered.

protected void processEvent (AWTEvent e)

it processes events occurring on this Component. By default this method calls the
appropriate process<type>Event() for the given class of event.

Process<type>Event (TypeEvent e)

Processes <type>Events occurring on this component by dispatching them to any registered


listeners. This method is not called automatically unless <type>event is enabled for this
component; either by registering a listener or by enableEvents().

Various add<type>Listener methods


 

Methods Defined in
addActionListener Button List TextField MenuItem

addAdjustmentListener Scrollbar      
addComponentListener All components      

addContainerListener Container      

addFocusListener All components      

addItemListener Checkbox Choice List checkboxMenuItem

addKeyListener All components      

addMouseListener All components      

addMouseMotionListener All components      

addTextListener TextComponent      

addWindowListener Window      

Section 9 : The java.lang Package


 

 
Write code using the following methods of the java.lang.Math class: abs, ceil,
floor, max, min, random, round, sin, cos, tan, sqrt.
 

 
 
Math
 
It is a final class having a private constructor. All of its methods are static.
 
Fields:
 
 static double E
 static double PI
 
Methods:
 
 type abs (type t)
type is double, float, int and long. Return type and argument type are same.
In case of int and long versions, if respective MIN_VALUE is the argument
then same is returned. In case of float and double versions if argument is
positive or negative zero, positive zero is returned. If argument is infinite,
positive Infinity is returned. If argument is NaN, the result is NaN.
 double ceil (double d)
returns the smallest (closest to negative infinity) double value that is not less
than the argument and is equal to a mathematical integer. Special cases:
If argument is equal to an integer, same is returned.
If argument is NaN, +Infinity, -Infinity, +0, or –0, the result is same as
argument.
If argument is less than zero but greater than –1.0, result is –0.0
 double floor (double d)
returns the largest (closest  to positive infinity) double value that is not
greater than the argument and is equal to mathematical integer.
Return values are same in special cases as that in ceil() except there is no
third case.
 double cos (double d)
d is in radians. If argument is NaN or infinity, result is NaN.
 type max (type t1, type t2)
type is int, float, long or double. Return type is same as argument type.
Returns the greater of the two values. For float and double versions:
if either of the arguments is NaN, NaN is returned.
Unlike the numerical comparison operators, here –0.0 is smaller than +0.0
 type min (type t1, type t2)
returns the smaller of the two values. Rest of the discussion is same as
max().
 double random ()
returns double value between +0.0 and 1.0 (exclusive). This method is
properly synchronized to allow correct use by more than one thread.
 double rint (double d)
returns the closest double value to argument and is equal to an integer.
 long round (double d)
return the closest long value to the argument.
If argument is NaN, result is zero.
If argument is –Infinity or any value less than or equal to the value of
Long.MIN_VALUE, the result is equal to Long.MIN_VALUE.
If argument is +Infinity or >= Long.MAX_VALUE, then the result is
Long.MAX_VALUE.
 int round (float f)
return the closest long or int values to the argument respectively.
If argument is NaN, result is zero.
If argument is –Infinity or any value less than or equal to the value of
Integer.MIN_VALUE, the result is equal to Integer.MIN_VALUE.
If argument is +Infinity or >= Integer.MAX_VALUE, then the result is
Integer.MAX_VALUE.
 double sqrt (double d)
returns the correctly rounded positive square root of a double value.
If the argument is NaN or less than zero, then the result is NaN.
If the argument is positive infinity, then the result is positive infinity.
If the argument is positive or negative zero, then the result is same as the
argument.
 double sin (double d)
d is in radians. If argument is NaN or infinity, result is NaN.
 double tan (double d)
same as sin().
 double toRadians (double angDeg)
 double toDegrees (double angRad)
 
 
Describe the significance of the immutability of String objects.

 
String
 
 
It is a public, final class. Implements Serializable, Comparable.
 
Unlike many other languages that implement strings as character arrays, Java implements
strings as objects of type String. This allows Java to provide a full complement of features
that make string handling convenient. Also, String objects can be constructed a number of
ways making it easy to obtain a string when needed.
 
When you create a String object, you are creating a string that cannot be changed. Each
time you need an altered version of an existing string, a new string object is created that
contains the modifications. This approach is used because fixed, immutable strings can be
implemented more efficiently than changeable ones. For those cases in which a modifiable
string is desired, there is a companion class to String called StringBuffer.
 
Constructors:
 
1. String ()
The new string represents an empty string.
2. String (String value)
Initializes the new string with value.
3. String (char [] value)
4. String (char [] value, int offset, int length)
5. String (StringBuffer sb)
6. String (byte [] value)
7. String (byte [] value, int offset, int length)
8. String (byte [] value, int offset, int length, String encoding)
9. String (byte [] value, String encoding)
 
Even though Java’s char type uses 16 bits to represent the Unicode character set, the
typical format for strings on the internet uses arrays of 8 bit bytes constructed from the
ASCII character set. The constructors 6 and 7 initialize a string when given a byte array. In
both, the byte-to-character conversion is done by using the default character encoding of
the platform.
 
The contents of the array are copied whenever you create a string object from an array. If
you modify the contents of the array after you have created the string, the string will be
unchanged.
 
Note: If you pass null in a constructor, compiler error says that it is ambiguous (for String
and StringBuffer versions).
 
Methods:
 
 char charAt (int index)
 int compareTo (Object o)
If o is not a string ClassCastException is thrown.
 int compareTo (String s)
 int compareToIgnoreCase (String s)
 String concat (String s)
 static String copyValueOf (char [] data)
 static String copyValueOf (char [] data, int offset, int length)
 boolean endsWith (String s)
Result will be true if “s” is an empty string or equal to this string.
 boolean equals (Object o)
 boolean equalsIgnoreCase (String s)
 byte [] getBytes ()
 byte [] getBytes (String encoding)
 void getChars (int srcBegin, int srcEnd, char [] dest, int destBegin)
 int indexOf (char c)
Returns the first occurrence. If no occurrence then returns –1.
 int indexOf (char c, int fromIndex)
 int indexOf (String s)
 int indexOf (String s, int fromIndex)
 String intern ()
If the string literal pool already contains a string equal to this string then the
string from the pool is returned; otherwise this string object is added to the
pool, and a reference to this string is returned.
 int lastIndexOf (char c)
 int lastIndexOf (char c, int index)
 int lastIndexOf (String s)
 int lastIndexOf (String s, int index)
 int length ()
 boolean regionMatches (int toffset, String other, int offset, int length)
 String replace (char oldChar, char newChar)
Replaces all occurrences of oldChar. If oldChar is not in the string then
reference to this string is returned otherwise a new string is returned.
 boolean startsWith (String prefix)
 boolean startsWith (String prefix, int offset)
 String substring (int beginIndex)
 String substring (int beginIndex, int endIndex)
 char [] toCharArray ()
 String toLowerCase ()
 String toUpperCase ()
 String trim ()
If this string object represents an empty character sequence, or the first and
last characters both have codes greater than ‘\u0020’ ( the space character),
then this string is returned.
 static String valueOf (boolean b)
 static String valueOf (char c)
 static String valueOf (char [] data)
 static String valueOf (char [] data, int offset, int length)
 static String valueOf (double d)
 static String valueOf (float f)
 static String valueOf (int n)
 static String valueOf (long l)
 static String valueOf (Object o)
if Object o=null; string.valueOf (o) returns null. But string.valueOf (null);
throws NullPointerException.
 
 
String conversion and toString()
 
When Java converts data into its string representation during concatenation, it does so by
calling one of the overloaded versions of the string conversion method valueOf(). For the
simple types, valueOf() returns a string that contains the human-readable equivalent of the
value with which it is called. For objects, valueOf() calls toString() method on the object.
For most arrays, valueOf() returns a rather cryptic string, which indicates that it is an array
of some type. For arrays of char, however, a string object is created that contains the
characters in the char[].
 
 
StringBuffer
 
 
String buffers are safe for use by multiple threads. These are used by the compiler (append
() method) to implement the binary string concatenation operator +.
 
Constructors:
 
 StringBuffer ()
No characters, initial capacity of 16 characters.
 StringBuffer (int length)
 StringBuffer (String s)
Initial capacity 16+s.length()
 
 
Methods:
 
 StringBuffer append (boolean b)
 StringBuffer append (char c)
 StringBuffer append (char [] data)
 StringBuffer append (char [] data, int offset, int length)
 StringBuffer append (double d)
 StringBuffer append (float f)
 StringBuffer append (int n)
 StringBuffer append (Object o)
 StringBuffer append (String s)
This method converts the arguments as if by String.valueOf ().
When the argument is String and is null, then the four characters “null” is
appended to this string buffer and  returned.
When the argument is Object and is null, then null is returned.
When the argument is direct null (i.e. sb.append (null)), then a compiler error
occurs saying that it is ambiguous (for char [] and String versions).
 int capacity ()
the capacity is the amount of storage available for newly inserted characters;
beyond which an allocation will occur.
 char charAt (int index)
 StringBuffer delete (int start, int end)
Removes the sub-string starting at start and extending to the character at
index end-1 or to the end of the StringBuffer if no such character exists.
Throws StringIndexOutOfBoundsException if start is negative, greater than
length(), or greater than end.
 StringBuffer deleteCharAt (int index)
 void ensureCapacity (int minimumCapacity)
The new capacity is the larger of the the minimumCapacity argument and
twice the old capacity plus 2. If the argument is negative, then the method
takes no action and simply returns.
 void getChars (int srcBegin, int srcEnd, char [] dest, int destBegin)
 StringBuffer insert (int offset, boolean b)
 StringBuffer insert (int offset, char c)
 StringBuffer insert (int offset, char [] data)
 StringBuffer insert (int offset, char [] data, int offset, int length)
 StringBuffer insert (int offset, double d)
 StringBuffer insert (int offset, float f)
 StringBuffer insert (int offset, int n)
 StringBuffer insert (int offset, Object o)
 StringBuffer insert (int offset, String s)
For all versions of insert (), discussion is same as that in append().
 StringBuffer replace (int start, int end, String s)
 StringBuffer reverse ()
 void setCharAt (int index, char c)
 void setLength (int newLength)
The string buffer is altered to represent a new character sequence, whose
length is specified by newLength. The string buffer is truncated or null
characters added.
 String substring (int start, int end)
 String toString ()
 
 
java.util Package
 

 
Make appropriate selection of collection classes/interfaces to suit specified
behavior requirements.
 
 
Collection (Interface)
 
Methods
 
1.boolean add (Object o);  ensures that this collection contains the specified element.
2.boolean addAll (Collection c); the behavior of this operation is undefined if the
specified collection is modified while the operation is in progress. This implies that
the behavior of this operation is undefined if the specified collection is this collection,
and this collection is non empty.
3.void clear();
4.boolean contains(Object o);
5.boolean containsAll(Collection c);
6.boolean equals(Object o);
7.boolean isEmpty();
8.boolean iterator();  There are no guarantees concerning the order in which the
elements are returned unless this collection is an instance of some class that
provides a guarantee.
9.boolean remove(Object o);
10.boolean removeAll(Collection c);
11.boolean retainAll(Collection c);
12.int size ();  If this collection contains more than Integer.MAX_VALUE, returns
Integer.MAX_VALUE.
13.Object [] toArray();
14.Object [] toArray(Object [] a); returns an array containing all of the elements in
this collection whose runtime type is that of the specified array.
 
Sub-interfaces  
 List
 Set
 BeanContext
 BeanContextServices
 
Implementing classes 
 AbstractCollection

 
 
Set (Interface)
 
Allows at most one null element. Great care must be taken if mutable objects are used as
set elements. The behavior of a set is not specified if the value of an object is changed in a
manner that affects equal comparisons while the object is an element in the set. A special
case of this prohibition is that it is not permissible for a set to contain itself as an element.
 
Implementing classes: HashSet
 
Methods : Inherited from Collection
 

 
List (Interface)
 
List is an ordered collection and allows duplicate elements. So multiple null elements are
allowed too. Operations like positional access to list elements may execute in time
proportional to the index value for some implementations like LinkedList. Thus, iterating
over the elements in a list is typically preferable to indexing through it, if the caller does not
know the implementation.
 
The methods provided for search for a specified object should be used with caution from a
performance point of view, as they may prove to be costly linear searches. While it is
permissible for lists to contain themselves as elements, extreme caution is advised: the
equals() and hashCode() methods are no longer well defined on such a list. 
 
Methods ( Other than those inherited from Collection) 
 void add (int index, Object element);
 boolean addAll (int index, Collection c);
 Object get (int index);
 int indexOf (Object o);  returns –1 if o is not in the list.
 int lastIndexOf (Object o);  returns –1 if o is not in the list.
 ListIterator listIterator();
 ListIterator listIterator(int index);  returns a list iterator of the elements
in the list in proper sequence starting at the specified position in this list.
 Object remove(int index);
 Object set(int index, Object element);
 List subList(int from index, int to index);  fromIndex inclusive, toIndex
exclusive.

 
 
Map (Interface)
 
Maps keys to values. A map cannot contain duplicate keys. Each key can map to at most
one value. This interface takes the place of Dictionary class, which was a totally abstract
class.
 
Map interface three collection views, which allow a map’s contents to be viewed as a set of
keys, collection of values, and set of key-value mappings. The order of a map is defined as
the order in which the iterators on the map’s collection views return their elements.
 
Some map implementations, like TreeMap class make specific guarantees as to their order,
others, like HashMap class do not.
 
Great care must be exercised if mutable objects are used as map keys. The behavior of a
map is not specified if the value of an object is changed in a manner that affects equal
comparisons while the object is a key in the map. A special case of this prohibition is that it
is not permissible for a map to contain itself as a key. While it is permissible for a map to
contain itself as a value, extreme caution is advised: the equals () and hashCode() methods
are no longer well defined on such a map.
 
Methods 
 void clear ();
 boolean containsKey(Object key);
 boolean containsValue(Object value);
 Set entrySet()  returns a set view of the mappings in the map.
 Object get(Object key);  returns the value to which this map maps the
specified key.
 boolean isEmpty();
 Set keySet();  returns a set view of the keys in this map.
 Object put(Object key, Object value);  returns previous value associated
with this key and replaces that specified value. Returns null if there was no
value associated with this key earlier.
 void putAll(Map t);
 Object remove(Object key); removes the mapping for this key if present.
 int size(); returns the key-value mapping number.
 Collection values(); returns a collection view of the values contained in this
map.
 
All the three views returned by keySet(), values() and entrySet() are backed by the map, so
changes to the map are reflected in the set, and vice-versa.
  
Sub-interfaces : SortedMap
 
Implementing classes :
 AbstractMap
 HashMap
 HashTable
 WeakHashMap
 Attributes
 RenderingHints

 
 
SortedSet and SortedMap
 
 
These interfaces extend Set and Map respectively, for implementations that sort their
elements in a specific order. Objects can specify their natural order by implementing
the Comparableinterface, or be dictated a total order by a comparator which implements
the Comparator interface.
 
Comparator
 
          int compare(Object o1, Object o2);
 
Since this method tests for equality, it is recommended that its implementation does not
contradict the semantics of the equals() method. Specific Comparator implementations can
be constructed to order elements according to some custom order, or the default
comparator which uses the natural order of the elements can be used.
 
Comparable
 
          int compareTo(Object o);
 
A class can define the natural order of its instances by implementing this interface. Then its
objects can be used 
 As elements in a sorted set.
 As keys in a sorted map.
 In lists which can be sorted automatically by Collections.sort() method.
 
This natural order of Comparable objects can be overruled by passing a Comparator to the
constructor when the sorted set or map is created.
 
 
SortedSet ( implementing class – TreeSet) 
 SortedSet headSet(Object toElement); returns a view of a portion of this
sorted set, whose elements are strictly less than the specified element.
 SortedSet tailSet(Object fromElement); returns a view of a portion of this
sorted set, whose elements are equal to or more than the specified element.
 SortedSet subSet(Object fromElement, Object
toElement); fromElement inclusive, toElement exclusive.
 Object first();
 Object last();
 Comparator comparator(); this returns the comparator associated with this
sorted set, or null if it uses natural ordering of its elements.
 
SortedMap ( implementing class – TreeMap) 
 SortedMap headMap(Object toKey); returns a view of a portion of this
sorted Map, whose Keys are strictly less than the specified Key.
 SortedMap tailMap(Object fromKey); returns a view of a portion of this
sorted Map, whose Keys are equal to or more than the specified Key.
 SortedMap subMap(Object fromKey, Object toKey); fromKey inclusive,
toKey exclusive.
 Object firstKey ();
 Object lastKey ();
 Comparator comparator(); this returns the comparator associated with this
sorted Map, or null if it uses natural ordering of its keys.

 
ArrayList
 
 
The size(), isEmpty(), get(), set(), iterator() and listIterator() operations run in constant
time. The add() operation runs in amortized constant time i.e. adding n elements requires
o(n) time. All other operations run in linear time.
 
An application can increase the capacity of an ArrayList object before adding a large number
of elements using ensureCapacity(). This may reduce the amount of incremental
reallocation.
 
The iterators returned by iterator() and listIterator() methods are fail-fast. Thus in the face
of concurrent modification, the iterator() fails quickly and cleanly, rather than risking
arbitrary, non-deterministic behavior later, by throwing a  ConcurrentModificationException.
 
ArrayList allows null elements.
 
Constructors: 
 ArrayList()
 ArrayList(Collection c)
 ArrayList(int initialCapacity)

 
HashMap
 
 
Allows null values and keys. It is roughly equivalent to HashTable, except that it is
unsynchronized and permits nulls. Makes no guarantee as to order of the Map. It is
HashTable based implementation. Constant time performance for get() and put(). Iteration
over collection views requires time proportionate to the capacity of the HashMap instance.
Thus it is very important not to set the initial capacity too high, or the load factor too low if
the iteration performance is important. Initial capacity and load factor affect its
performance. When the number of entries exceeds the product of load factor and the
current capacity, the capacity is roughly doubled. Default load factor is 0.75.
 
Iterators returned by all of this class’s collection-view methods are fail-fast.
 
Constructors : 
 HashMap()
 HashMap(int initialCapacity)
 HashMap(int initialCapacity, float loadFactor)
 HashMap(Map)

 
HashSet
 
 
Backed by a HashTable ( actually a HashMap instance). No guarantees as to the iteration
order of the set. Offers constant time performance for basic operations like add(), remove(),
contains() and size(). Rest like as in HashMap. Iterators fail fast. Default load factor is 0.75.
 
Constructors : 
 HashSet()
 HashSet (int initialCapacity)
 HashSet (int initialCapacity, float loadFactor)
 HashSet (Collection c)

 
 
HashTable
 
 
Extends Dictionary implements Map. It is synchronized. The iterators returned by iterator()
and listIterator() of the collections returned by HashTable’s collection-view methods are fail
fast. The Enumerations returned by its keys() and values() are not fail fast. Default load
factor is 0.75.
 
Constructors : 
 HashTable ()
 HashTable (int initialCapacity)
 HashTable (int initialCapacity, float loadFactor)
 HashTable (Map m)

 
 
TreeMap
 
 
Implements SortedMap extends AbstractMap. This class guarantees that map will be in
ascending-key order, sorted as per natural order for the key’s class(comparable) or by
comparator provided at creation time. This implementation provides guaranteed log(n) time
cost for containsKey(), get(), put() and remove() operations. Iterators are fail fast.
 
Constructors : 
 TreeMap ()
 TreeMap (Comparator c)
 TreeMap (SortedMap sm)
 TreeMap (Map t)

 
 
TreeSet
 
 
Implements Set, backed by a  TreeMap instance.
 
Constructors :
 TreeSet ()
 TreeSet (Comparator c)
 TreeSet (SortedSet sm)
 TreeSet (Collection c)
 

 
Vector
 
 
Extends AbstractList, implements List. Iterators fail fast, Enumerations are not.
 
Constructors :
 Vector ()
 Vector (Comparator c)
 Vector (int initialCapacity)
 Vector (int initialCapacity, int capacityIncrement)
 
 

 
Choosing an implementation
 
Lists
 
Type Methods
Get IterationInsert Remove
Array 1 1 n.a. n.a.
ArrayList 2 3 2 2
LinkedList4 2 1 1
Vector 3 4 3 2
 
 
For random access lookups and iteration arrays are fastest. The best approach is probably
to choose ArrayList as default, and to change to LinkedList if there are performance
problems due to many insertions and removals from the middle of the list. While working
with a fixed size group of elements array is best.
 
Sets
 
The performance of HashSet is generally superior to TreeSet for all operations, in particular
addition and look up (the two most important operations). The only reason TreeSet exists is
because it maintains its elements in sorted order, so you only use it when you need a sorted
list.
 
Maps
 
When choosing between implementations of Map, the size of the map is what most strongly
affects performance. When you are using a map your first choice should be HashMap, and
only if you need a constantly sorted map will you need a TreeMap. HashTable is generally a
bit slower than HashMap. TreeMap     should be used as a way to create an ordered list. The
behavior of a tree is that it is always in order and does not have to be specially sorted. Once
you fill a TreeMap you can call keySet() to get a set view, and then use toArray(). HashMap
is designed to rapidly find things. Also, you can easily create a HashMap from a TreeMap
with a single object creation.
 

 
 
Points to Remember
 
1. Some of the operations in the Collection interface are optional, meaning that a collection
may choose not to provide a proper implementation of such an operation. In such a case,
an UnsupportedOperationException is thrown when the optional operation is invoked.
 
2. The inherited method add(Object o) from Collection into the List will append the specified
element to the end of the list. The inherited remove(Object o) removes the first occurrence
of the Object from the list.
 
3. Apart from other utility methods for searching, sorting etc. Collections class’s methods
can be used to customize collection implementations. The important considerations are
 Thread safety
 Data immutability
The Java2 collection classes, except for Vector and HashTable, are not thread safe i.e. their
integrity is jeopardized by concurrent access.
 
 Type synchronizedType(Type t)
 Type unmodifiableType(Type t)
 
where Type is one of the following
 Collection
 List
 Map
 Set
 SortedSet
 SortedMap
 
4. Linked lists do not support fast random access. If you want to see the nth element, you
have to start at the beginning and skip past the first n-1 elements first. Nevertheless, the
LinkedList class supplies a get( int index), which is not very efficient. If you find yourself
using it, you are probably using wrong data-structure for your problem. For every call of
get(index) search begins at the beginning.
 
5. One should always define hashCode() for objects that one inserts in a hash table.
 
6. Adding an element to a tree is slower than adding it to a hash table, but it is still much
faster than array or LinkedList.

Section 11 : The java.io Package


 
 

 
Write code that uses objects of the file class to navigate a file system.
 

 
File
 

This class extends Object, implements Comparable, Serializable. The current user directory
is named by the system property user.dir, and is usually the directory in which the JVM was
invoked. File is an abstract representation of file and directory path names. Instances of this
class are immutable.

Fields

 static final String pathSeparator
The system dependent path separator character, represented as a string for
convenience. This string contains a single character, namely pathSeparatorChar.

 static final char pathSeparatorChar
System dependent.

 static final String separator
The system dependent default name separator character, represented as a string
for convenience. This string contains a single character, namely separatorChar.

 static final char separatorChar
 

Constructors:

 File (File parent, String child)


If parent is null then the new file instance is created as if by invoking
File(String pathname). Otherwise, the parent abstract pathname is taken to
denote a directory, and child is taken either as a directory or a file.

Throws NullPointerException if child is null.

 File (String pathname)


Throws NullPointerException if pathname is null.

 File (String parent, String child)


Same as first constructor.

Methods:

 boolean canRead()
 boolean canWrite ()
 boolean exists ()
 boolean isFile ()
 boolean isDirectory()
 int compareTo(File pathname)
 int compareTo(Object obj)
if the other object is an abstract pathname, then this method behaves as the previous
method, otherwise ClassCastException is thrown.
 boolean createNewFile()
Atomically creates a new, empty file named by this abstract pathname if and only if a
file with this name does not exist yet. Returns false if the named file already exists.
Throws IOException.

 static File createTempFile(String prefix, String suffix)


Throws IOException.
 static File createTempFile(String prefix, String suffix, File directory)
Throws IOException.

 boolean delete()
deletes this file or directory. If it is a directory, then the directory must be empty in
order to be deleted.
 void deleteOnExit()
Requests that file be deleted when JVM terminates. Once the request has been made, it
is not possible to cancel the request.
 File getAbsoluteFile()
 String getAbsolutePath()
 File getCanonicalFile()
 String getCanonicalPath()
 String getName()
 String getParent()
Returns null if this pathname does not name a parent directory.
 File getParentFile ()
 String getPath ()
Converts this abstract pathname to a pathname string.
 boolean isAbsolute ()
 boolean isHidden ()
 long lastModified ()
Returns zero if the file does not exist or if an I/O error occurs.
 long length ()
 String [] list ()
If this file object does not denote a directory then this and the following method return
null. Names denoting the directory itself and the directory’s parent directory are not
included in the result. Each string is a file name rather than a complete path.
 String [] list (FileNameFilter filter)
 File [] listFiles ()
If this file object does not denote a directory then this method returns null. If
this pathname is absolute then each resulting pathname is absolute; if this
pathname is relative then each resulting pathname will be relative to the
same directory.

 static file [] listRoots ()
 boolean mkdir ()
 boolean mkdirs()
Creates the directory named by this abstract pathname, including any necessary but non
existent parent directories. If this operation fails, it may have succeeded in creating
some of the necessary parent directories. Returns true only if the directory, along with
all necessary parent directories was created; false otherwise.
 boolean renameTo (File destination)
Throws SecurityException. Throws NullPointerException if destination is null.
 boolean setLastModified (long n)
throws IllegalArgumentException if n is negative.
 boolean setReadOnly ()
 URL toURL ()
Converts this object into a file:URL. Throws MalformedException if the path cannot be
passed as a URL.
Write code that uses objects of the classes InputStreamReader and
OutputStreamWriter to translate between Unicode and either platform default or
ISO 8859-1 character encoding and Distinguish between conditions under which
platform default encoding conversion should be used and conditions under which a
specific conversion should be used.
 

 
 
InputStreamReader and OutputStreamWriter
 
 
These classes are bridges between character streams and byte streams. InputStreamReader
converts bytes into characters and OutputStreamWriter translates characters written to it
into bytes.
 
Constructors:
 InputStreamReader (InputStream in)
 InputStreamReader (InputStream in, String encoding)
 OutputStreamWriter (OutputStream out)
 OutputStreamWriter (OutputStream out, String encoding)
The constructors, with encoding as parameter, throw UnsupportedEncodingException.
 
Methods of InputStreamReader:
 
 void close ()
 String getEncoding ()
 Int read ()
 Int read (char [] buffer, int offset, int length)
 boolean ready ()
 
Methods of OutputStreamWriter:
 
 void close ()
 void flush ()
 String getEncoding ()
 void write (int c)
 void write (char [] buffer, int offset, int length)
 void write (String s, int offset, int length)
 
 
 A character encoding is a scheme for representing characters. Java represents characters
internally in the 16 bit Unicode character encoding, but the host platform may use different
encoding scheme to represent characters externally. If the default encoding of the host
platform is different than that used by Java, then it becomes necessary to translate the
characters representation between these two encoding schemes. In such cases, the
encoding of the platform may be specified to facilitate this translation.
 
Select valid constructor arguments for FilterInputStream and FilterOutputStream
subclasses from a list of classes in the java.io.package.
 

 
FilterInputStream 
 
This class contains some other input stream, which it uses as a basic source of data. It
simply overrides all methods of InputStream.
 
Valid constructors of some of the subclasses of this class:
 
 BufferedInputStream (InputStream in)
 BufferedInputStream (InputStream in, int size)
 DataInputStream ((InputStream in)
 PushbackInputStream (InputStream in)
 PushbackInputStream (InputStream in, int size)
 
 
 
FilterOutputStream
 
This class contains some other output stream, which it uses as a basic source of data. It
simply overrides all methods of OutputStream.
 
Valid constructors of some of the subclasses of this class:
 
 BufferedOutputStream (OutputStream out)
 BufferedOutputStream (OutputStream out, int size)
 DataOutputStream (OutputStream out)
 PrintStream (OutputStream out)
 PrintStream (OutputStream out, boolean autoflush)
 
PrintStream never throws IOException. It provides print (), println () for all types.
 
The main point to keep in mind here is that you must be able to recognize the subclasses of
InputStream and OutputStream. So, you must know the hierarchy of these classes.
 
InputStream
 
 ByteArrayInputStream
 FileInputStream
 PipedInputStream
 FilterInputStream
o BufferedInputStream
o PushbackInputStream
o DataInputStream
 ObjectInputStream
 
OutputStream
 
 ByteArrayOutputStream
 FileOutputStream
 PipedOutputStream
 FilterOutputStream
o BufferedOutputStream
o PrintStream
o DataOutputStream
 ObjectOutputStream
 
 
 
Write appropriate code to read, write and update files using FileInputStream,
FileOutputStream, and RandomAccessFile objects.
 

 
FileInputStream
 
Extends InputStream.
 
Constructors:
 
 FileInputStream (File file)
 
Creates a FileInputStream object by opening a connection to an actual file,
the file named by the File object in the file system. A new FileDescriptor
object is created  to represent this file connection. Throws
FileNotFoundException if the file does not exist, is a directory or for some
other reason cannot be opened for reading. Throws SecurityException if
access is denied by SecurityManager.
 
 FileInputStream (FileDescriptor fdObj)
 
Creates a FileInputStream object by using fdObj, which represents an existing
connection to an actual file. Throws NullPointerException if fdObj is null.
Throws SecurityException if read access is denied.
 
 FileInputStream (String name)
 
Creates a FileInputStream object by opening a connection to an actual file,
the file named by the path-name String name. A new FileDescriptor object is
created  to represent this file connection. Throws FileNotFoundException if the
file does not exist, is a directory or for some other reason cannot be opened
for reading. Throws SecurityException if access is denied by SecurityManager.
 
 
Methods:
 
 int available ()
 void close ()
 protected void finalize ()
Ensures that close() is called at the time of garbage collection.
 FileDescriptor getFD ()
 int read ()
 int read (byte [] b)
This method blocks until some input is available.
 int read (byte [] b, int offset, int length)
 long skip (long n)
This method may, for a variety of reasons, end up skipping a smaller number
of bytes, possibly zero. Returns actual number of bytes skipped.
 
This class does not override mark() and reset().
 
 
FileOutputStream
 
Extends OutputStream. It writes data to a file or a FileDescriptor. Whether or not a file is
available or may be created depends upon the underlying platform.
 
Constructors:
 
1. FileOutputStream (File f)
Creates a file output stream to write to the file represented by the
specified File object. 
2. FileOutputStream (FileDescriptor fdObj)
Creates an output file stream to write to the specified file descriptor,
which represents an existing connection to an actual file in the file
system.
3. FileOutputStream (String name)
Creates an output file stream to write to the file with the specified name.
A new FileDescriptor object is created to represent this file connection.
4. FileOutputStream (String name, boolean append)
Creates an output file stream to write to the file with the specified name.
If the second argument is true, then bytes will be written to the end of
the file rather than the beginning. A new FileDescriptor object is created
to represent this file connection.
 
Constructors 1,3 and 4 throw FileNotFoundException if the file exists but is a directory
rather than a regular file, does not exist but cannot be created, or cannot be opened for any
other reason.
 
Methods: Overrides those in OutputStream.
 
 
 
RandomAccessFile
 
Extends object, implements DataInput and DataOutput.
 
A random access file behaves like a large array of bytes stored in the file system. For all the
reading routines in the class if end-of-file is reached before the desired number of bytes has
been read, an EOFException is thrown. If any byte cannot be read for any reason other than
end of file, an IOException other than EOFException is thrown.
No method of this class throws IllegalArgumentException.
 
Constructors:
 
 RandomAccessFile (File f, String mode)
 RandomAccessFile (String name, String mode)
 
The mode argument must either be equal to “r” or “rw”, indicating that the file is to be
opened for input only or for both input and output, respectively. The write methods on this
object will always throw an IOException if the file is opened with a mode of “r”. If the mode
is “rw” and the file does not exist,  then an attempt is made to create it. An IOException is
thrown if the file argument refers to a directory. These constructors will throw
IllegalArgumentException if mode is not “r” or “rw”. If file exists but is a directory, or cannot
be opened or created for any other reason.
 
Methods:
 
 void close ()
 long length ()
 int read ()
Reads a byte which is returned as an integer in the range of 0 to 255. method
blocks if no onput is available.
 int read (byte [] b)
 int read (byte [] b, int offset, int length)
 FileDescriptor getFD()
 long getFilePointer ()
Returns the current offset in this file.
 type readType ()
type is java primitive type (all 8 types). The method readBoolean () reads a
single byte. A value of
0 represents false. All other values represent true.
 void readFully (byte [] b)
 void readFully (byte [] b, int offset, int length)
Both of the above methods block until the requested number of bytes are
read, the end of stream is detected or exception thrown.
 String readLine ()
Does not support the full Unicode character set. This method successively
reads the bytes from the file, starting at the current file pointer, until it
reaches a line terminator or end of file. Each byte is converted to a character
by taking the byte’s value for the lower eight bits of the character and setting
the high eight bits to zero. This method blocks for input.
 int readUnsignedByte ()
 int readUnsignedShort ()
 String readUTF ()
 void seek (long position)
The offset may be set beyond the end of file. This does not change the length
of the file. The file length changes only by writing after the offset has been
set beyond the end of the file. If ‘position’ is less than zero, IOException is
thrown.
 void setLength (long newLength)
 int skipBytes (int n)
It may skip over smaller number of bytes (even zero). This method never
throws an EOFException. If n is negative, no bytes are skipped.
 void write (int b)
 void write (byte [] b)
 void write (byte [] b, int offset, int length)
 void writeByte (int b)
 void writeBytes (String s)
 void writeChar ( int v)
 void writeChars (String s)
 void writeDouble (double d)
 void writeFloat (float f)
 void writeInt (int v)
 void writeLong (long l)
 void writeShort (int s)
 void writeUTF (String s)
 
 
 

Describe the permanent effects on the file system of constructing and using
FileInputStream, FileOutputStream, and RandomAccessFile objects.

 
FileInputStream
 
Creating an object of this class does not have any effect on the file system. When you try to
use the object for reading the file it represents, it opens the file for reading if the file exists.
Attempts to use this object may throw FileNotFoundException if the file does not exist, is a
directory or for some other reason cannot be opened for reading.
 
FileOutputStream
 
Creating an object of this class opens the file it represents, to write to the file. If the file
does not exist, a new file is created for writing. Attempts to use this object may throw
FileNotFoundException if the file exists but is a directory rather than a regular file, does not
exist but cannot be created, or cannot be opened for any other reason.
 
RandomAccessFile
 
The mode argument in its constructor must either be equal to “r” or “rw”, indicating that the
file is to be opened for input only or for both input and output, respectively. The write
methods on this object will always throw an IOException if the file is opened with a mode of
“r”. If the mode is “rw” and the file does not exist,  then an attempt is made to create it. An
IOException is thrown if the file argument refers to a directory. These constructors will
throw IllegalArgumentException if mode is not “r” or “rw”. If file exists but is a directory, or
cannot be opened or created for any other reason.

 
Miscellaneous
 

 
The hierarchy of I/O package is like this:
 
InputStream
 ByteArrayInputStream
 FileInputStream
 PipedInputStream
 FilterInputStream
o BufferedInputStream
o PushbackInputStream
o DataInputStream
 ObjectInputStream
 
OutputStream
 ByteArrayOutputStream
 FileOutputStream
 PipedOutputStream
 FilterOutputStream
o BufferedOutputStream
o PrintStream
o DataOutputStream
 ObjectOutputStream
 
Reader
 BufferedReader
 CharArrayReader
 FilterReader
o PushbackReader
o FileReader
 InputStreamReader
 PipedReader
 StringReader
 
Writer
BufferedWriter
CharArrayWriter
FilterWriter
OutputStreamWriter
o FileWriter
 PipedWriter
 PrintWriter
 StringWriter
  
Some methods of InputStream:
 
 int available()
 void close ()
 void mark( int readLimit)
 boolean markSupported ()
 abstract int read ()
 int read (byte [] bytes)
 int read (byte [] bytes, int offset, int length)
 void reset ()
 long skip (long n)
 
Some methods of OutputStream:
 
 void close ()
 void flush ()
 void write (byte [] b)
 void write (byte [] b, int offset, int length)
 abstract void write (int b)
 
Some methods of Reader:
 
 void close ()
 void mark (int readLimit)
 boolean markSupported ()
 int read ()
 int read (char [] chars)
 abstract int read (char [] chars, int offset, int length)
 boolean ready ()
 void reset ()
 long skip (long n)
 
Some methods of Writer:
 
 abstract void close ()
 abstract void flush ()
 void write (char [] chars)
 abstract void write (char [] chars, int offset, int length)
 void write (int c)
 void write (String s)
 void write (String s, int offset, int length)
 
 
 
Methods that do not throw IOException:
 
InputStream:
 
 mark ()
 markSupported ()
 
File:
 
 All Constructors
 getCanonicalFile ()
 getCanonicalPath ()
 createNewFile ()
 toURL ()
 createTempFile ()
 
OutputStreamWriter:
 
 getEncoding ()
 
FileInputStream and FileOutputStream:
 
 All constructors throw FileNotFoundException.
 
RandomAccessFile:
 
 All constructors throw FileNotFoundException.
 
Reader and Writer:
 
 markSupported ()
 
PrintStream and PrintWriter:
 
 never throw IOException.
 
FileReader:
 
All constructors throw FileNotFoundException except fdObj version.
 
FileWriter:
 
One constructor (fdObj version)
 
BufferedReader and BufferedWriter:
 
 All the constructors.
 markSupported()
 
BufferedInputStream and BufferedOutputStream:
 
 All constructors.
 
 
Points to remember

 
 Everything from the start marker of a comment block (e.g. /*) is ignored until the
first occurrence of the matching end marker (*/).

 The "throw" statement can only throw "Throwable" objects. A NullPointerException


will be thrown if the Exception given to the "throw" statement results in null.

 In the same statement you can use decimal, octal and/or hexadecimal statements.

 While creating a multidimensional array, dimensions must be created left to right.


So, int [] [] array = new int [] [4]; is not valid.

 Elements of an un-initialized array object get the default value corresponding to the
type of the elements. Whether the array object reference is a local or member
variable, does not matter.

 In a switch statement the type of the case labels must be assignable to the type
of switch expression.

 It is not possible to break out of an "if" statement. If the "if" statement is placed
within a labeled block, a switch statement or a loop construct, the usage of "break"
would be valid.

 The "if" statement does not return any value.

 "continue" cannot be used outside the context of a loop.

 A variable declared in a "try" block is not visible in "catch" or "finally" block.

 If C extends B and B extends A, then it is not possible to call a method of A


( implemented in all the three classes ) from an instance method in class C.

 An object that has been eligible for garbage collection may stop being eligible for
garbage collection and return to normal life. This happens if the call to the finalize()
reestablishes a reference from the active part of the program to the object.

 If a class has a final blank variable, then it must be initialized when an instance is


created ( in all the constructors or any initializer ) , or else the code will fail to
compile.

 A thread's status (user or daemon) can be changed before the thread is started.
Changing the status of a thread already started throws IllegalStateException.

 An exception which is not thrown in the "try" block (for example, thrown in a "catch"
block) is not handled by subsequent "catch" blocks, but will rather be sent to the
caller of the method. Before this happens, "finally" block is executed. Subsequent
code after "finally" remains unreached if that exception remains uncaught after the
execution of "finally" block.

 If two or more interfaces declare a variable with the same name, then a class
implementing these interfaces cannot refer to that variable by its simple name as it
leads to ambiguity (even if the values of the variable is same in both the interfaces ).
The ambiguity can be avoided by using fully qualified names e.g.
Interface1.varName and Interface2.varName.

 An object can be eligible for garbage collection even if there are references pointing
to the object, as long as the objects with the references are themselves eligible for
garbage collection.

 The unary post-fix operators and all binary operators, except for assignment
operators, associate from left to right. All other operators associate from right to left.

 Floating point modulo (%) by zero produces NaN , but floating point divide by zero
does not.

 Integer division truncates to the next lower integer value in the absolute sense, but
division by right shifting truncates to the next lower integer value in an algebraic
sense. So, -7/2 == -3 but -7 >> 1 == -4.

 Native methods cannot be "abstract", or "strictfp".

 An abstract method cannot be static, final, synchronized, native, private, or strictfp.

 After a thread has started, it will continue to run even if its reference is set to null. A
running thread has a reference in a ThreadGroup even if your program does not
retain one. Thus a running thread is never garbage collected.

 A NullPointerException is thrown when an application attempts to use null in a case


where an object is required.

 A null reference may be used to access a static variable or method.

 A local class cannot have any access modifier.

 The "this" variable is not a normal reference variable that can be changed by
statements like this = new A();   "this" cannot be used to refer to local variables.
http://www.akgupta.com/Java/links.htm

You might also like