You are on page 1of 28

17CS2605D –Fundamentals of Java programming

UNIT-III

Chapter 7: Interfaces
Interface in java is core part of Java programming language and one of the ways to
achieve abstraction in Java along with abstract class.At very basic level interface in java is a
keyword but same time it is an object oriented term to define contracts and abstraction, this
contract is followed by any implementation of Interface in Java. Since multiple inheritance is not
allowed in Java, interface is only way to implement multiple inheritance at Type level.

There are a number of situations in software engineering when it is important for


disparate groups of programmers to agree to a "contract" that spells out how their software
interacts. Each group should be able to write their code without any knowledge of how the other
group's code is written. Generally speaking, interfaces are such contracts.

An Interface is nothing but a contract as to how a class should behave. It just declares the
behavior as empty methods and the implementing class actually writes the code that will
determine the behavior.

When you implement an interface, you're agreeing to adhere to the contract defined in the
interface. That means you're agreeing to provide legal implementations for every method defined
in the interface, and that anyone who knows what the interface methods look like can rest
assured that they can invoke those methods on an instance of your implementing class.

In the Java programming language, an interface is a reference type, similar to a class that
can contain only constants, method signatures, and nested types. There are no method bodies.
Interfaces cannot be instantiated—they can only be implemented by classes or extended by other
interfaces.

Interfaces have another very important role in the Java programming language. Interfaces
are not part of the class hierarchy, although they work in combination with classes. The Java
programming language does not permit multiple inheritance, but interfaces provide an
alternative.

In Java, a class can inherit from only one class but it can implement more than one
interface. Therefore, objects can have multiple types: the type of their own class and the types of
all the interfaces that they implement. This means that if a variable is declared to be the type of
an interface, its value can reference any object that is instantiated from any class that implements
the interface. This is discussed later in this lesson, in the section titled "Using an Interface as a
Type."

1|P ag e
Interface and class

An interface is similar to a class in the following ways:

 An interface can contain any number of methods.

 An interface is written in a file with a .java extension, with the name of the interface
matching the name of the file.

 The byte code of an interface appears in a .class file.

 Interfaces appear in packages, and their corresponding byte code file must be in a
directory structure that matches the package name.

An interface is different from a class in several ways, including:

 You cannot instantiate an interface.

 An interface does not contain any constructors.

 All of the methods in an interface are abstract.

 An interface cannot contain instance fields. The only fields that can appear in an interface
must be declared both static and final.

 An interface is not extended by a class; it is implemented by a class.

 An interface can extend multiple interfaces.

Defining an Interface

An interface declaration consists of modifiers, the keyword interface, the interface name,
a comma-separated list of parent interfaces (if any), and the interface body. For example:

public interface GroupedInterface extends Interface1, Interface2, Interface3 {

// constant declarations

// base of natural logarithms

double E = 2.718282;

// method signatures

2|P ag e
void doSomething (int i, double x);

int doSomethingElse(String s);

The public access specifier indicates that the interface can be used by any class in any
package. If you do not specify that the interface is public, your interface will be accessible only
to classes defined in the same package as the interface.

An interface can extend other interfaces, just as a class can extend or subclass another
class. However, whereas a class can extend only one other class, an interface can extend any
number of interfaces. The interface declaration includes a comma-separated list of all the
interfaces that it extends.

The Interface Body

The interface body contains method declarations for all the methods included in the
interface. A method declaration within an interface is followed by a semicolon, but no braces,
because an interface does not provide implementations for the methods declared within it. All
methods declared in an interface are implicitly public, so the public modifier can be omitted.

An interface can contain constant declarations in addition to method declarations. All


constant values defined in an interface are implicitly public, static, and final. Once again, these
modifiers can be omitted.

A Simple Example

public interface MyInterface {

public String hello = "Hello";

public void sayHello();


}

As you can see, an interface is declared using the Java keyword interface. Just like with
classes, an interface can be declared public or package scope (no access modifier).
The interface contains one variable and one method. The variable can be accessed directly from
the interface, like this:

System.out.println(MyInterface.hello);

3|P ag e
The method, however, needs to be implemented by some class, before you can access it. The
next section will explain how that is done.

Implementing an Interface

Before you can really use an interface, you must implement that interface in some class.
Here is a class that implements the MyInterface interface shown above:
public class MyInterfaceImpl implements MyInterface {

public void sayHello() {


System.out.println(MyInterface.hello);
}
}
Notice the the implements MyInterface part of the above class declaration. This signals to
the Java compiler that the MyInterfaceImpl class implements the MyInterface interface.

A class that implements an interface must implement all the methods declared in the
interface. The methods must have the exact same signature (name + parameters) as declared in
the interface. The class does not need to implement (declare) the variables of an interface. Only
the methods.

Interface Instances

Once a class implements an interface you can use an instance of that class as an instance
of that interface. Here is an example:

MyInterface myInterface = new MyInterfaceImpl();

myInterface.sayHello();

Notice how the variable is declared to be of the interface type MyInterface while the
object created is of type MyInterfaceImpl. This is possible because the
class MyInterfaceImpl implements the MyInterface interface. You can then reference instances
of the MyInterfaceImpl class as instances of theMyInterface interface.

You cannot create instances of an interface by itself. You must always create an instance
of some class that implements the interface, and reference that instance as an instance of the
interface.

4|P ag e
Implementing Multiple Interfaces

A class can implement multiple interfaces. In that case the class must implement all the
methods declared in all the interfaces implemented. Here is an example:

public class MyInterfaceImpl implements MyInterface, MyOtherInterface {

public void sayHello() {


System.out.println("Hello");
}

public void sayGoodbye() {


System.out.println("Goodbye");
}
}

This class implements two interfaces called MyInterface andMyOtherInterface. You list
the names of the interfaces to implement after theimplements keyword, separated by a comma.
If the interfaces are not located in the same packages as the implementing class, you will also
need to import the interface. Interfaces are imported just like classes. For instance:

import com.jenkov.package1.MyInterface;
import com.jenkov.package2.MyOtherInterface;

public class MyInterfaceImpl implements MyInterface, MyOtherInterface {


...
}

Here are the two interfaces implemented by the class above:

public interface MyInterface {

public void sayHello();


}
public interface MyOtherInterface {

public void sayGoodbye();


}

5|P ag e
As you can see each interface contained one method. These methods are implemented by
the class MyInterfaceImpl.

Example for an Interface

interface Shape {

public double area();


public double volume();
}
public class Point implements Shape {

static int x, y;
public Point() {
x = 0;
y = 0;
}
public double area() {
return 0;
}
public double volume() {
return 0;
}
public static void print() {
System.out.println("point: " + x + "," + y);
}
public static void main(String args[]) {
Point p = new Point();
p.print();
}
}

access only the protected and the public value.

6|P ag e
Chapter 8: Exception Handling

Exception Handling

Anexceptionisaproblemthatarisesduringtheexecutionofaprogram.Anexceptioncanoccur for
many different reasons, including thefollowing:
 A user has entered invaliddata.
 A file that needs to be opened cannot befound.
 A network connection has been lost in the middle of communications, or the JVMhas
run out ofmemory

“ExceptionalHandlingisatasktomaintainnormalflowoftheprogram.Forthiswe
shouldtrytocatchtheexceptionobjectthrownbytheerrorconditionandthen display
appropriate message for taking correctiveactions”

Types of Exceptions

1. Checked Exception: A checked exception is an exception that is typically a user


errororaproblemthatcannotbeforeseenbytheprogrammer.Checkedexceptioncanalso be
defined as “The classes that extend the Throwable clas except
RuntimeExceptionandErrorareknownasCheckedExceptions”.Forexample,ifa
fileistobeopened,butthefilecannotbefound,anexceptionoccurs.Theseexceptions are
checked at compile-time and cannot simply be ignored at the time of compilation.
Example of Checked Exception are IOException, SQLExceptionetc.
2. Unchecked Exception: Also known as Runtime Exceptions and theyare ignored at
the time of compilation but checked during execution ofthe
program.UncheckedExceptionscanalsobedefinedas“TheClassesthatextend the
RuntimeException class are known as Unchecked Exceptions”.Example are
ArithmeticException, NullPointer Exceptionetc.
3. Error: These are not exceptions at all, but problems that arise beyond the control of
theuserortheprogrammer.Errorsaretypicallyignoredinyourcodebecauseyoucanrarelydo
anythingaboutanerror.Forexample, if a stack over flow occurs, and an error will arise.
They are also ignored at the time of compilation.

7|P ag e
Hierarchy of Exception

Allexceptionclassesaresubtypesofthejava.lang.Exceptionclass.Theexceptionclassisa
subclassoftheThrowableclass.Otherthantheexceptionclassthereisanothersubclasscall
ed Error which is derived from the Throwable class.

Table of JAVA – Built in Exceptions

Following is the list of Java Unchecked Runtime Exception


Exception Description
ArithmeticException Arithmetic error, such asdivide-by-zero.
ArrayIndexOutOfBoundsException Array index isout-of-bounds.
ArrayStoreException Assignment to an array element of
anincompatibletype.
ClassCastException Invalidcast.
IllegalArgumentException Illegal argument used to invoke amethod.
IllegalMonitorStateException Illegal monitor operation, such as waiting
onanunlockedthread.
IllegalStateException Environment or application is in incorrectstate.
IllegalThreadStateException Requested operation not compatible
withcurrentthreadstate.
IndexOutOfBoundsException Some type of index isout-of-bounds.

8|P ag e
NegativeArraySizeException Array created with a negativesize.
NullPointerException Invalid use of a nullreference.
NumberFormatException Invalid conversion of a string to a numericformat.
SecurityException Attempt to violatesecurity.
StringIndexOutOfBounds Attempt to index outside the bounds of astring.
UnsupportedOperationException An unsupported operation wasencountered.

Handling Exceptions in Java

Following five keywords are used to handle an exception in Java:

1. try
2. catch
3. finally
4. throw
5. throws

try –catch block

A method catches an exception using a combination of the try and catch keywords. A
try/catch block is placed around the code that might generate an exception. Code within a
try/catch block is referred to as protected code, and the syntax for using try/catch looks like
the following:

Write block of code here that is likely to cause an


error condition and throws an exception

A catch statement involves declaring the type of exception you are trying to catch. If an
exception occurs in protected code, the catch block (or blocks) that follows the try is checked.
If the type of exception that occurred is listed in a catch block, the exception is passed to the
catch block much as an argument is passed into a method parameter.

Example of Program without Exceptional Handling

9|P ag e
Now as the statement which can
cause error condition is wrapped
under try block and catch block is also
present to handle the exception
This object
statement can Incause
thrown. error even
this case as if
divide by Zero is an
there is an error rest of the program
ArithmeticException
will execute normally

Output

Output:

Same Program with Exception Handling

Multiple Catch Blocks:

A try block can be followed by multiple catch blocks, but when we use multiple
catch statements it is important that exception subclasses must come before any of
their superclasses. The reason is “a catch statement with superclass will catch
exceptions of that type plus any of its subclass, thus causing a catch statement with
subclass exception a non- reachable code which is error in JAVA”.

Example:

10 | P a g e
In the example, two catch statement are used but
first one is of type Exception which is a superclass
of ArithmeticException (used in second catch). So
any exception thrown will be caught by first catch
block which makes second block unreachable and
error is shown during compile time

Output

However if the order of the catch blocks is reversed like shown below, then program will

xecute normally

11 | P a g e
Finally Block

The finally keyword is used to create a block of code that follows a try block. A finally block of
code always executes, whether or not an exception has occurred. Using a finally block allows
you to run any cleanup-type statements that you want to execute, no matter what happens in
the protected code.

Example of Finally Statement

12 | P a g e
Output 1

In the first case no command line arguments are passed which will throw
ArrayIndexOutOfBoundsException and in the above code we are handling only
ArithmeticExceptionwhichwillcausethesystemtoterminateandremainingprogramwillnot
run.Butinthiscasealsothestatementwritteninthefinallyblockwillgetsexecutedasshown below:

In second case ‘0’ is passed as command line argument to let program throw
ArithmeticException which will eventually be handled by catch block. See the output below
whichclearlyshowsthatremainingpartofthecodewillalsorunalongwithfinallystatement.

In third case ‘5’ is passed as command line argument which is perfectly fine and in this case
no exception will be throws. Now see the output below, in this case also finally statement will

13 | P a g e
get executed.

Throw Keyword

The throw keyword is used to explicitly throw an exception. We can throw either checked or
unchecked exception. The throw keyword is normally used to throw custom exception.

Example

In the example shown below a method validage(inti) is used which will check the value of
passedparameteriandifthevalueislessthan18thanaArithmeticExceptionisthrown.Now as you
can see when we have called the method no try catch block is used which results in
termination of the program and message is displayed as “not valid” which is passed during
throwing of ArithmeticExceptionobject.

14 | P a g e
Output

Howeverifduringcallofvalidagemethodtry-catchblockhasbeenusedthentheprogramwill
runnormally

Output

Throws Keyword

The throws keyword is used to declare the exception, it provide information to the
programmerthattheremayoccuranexceptionsoduringcallofthatmethod,andprogrammer
mustuseexceptionalhandlingmechanism.Throwskeywordisalsousedtopropagatechecked
exception.

Example

15 | P a g e
In this example, exception is created by extending Exception class and the custom exception
is declared in the method validage(inti)

Code to create custom exception with


name “ajexception”

Case 1: During call of validage method exceptional handling is not used and code looks like
this and error is displayed in the compilation of the code.

Output

Case 2: During call of method validage exceptional handling is used with try-catch keyword
like this and the program runs as expected.

16 | P a g e
Output:

Case 3: During call of method validage exceptional handling is used without try-catch
keyword and throws keyword is used in main method as shown below

There will be no error now during compile time, but program will gets terminated when
exception event takes place.

Output

Case 4: Try to propagate custom exception not of type Runtime Exception without declaring
in method using throws keyword. This will give compile time error

17 | P a g e
Output:

Case 5: Make custom exception by extending RunTime Exception Class and try the same
method as use for Case 4. There will be no error now and the program runs as expected

Output

Important Points in Exceptional Handling

 A catch clause cannot exist without a try statement.

 Itisnotcompulsorytohavefinallyclauseswheneveratry/catchblockispresent.

 Thetryblockcannotbepresentwithouteithercatchclauseorfinallyclause.

 Any code cannot be present in between the try, catch, finally blocks.

Declaring your Own Exceptions

You can create your own exceptions in Java. Keep the following points in mind when
writing your own exception classes:

 All exceptions must be a child of Throwable.

 If you want to write a checked exception that is automatically enforced by the


Handle or Declare Rule, you need to extend the Exception class.

 If you want to write a runtime exception, you need to extend the Runtime
Exception lass.

18 | P a g e
UNIT-III
Chapter 9: I/O Streams
An I/O Stream represents an input source or an output destination. A stream can represent
many different kinds of sources and destinations, including disk files, devices, other programs,
and memory arrays.

Streams support many different kinds of data, including simple bytes, primitive data
types, localized characters, and objects. Some streams simply pass on data; others manipulate
and transform the data in useful ways.

No matter how they work internally, all streams present the same simple model to
programs that use them: A stream is a sequence of data. A program uses an input stream to read
data from a source, one item at a time:

Reading information into a program.

A program uses an output stream to write data to a destination, one item at time:

The data source and data destination pictured above can be anything that holds,
generates, or consumes data. Obviously this includes disk files, but a source or destination can
also be another program, a peripheral device, a network socket, or an array.

19 | P a g e
There are two kinds of Streams −InPutStream − The InputStream is used to read data
from a source. OutPutStream − The OutputStream is used for writing data to a destination.

Byte Streams

Java byte streams are used to perform input and output of 8-bit bytes. Though there are
many classes related to byte streams but the most frequently used classes are, FileInputStream
and FileOutputStream.

Programs use byte streams to perform input and output of 8-bit bytes. All byte stream
classes are descended from InputStream and OutputStream.

There are many byte stream classes. To demonstrate how byte streams work, we'll focus on the
file I/O byte streams, FileInputStream and FileOutputStream. Other kinds of byte streams
are used in much the same way; they differ mainly in the way they are constructed.

Using Byte Streams

We'll explore FileInputStream and FileOutputStream by examining an example


program named CopyBytes, which uses byte streams to copy input.txt, one byte at a time.
Following is an example which makes use of these two classes to copy an input file into an
output file

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyBytes {


public static void main(String[] args) throws IOException {

FileInputStream in = null;
FileOutputStream out = null;

try {
in = new FileInputStream("input.txt");
out = new FileOutputStream("output.txt");
int c;

while ((c = in.read()) != -1) {


out.write(c);
}
} finally {
if (in != null) {
in.close();
}

20 | P a g e
if (out != null) {
out.close();
}
}
}
}

CopyBytes spends most of its time in a simple loop that reads the input stream and writes the
output stream, one byte at a time, as shown in the following figure.

Simple byte stream input and output.

Notice that read() returns an int value. If the input is a stream of bytes, why doesn't
read() return a byte value? Using a int as a return type allows read() to use -1 to indicate that
it has reached the end of the stream.

Character Streams

The Java platform stores character values using Unicode conventions. Character stream
I/O automatically translates this internal format to and from the local character set. In Western
locales, the local character set is usually an 8-bit superset of ASCII.

For most applications, I/O with character streams is no more complicated than I/O with byte
streams. Input and output done with stream classes automatically translates to and from the local
character set. A program that uses character streams in place of byte streams automatically
adapts to the local character set and is ready for internationalization — all without extra effort by
the programmer.

21 | P a g e
If internationalization isn't a priority, you can simply use the character stream classes without
paying much attention to character set issues. Later, if internationalization becomes a priority,
your program can be adapted without extensive recoding. See the Internationalization trail for
more information.

Using Character Streams

All character stream classes are descended from Reader and Writer. As with byte streams, there
are character stream classes that specialize in file I/O: FileReader and FileWriter. The
CopyCharacters example illustrates these classes.

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class CopyCharacters {


public static void main(String[] args) throws IOException {

FileReader inputStream = null;


FileWriter outputStream = null;

try {
inputStream = new FileReader("input.txt");
outputStream = new FileWriter("characteroutput.txt");

int c;
while ((c = inputStream.read()) != -1) {
outputStream.write(c);
}
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
}
}

CopyCharacters is very similar to CopyBytes. The most important difference is that


CopyCharacters uses FileReader and FileWriter for input and output in place of
FileInputStream and FileOutputStream. Notice that both CopyBytes and CopyCharacters
use an int variable to read to and write from. However, in CopyCharacters, the int variable
holds a character value in its last 16 bits; in CopyBytes, the int variable holds a byte value in its
last 8 bits.

22 | P a g e
Buffered Streams

Most of the examples we've seen so far use unbuffered I/O. This means each read or write
request is handled directly by the underlying OS. This can make a program much less efficient,
since each such request often triggers disk access, network activity, or some other operation that
is relatively expensive.

To reduce this kind of overhead, the Java platform implements buffered I/O streams. Buffered
input streams read data from a memory area known as a buffer; the native input API is called
only when the buffer is empty. Similarly, buffered output streams write data to a buffer, and the
native output API is called only when the buffer is full.

A program can convert an unbuffered stream into a buffered stream using the wrapping idiom
we've used several times now, where the unbuffered stream object is passed to the constructor
for a buffered stream class. Here's how you might modify the constructor invocations in the
CopyCharacters example to use buffered I/O:

inputStream = new BufferedReader(new FileReader("xanadu.txt"));


outputStream = new BufferedWriter(new FileWriter("characteroutput.txt"));

There are four buffered stream classes used to wrap unbuffered streams: BufferedInputStream
and BufferedOutputStream create buffered byte streams, while BufferedReader and
BufferedWriter create buffered character streams.

Flushing Buffered Streams

It often makes sense to write out a buffer at critical points, without waiting for it to fill. This is
known as flushing the buffer.

Some buffered output classes support autoflush, specified by an optional constructor argument.
When autoflush is enabled, certain key events cause the buffer to be flushed. For example, an
autoflush PrintWriter object flushes the buffer on every invocation of println or format. See
Formatting for more on these methods.

To flush a stream manually, invoke its flush method. The flush method is valid on any output
stream, but has no effect unless the stream is buffered.

Scanning and Formatting

Programming I/O often involves translating to and from the neatly formatted data humans like to
work with. To assist you with these chores, the Java platform provides two APIs. The scanner

23 | P a g e
API breaks input into individual tokens associated with bits of data. The formatting API
assembles data into nicely formatted, human-readable form.

Scanning

Objects of type Scanner are useful for breaking down formatted input into tokens and translating
individual tokens according to their data type.

Breaking Input into Tokens

By default, a scanner uses white space to separate tokens. (White space characters include
blanks, tabs, and line terminators. For the full list, refer to the documentation for
Character.isWhitespace.) To see how scanning works, let's look at ScanXan, a program that
reads the individual words in xanadu.txt and prints them out, one per line.

import java.io.*;
import java.util.Scanner;

public class ScanXan {


public static void main(String[] args) throws IOException {

Scanner s = null;

try {
s = new Scanner(new BufferedReader(new FileReader("xanadu.txt")));

while (s.hasNext()) {
System.out.println(s.next());
}
} finally {
if (s != null) {
s.close();
}
}
}
}

Formatting

Stream objects that implement formatting are instances of either PrintWriter, a character
stream class, or PrintStream, a byte stream class.

24 | P a g e
The only PrintStream objects you are likely to need are System.out and System.err. (See
I/O from the Command Line for more on these objects.) When you need to create a formatted
output stream, instantiate PrintWriter, not PrintStream.

Like all byte and character stream objects, instances of PrintStream and PrintWriter
implement a standard set of write methods for simple byte and character output. In addition,
both PrintStream and PrintWriter implement the same set of methods for converting internal
data into formatted output. Two levels of formatting are provided:

 print and println format individual values in a standard way.


 format formats almost any number of values based on a format string, with many options
for precise formatting.

The print and println Methods

Invoking print or println outputs a single value after converting the value using the
appropriate toString method. We can see this in the Root example:

public class Root {


public static void main(String[] args) {
int i = 2;
double r = Math.sqrt(i);

System.out.print("The square root of ");


System.out.print(i);
System.out.print(" is ");
System.out.print(r);
System.out.println(".");

i = 5;
r = Math.sqrt(i);
System.out.println("The square root of " + i + " is " + r + ".");
}
}

Here is the output of Root:

The square root of 2 is 1.4142135623730951.


The square root of 5 is 2.23606797749979.

The i and r variables are formatted twice: the first time using code in an overload of print, the
second time by conversion code automatically generated by the Java compiler, which also
utilizes toString. You can format any value this way, but you don't have much control over the
results.

25 | P a g e
Data Streams

Data streams support binary I/O of primitive data type values (boolean, char, byte, short,
int, long, float, and double) as well as String values. All data streams implement either the
DataInput interface or the DataOutput interface. This section focuses on the most widely-used
implementations of these interfaces, DataInputStream and DataOutputStream.

The DataStreams example demonstrates data streams by writing out a set of data records,
and then reading them in again. Each record consists of three values related to an item on an
invoice, as shown in the following table:

Order
Data Data Sample
in Output Method Input Method
type description Value
record
1 double Item price DataOutputStream.writeDouble DataInputStream.readDouble 19.99
2 int Unit count DataOutputStream.writeInt DataInputStream.readInt 12
Item "Java T-
3 String DataOutputStream.writeUTF DataInputStream.readUTF
description Shirt"

Let's examine crucial code in DataStreams. First, the program defines some constants containing
the name of the data file and the data that will be written to it:

static final String dataFile = "invoicedata";

static final double[] prices = { 19.99, 9.99, 15.99, 3.99, 4.99 };


static final int[] units = { 12, 8, 13, 29, 50 };
static final String[] descs = {
"Java T-shirt",
"Java Mug",
"Duke Juggling Dolls",
"Java Pin",
"Java Key Chain"
};

Then DataStreams opens an output stream. Since a DataOutputStream can only be created as a
wrapper for an existing byte stream object, DataStreams provides a buffered file output byte
stream.

out = new DataOutputStream(new BufferedOutputStream(


new FileOutputStream(dataFile)));

DataStreams writes out the records and closes the output stream.

for (int i = 0; i < prices.length; i ++) {


out.writeDouble(prices[i]);

26 | P a g e
out.writeInt(units[i]);
out.writeUTF(descs[i]);
}

Object Streams

Just as data streams support I/O of primitive data types, object streams support I/O of
objects. Most, but not all, standard classes support serialization of their objects. Those that do
implement the marker interface Serializable.

The object stream classes are ObjectInputStream and ObjectOutputStream. These


classes implement ObjectInput and ObjectOutput, which are subinterfaces of DataInput and
DataOutput. That means that all the primitive data I/O methods covered in Data Streams are
also implemented in object streams. So an object stream can contain a mixture of primitive and
object values. The ObjectStreams example illustrates this. ObjectStreams creates the same
application as DataStreams, with a couple of changes. First, prices are now BigDecimalobjects,
to better represent fractional values. Second, a Calendar object is written to the data file,
indicating an invoice date.

If readObject() doesn't return the object type expected, attempting to cast it to the
correct type may throw a ClassNotFoundException. In this simple example, that can't happen,
so we don't try to catch the exception. Instead, we notify the compiler that we're aware of the
issue by adding ClassNotFoundException to the main method's throws clause.

Output and Input of Complex Objects

The writeObject and readObject methods are simple to use, but they contain some very
sophisticated object management logic. This isn't important for a class like Calendar, which just
encapsulates primitive values. But many objects contain references to other objects. If
readObject is to reconstitute an object from a stream, it has to be able to reconstitute all of the
objects the original object referred to. These additional objects might have their own references,
and so on. In this situation, writeObject traverses the entire web of object references and writes
all objects in that web onto the stream. Thus a single invocation of writeObject can cause a
large number of objects to be written to the stream.

This is demonstrated in the following figure, where writeObject is invoked to write a single
object named a. This object contains references to objects b and c, while b contains references to
d and e. Invoking writeobject(a) writes not just a, but all the objects necessary to reconstitute
a, so the other four objects in this web are written also. When a is read back by readObject, the
other four objects are read back as well, and all the original object references are preserved.

27 | P a g e
I/O of multiple referred-to objects

You might wonder what happens if two objects on the same stream both contain
references to a single object. Will they both refer to a single object when they're read back? The
answer is "yes." A stream can only contain one copy of an object, though it can contain any
number of references to it. Thus if you explicitly write an object to a stream twice, you're really
writing only the reference twice. For example, if the following code writes an object ob twice to
a stream:

Object ob = new Object();


out.writeObject(ob);
out.writeObject(ob);

Each writeObject has to be matched by a readObject, so the code that reads the stream
back will look something like this:

Object ob1 = in.readObject();


Object ob2 = in.readObject();

This results in two variables, ob1 and ob2, that are references to a single object.

However, if a single object is written to two different streams, it is effectively duplicated


— a single program reading both streams back will see two distinct objects.

28 | P a g e

You might also like