Transcript

Introduction to Computer Science

• Packages• Polymorphism• Interfaces• Exceptions• Streams – input/output

Unit 12Unit 12

12- 2

Packages

• Java classes are placed into directories (or folders) on the computer

• The classes in each directory form a package

• This helps organize classes, and also gives another way of controlling access among classes

• Example: java.applet is the package of classes in subdirectory "applet" under the directory "java" (whose location varies depending on the system)

12- 3

Sample Packages that come with the Java API (continually evolving)

java.applet Classes for implementing applets

java.awt For graphics, windows, GUIs

java.awt.event For AWT event-handling model

java.awt.image Classes for image processing

java.awt.peer Interface defs, platform-indep. GUIs

java.io Classes for input and output

java.lang Basic language classes (String, Math)

java.net Classes for networking

java.util Useful auxiliary classes, like Date

12- 4

Direct Use of Java API Class

• To use, for example, the class Math in the package java.lang, it is possible to use the fully-qualified name:

x = java.lang.Math.sqrt(3);

12- 5

Importing Classes

• Of course, it's more convenient to do it the way we've been doing it, using the import statement; either

import package_name.class_name;

or

import package_name.*;

12- 6

Importing

import package_name.class_name;

allows class_name to be used without giving the full package name

import package_name.*;

allows all classes in the package to be used without qualifying their names

12- 7

Example of import

java.util.Date d = new java.util.Date( );java.awt.Point p = new java.awt.Point(1, 2);java.awt.Button b = new java.awt.Button( );

can be abbreviated as

import java.util.Date;import java.awt.*;…Date d = new Date( );Point p = new Point(1, 2);Button b = new Button( );

12- 8

It's Always There

• Java always assumes that the classes in java.lang (basic language classes, such as String and Math) are available

• It's as if you have the statement

import java.lang.*;

at the beginning of every program

12- 9

Packages You Define

• All of the .class files placed in one directory belong to the same, unnamed package

• To cause a class to be placed in a particular named package:–Put the .class file in the appropriate directory

–Compile the class with the package statement, which must be the first non-comment line in the Java source file:

package package-name;

12- 10

Classes in Different Packages

• Classes in different packages obviously have different fully-qualified names

• Classes in different packages also have different rules regarding the visibility of names

12- 11

Example:Visibility of Instance Variables

• A public instance variable is visible to all other classes

• A private instance variable is visible only to the methods of its class

• If it is declared neither public nor private, then it has "package visibility"; it is visible to methods defined in other classes in the same package as its class

• Same rules apply to static variables and instance and static methods

12- 12

Similarly for Classes

• A class declared public is visible to all classes

• A class not declared public is visible to the classes in its own package

• A class cannot be declared private

12- 13

private, public, protected

• Private variables and methods: no access by clients or by subclasses

• Public variables and methods: accessed by clients and by subclasses

• Default (no label): variables and methods have package visibility, accessible only to clients and subclasses in the same package

12- 14

Protected

• We might want to give subclasses access to variables and methods without allowing clients to have access

• That's the purpose of another category of accessibility: protected

• Members declared protected are visible to other classes in the same package, and to subclasses in other packages, but not to clients in other packages

12- 15

Two Kinds of Visibility

• Inherited Visibility and Direct Access Visibility:

class A {int _x;…

}

class B extends A {… _x … // inherited visibility of x… A._x … // direct access visibility of x

}

12- 16

Summary of Visibility

Visibility public default protected private

clients in D D D nonesame package

clients in D none none nonedifferent package

subclass in D & I D & I D & I nonesame package

subclass in D & I none I nonedifferent package

I = inherited access, D = direct access

12- 17

Using Protected

• When there's a possibility that a class will have subclasses (and you want the attributes and methods to be usable in the inheritance hierarchy), you should use protected

• Inherited protected variables and methods are considered to be protected members of the subclass (visible to further subclasses, and hidden from clients)

• Inherited public variables and methods are considered to be public members of the subclass (visible to everyone)

class PreciseTime extends Time {…

public void printTime ( ) { if ((_hour == 0) && (_minute == 0))

System.out.print(“midnight”); else if ((_hour == 12) && (_minute == 0))

System.out.print(“noon”); else {

if (_hour == 0) System.out.print(12);else if (_hour > 12) System.out.print(_hour - 12);else System.out.print(_hour);

if (_minute < 10) System.out.print(“:0”+ _minute);else System.out.print(“:” + _minute);if (_second < 10) System.out.print(“:0”+ _second);else System.out.print(“:” + _second);

if (_hour < 12) System.out.print(“AM”);else System.out.print(“PM”);

}}

}

Now we overrideprintTime( )

12- 19

Doesn't Work

• Problem is, it doesn't work: the new printTime accesses _hour and _minute, private instance variables of class Time

• So we need to change the definition of class Time:class Time {

protected int _hour, _minute;…

}• Still no access to _hour and _minute from regular

clients of Time, just to PreciseTime and other subclasses of Time

12- 20

Constructors for Subclasses

• Java guarantees that a class’s constructor method is called whenever an instance of that class is created

• It also guarantees that the constructor is called whenever an instance of any subclass is created

• Therefore, every constructor method must call (explicitly or implicitly) its superclass constructor method

12- 21

Constructors for Subclasses

• If we have an inheritance hierarchy:class B

|subclass C of B

|subclass D of C

…subclass F of …

|subclass G of F

If a new object of class G is created, the constructors will be called in order B, C, D, … , F, G (i.e., G calls F, which calls E,…)

12- 22

Constructor Chaining

• If the first statement in a constructor is not an explicit call to a constructor of the superclass (using super), or an explicit call to another constructor in the same class (using this), then Java implicitly inserts the call super( ) (i.e., super with no arguments)

• Even if this is used to invoke another constructor in the same class, eventually some constructor will (explicitly or implicitly) invoke the superclass constructor

• If the superclass has no zero-argument constructor, the implicit super( ) causes a compilation error

12- 23

super( )

• Therefore, if a superclass doesn't have a zero-argument constructor, the subclass must explicitly call the superclass's constructor with arguments:

class C extends B {…public C (…) {

super( B's constructor arguments );

…}

}

12- 24

super( )

• The call to super(…) must be the first statement in the body of C's constructor

• The constructor for PreciseTime made use of this feature, calling super(h, m) to allow the Time constructor to do initialization

public PreciseTime(int h, int m, int s) {super(h, m);_second = s;

}

12- 25

Dynamic Binding

• I said that a PreciseTime object is also (kind of) a Time object

• It's a useful way of thinking about it, and it is the basis for a very powerful feature of Java, dynamic binding

• A PreciseTime object can be used almost anywhere that a Time object can be used

12- 26

Several Passes at Polymorphism

• Polymorphism means “taking many forms”: a reference of a given class can adapt take the form of any of its subclasses.

• First we will look at the polymorphism and dynamic binding quickly – a few key facts

• Then we will look at it in depth – this set of slides adapted (with permission) from:www.cc.gatech.edu/classes/AY2002/cs1322_spring/slides/

current/CS2_22_PolymorphismDynamicBinding.ppt

12- 27

This is legal, blurring the distinction of Time and PreciseTime

• A Time variable (like dawn) can contain a reference to a PreciseTime object

• More generally, a CCC variable can contain a reference to any object of any class in CCC's subclass hierarchy (down the tree – but not up the tree)

Time dawn;dawn = new PreciseTime(3, 45, 30);

12- 28

There's an order to this

Time dawn;

dawn

heap

12- 29

This is legal, blurring the distinction of Time and PreciseTime

Time dawn;dawn = new PreciseTime(3, 45, 30);

dawn

dawnAttributes: _hour = 3 _minute = 45 _second = 30Methods: …

heap

12- 30

So now what?

• What happens if we send dawn the printTime( ) message?dawn.printTime( );printTime( ) is defined in both Time and PreciseTime classes

• dawn was declared as a Time variable, but the actual object in dawn is a PreciseTime object

• So the printTime( ) defined in the PreciseTime class will be used

12- 31

Static Binding of Methods

• Before we had subclasses, life was simple

• The Java compiler could always figure out, without running the program, which instance method would be invoked

• The ability to know the exact method that will be invoked every time a message is sent is called static binding of methods

12- 32

Dynamic Binding

• This is no longer true when we have subclasses

• It is possible to specify in a program that there's an object of some class, B (i.e., the object is defined as being referenced by a variable of type B)

• B has subclasses C and D• C and D each provide their own

definition of method f ( )

B newObj;

B

C D

12- 33

Dynamic Binding

• The actual creation of the object (C or D) only occursat runtime

• Therefore, the compilercan't know, when the object newObj is sent f ( ), whether it will be handled by the C definition or the D definition; we can only know at runtime

if (x == 7) newObj = new C( );else newObj = new D( );

newObj.f( );

Using f( ) from class C or D?

x might come from the user

12- 34

Polymorphism Pass 2:More In Depth

• Polymorphism is an important concept that is a part of Object Oriented Programming

• We often would like to deal with a collection of various types of objects. We want to process members of that group in a generic way. Yet in the end, we’d like specific and appropriate behavior to still occur.

• This set of slides adapted (with permission) from:www.cc.gatech.edu/classes/AY2002/cs1322_spring/slides/current/ CS2_22_PolymorphismDynamicBinding.ppt

12- 35

Polymorphism

• Example: We have an array of animals, each of which is an object of one subclass out of several possible subclasses of Animal. The array is declared to have Animal as its element type. Now we’d like to process through the array and have each element invoke a makeNoise() method.

• Luckily when a method call is made, the compiler isn’t too concerned about the specifics of the method being called. It’s question is: “is there a method with a matching signature?”

12- 36

Array of Animals

• Fill an array with Bird, Dog, Fish – but the array is an array of Animal

Animal

Bird Dog Fish

[0] [1] [2]

An array of Animal – we want to fill it with different instances of animals, but send the same message to each – they each will respond differently

extendsextends extends

12- 37

PolymorphismPolymorphism

class Animal { public void makeNoise ( ) { System.out.println("I am an animal."); } // of makeNoise} // of Animal

class Fish extends Animal { public void makeNoise( ) { System.out.println("Glug glug gurgle gurgle"); } // of makeNoise} // of Fish

class Bird extends Animal { public void makeNoise( ) { System.out.println("Tweet tweet flap flap"); } // of makeNoise} // of Bird

12- 38

PolymorphismPolymorphism (cont’d) (cont’d)

class Dog extends Animal {

public void makeNoise( ) { System.out.println("Sniff sniff woof woof"); } // of makeNoise

public void bark( ) { System.out.println("Arf Arf"); } // of bark

} // of Dog

12- 39

PolymorphismPolymorphism

public class Driver { public static void main (String[ ] argv) { Animal[ ] animalArray = new Animal[3]; int index;

animalArray[0] = new Bird( ); animalArray[1] = new Dog( ); animalArray[2] = new Fish( ); for (index = 0; index < animalArray.length; index++) { animalArray[index].makeNoise( ); } // of for } // of main} // of Driver

the Animal class has makeNoise, so any member of the array can makeNoise

Output: Tweet tweet flap flap Sniff sniff woof woof Glug glug gurgle gurgle

12- 40

Polymorphism and Dynamic Binding

• Polymorphism & Dynamic Binding together insure that the correct makeNoise( ) method will always be called.

• An object of a subclass can be substituted for its superclass, e.g., a bird for an animal.

“A bird is a animal.” Yes.

• The reverse is not true: can’t substitute superclass for a subclass, e.g., CANNOT substitute an animal for a bird.

“An animal is a bird?” No. Not necessarily.

12- 41

instanceof

• The keyword instanceof is used to ask an object if it is an instance of the specified class, e.g., "Is this particular animal of class Dog?"

(d instanceof Dog)

• It’s a boolean relation, returning true or false:

if (d instanceof Dog) {…

}

12- 42

public class Driver2 { public static void main(String[ ] argv) { Animal[ ] = animalArray[3]; Dog d; int i; animalArray[0] = new Bird( ); animalArray[1] = new Dog( ); animalArray[2] = new Fish( ); for (i = 0; i < animalArray.length; i++) if (animalArray[i] instanceof Dog){

d = (Dog) animalArray[i]; d.bark( ); } // if } // main} // Driver2

Casting with PolymorphismCasting with Polymorphism

We cast before calling bark()because only dogs can bark. Not all Animals can execute the method

12- 43

Upcasting

• Why didn’t we have to explicitly cast Bird, Dog and Fish to Animal when we put the instances into the array on the previous slide?

• Because this is upcasting – casting from a derived class to a base class – and Java does it for us automatically

• You can also write it explicitly if you want (no harm done)

12- 44

Casting a Superclass to a Subclass

• Casting used here to give an object of a superclass the form of the appropriate subclass. If we just wrote:

if (animalArray[i] instanceof Dog) {animalArray[i].bark();

}

it would produce an error because objects of class Animal have no method called bark. So, we first cast the object that instanceof tells us is indeed a Dog object, as a Dog.

if (animalArray[i] instanceof Dog) {d = (Dog) animalArray[i]d.bark( );

}

12- 45

Why is Casting Necessary Here?

• If Java can determine that a given Animal is or is not a Dog (via instanceof), then why do we need to cast it to a Dog object before Java can recognize that it can bark?

• Why can’t Java do it for us automatically?

• Answer: the difference between compile-time and run-time type checking.

12- 46

Why is Casting Necessary Here?

Sourcecode

CompileBytecode

JVMInterpreter

Programruns

errors errors

Compile-time Errors:

• Those that are discernable without the program executing.

• Question of language legality: "Is this a legal statement?" e.g., index = strName;

Statement is not legal.

Run-time Errors:

• Those that are discernable only when the program is running with actual data values.

• Question of execution legality: "Is it legal for this variable to have the actual value assigned to it?", e.g.,

animalArray[<badIndex>] = someAnimal

Statement legal, but particular index value isn’t.

12- 47

Why is Casting Necessary Here?

if (animalArray[i]instanceof Dog) {

animalArray[i].bark();}

if (animalArray[i] instanceof Dog) { d = (Dog) animalArray[i]; d.bark( );}

• 1st line is legal. 2nd line isn’t (unless array has Dog). We can see that 1st line guarantees 2nd is legal.• Compiler cannot see inter-statement dependencies… unless compiler runs whole program with all possible data sets!• Runtime system could tell easily. . . BUT. . . We want most checking at compile-time for reasons of bothperformance and correctness.

• Here, legality of each line of code can be evaluated at compile time.• Legality of each line discernable without worrying about inter-statement dependencies, i.e., each line can stand by itself.• Can be sure that code is legal (not sometimes-legal).

A Good Use for Casting: Resolving polymorphic ambiguities for the compiler.

12- 48

How Objects Are CreatedDog d = new Dog();

An implicit super() calls parent class constructor first.After all, a Dog is-a Animal, && is-a Object

d

Animal

Dog

Object

d

Animal

Dog

Object

d

Animal

Dog

Object

1.1.1.1. 2.2.2.2. 3.3.3.3.

Execution Time

12- 49

Multiple References to Different Types of the Same Instance

a

Animal

Dog

Object

Animal a = new Dog(); Object o = a;

a

Animal

Dog

Objecto

We can create new references that point to different types in the same block of memory.

12- 50

Dynamic Binding

a

Animal

Dog

Objecto

System.out.println(o.toString());

.toString()

.toString()

.toString()

Dynamic binding provides runtime resolution to themost specific implementation possible.

When calling a method on a reference, the method must be present in the type (or inherited). However, the specific implementation called is determined at runtime. That’s ‘dynamic binding’.

12- 51

Casting and Polymorphism

o.doYourThing(); // ERROR!

The calling type must have the method, either inits instance, or from its parent.

a

Animal

Dog

Objecto

.doYourThing()

.doYourThing()

No MethodNo Method Dynamic binding

does not work miracles. The reference type must have the method available (in the present class or inherited), or else a compilation error occurs.

12- 52

The organizing principle is the shared inherited relationship with Animal. Since Fish, Dog and Bird all extend from Animal, we can make an Animal array to hold different expressions of this class.

What Should Our Array Elements Be?

So, we have these three blocks, representing objects in memory, each different, holding unique references and primitive values. How can these disparate objects be held in an array, which must be heterogeneous?

ObjectObjecttoString()

AnimalAnimalint numLegs = 2String strTypetoString();move();

BirdBirdmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 0String strTypetoString();move();

FishFishmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 3String strTypetoString();move();

DogDogmove();bark();

12- 53

We could also have made an array of Object types. But we then will have problems invoking methods on members of this array, since Object lacks key methods--like move().

What Should Our Array Elements Be?

So, we have these three blocks, representing objects in memory, each different, holding unique references and primitive values. How can these disparate objects be held in an array, which must be heterogeneous?

ObjectObjecttoString()

AnimalAnimalint numLegs = 2String strTypetoString();move();

BirdBirdmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 0String strTypetoString();move();

FishFishmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 3String strTypetoString();move();

DogDogmove();bark();

12- 54

So we select Animal as our common type. It’s the most specific type, and yet is still held in common by all the members we plan to hold in the array.

What Should Our Array Elements Be?

So, we have these three blocks, representing objects in memory, each different, holding unique references and primitive values. How can these disparate objects be held in an array, which must be heterogeneous?

ObjectObjecttoString()

AnimalAnimalint numLegs = 2String strTypetoString();move();

BirdBirdmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 0String strTypetoString();move();

FishFishmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 3String strTypetoString();move();

DogDogmove();bark();

12- 55

Multiple References to Instance

ObjectObjecttoString()

AnimalAnimalint numLegs = 2String strTypetoString();move();

BirdBirdmove();

Recall that we can have many reference types pointing to the same Fish or Dog or Bird instance in memory. Thus, since arrays must be of a single type, we just polymorph any references we have into Animal references.

Bird bTemp = new Bird();Object oTemp = (Object) bTemp;Animal aTemp = (Animal) bTemp;

aTemp bTempoTemp

Here, the castingis not needed since we areupcastingupcasting.

It’s shown to be explicit.

12- 56

Array Elements are of a Single Type

ObjectObjecttoString()

AnimalAnimalint numLegs = 2String strTypetoString();move();

BirdBirdmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 0String strTypetoString();move();

FishFishmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 3String strTypetoString();move();

DogDogmove();bark();

Animal [ ]Animal [ ]

final int length = 3

ObjectObject

toString();

[ 0 ] [ 1 ] [ 2 ]

Thus, when we have many objects in memory, we polymorph our references to the instances. This gives us an array of Animal types, even though each instance is a different subclass.

Let’s invoke some methods on these objects.

ObjectObjecttoString()

AnimalAnimalint numLegs = 2String strTypetoString();move();

BirdBirdmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 0String strTypetoString();move();

FishFishmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 3String strTypetoString();move();

DogDogmove();bark();

Animal [ ]Animal [ ]

final int length = 3

ObjectObjecttoString();

Is our picture correct?

What if we executed this code:

Object oTemp;oTemp = animalArray[1];

oTemp

No. The codeNo. The codeworks. But our drawing is works. But our drawing is

pointing to the wrongpointing to the wrongpart of our objectpart of our object

Object

ObjectObjecttoString()

AnimalAnimalint numLegs = 2String strTypetoString();move();

BirdBirdmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 0String strTypetoString();move();

FishFishmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 3String strTypetoString();move();

DogDogmove();bark();

Animal [ ]Animal [ ]

final int length = 3

ObjectObjecttoString();

Is our picture correct?

What if we executed this code:

Object oTemp;oTemp = animalArray[1];

oTemp

Much better. ThisMuch better. Thisfussiness will payfussiness will pay

off shortly.off shortly.

ObjectObjecttoString()

AnimalAnimalint numLegs = 2String strTypetoString();move();

BirdBirdmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 0String strTypetoString();move();

FishFishmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 3String strTypetoString();move();

DogDogmove();bark();

Animal [ ]Animal [ ]

final int length = 3

ObjectObjecttoString();

Now, let’s add another line of code:

Object oTemp;oTemp = animalArray[1];oTemp.move();

oTemp

Does this work?

NO. The class Object

has no method called move()

ObjectObjecttoString()

AnimalAnimalint numLegs = 2String strTypetoString();move();

BirdBirdmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 0String strTypetoString();move();

FishFishmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 3String strTypetoString();move();

DogDogmove();bark();

Animal [ ]Animal [ ]

final int length = 3

ObjectObjecttoString();

The fix is in:

Object oTemp;oTemp = animalArray[1];Animal aTemp = (Animal) oTemp;

oTemp

aTemp

Note the explicitdown castingdown casting

was necessary.

ObjectObjecttoString()

AnimalAnimalint numLegs = 2String strTypetoString();move();

BirdBirdmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 0String strTypetoString();move();

FishFishmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 3String strTypetoString();move();

DogDogmove();bark();

Animal [ ]Animal [ ]

final int length = 3

ObjectObjecttoString();

The fix is in:

Object oTemp;oTemp = animalArray[1];Animal aTemp = (Animal) oTemp;aTemp.move();

oTemp

aTemp

Hmm... Let’s look atthis closely.

ObjectObjecttoString()

AnimalAnimalint numLegs = 2String strTypetoString();move();

BirdBirdmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 0String strTypetoString();move();

FishFishmove();

ObjectObjecttoString()

AnimalAnimalint numLegs = 3String strTypetoString();move();

DogDogmove();bark();

Animal [ ]Animal [ ]

final int length = 3

ObjectObjecttoString();

Object oTemp;oTemp = animalArray[1];Animal aTemp = (Animal) oTemp;aTemp.move();

oTemp

aTemp

ObjectObjecttoString()

FishFishmove();

AnimalAnimalint numLegs = 3String strTypetoString();move();

It looks like bothAnimal and Fishhave move( ) methods.

Which one gets called when the aTemp.move( ) line executes?

The reference typewe are using is an

Animal type. Would thatdetermine whether Animal

or Fish has their method called?

12- 63

Dynamic Binding

ObjectObjecttoString()

FishFishmove();

AnimalAnimalint numLegs = 3String strTypetoString();move();

Object oTemp;oTemp = animalArray[1];Animal aTemp = (Animal) oTemp;aTemp.move();

aTemp

Here, the principle of dynamic bindingdynamic binding will ensure that at run time, the most specific behavior will be invoked. Here, the Fish move() method is more specific than its parent method. So, the Fish’s move() method gets called with the aTemp.move() line.

Understand this term.Understand this term.Understand what is does.Understand what is does.

It is a It is a CORECORE feature of any Object feature of any Object

Oriented language.Oriented language.

12- 64

Sanity Check

ObjectObjecttoString()

FishFishmove();

AnimalAnimalint numLegs = 3String strTypetoString();move();

Object oTemp;oTemp = animalArray[1];Animal aTemp = (Animal) oTemp;System.out.println (oTemp.toString());

oTemp

What about:

System.out.println ( ((Object)oTemp).toString() );

What Happens Here?

Does castingsomehowoverpowerdynamicbinding?

12- 65

Sanity Check

ObjectObjecttoString()

FishFishmove();

AnimalAnimalint numLegs = 3String strTypetoString();move();

oTemp

System.out.println ( ((Object)oTemp).toString( ) );

What Happens Here?

No matterNo matterhow youhow you

cast things,cast things,dynamicdynamic

binding takesbinding takeshold. It’shold. It’slike the like the

law of gravitylaw of gravity..

Object oTemp;oTemp = animalArray[1];Animal aTemp = (Animal) oTemp;System.out.println (oTemp.toString());

What about:

12- 66

Sanity Check

ObjectObjecttoString()

FishFish

move();toString();

AnimalAnimalint numLegs = 3String strTypetoString();move();

oTemp

What if Fish had its owntoString()?

No matterNo matterhow youhow you

cast things,cast things,dynamicdynamic

binding takesbinding takeshold. It’shold. It’slike the like the

law of gravity.law of gravity.

Dynamic binding will always resolve, at run time, to themost specific version of the method. ALWAYS.ALWAYS.

Object oTemp;oTemp = animalArray[1];Animal aTemp = (Animal) oTemp;System.out.println (oTemp.toString());

12- 67

“Always?”

ObjectObjecttoString()

FishFish

move();toString();

AnimalAnimalint numLegs = 3String strTypetoString();move();

Object oTemp;oTemp = animalArray[1];oTemp.move(); // WRONG!

oTemp

Does dynamic bindingalso work miracles?

That is, does it letyou find methods in

extending classes, if thepresent class does nothave such a method?

NO. This would cause a compile time error. Java is strongly typedstrongly typed, meaning that each time you invoke a method, the method MUST be present in the class--even if dynamic binding would later find a more specific version. So: no, dynamic binding dynamic binding does not defeat type safety in Java.does not defeat type safety in Java.

No suchmethod move()

in Object

12- 68

Another example –A Hierarchy Diagram

File

RestrictedFile

Object

Has methods:public boolean isLocked()public void lock()public void unlock(long key)Redefines open() (only open file if it is unlocked; it’s locked at creation)

Has methods:public boolean isOpen()public void open()public void close()public String getName()

Has method (among others):public String toString()

12- 69

Sub-classes as Sub-types

• We can view a RestrictedFile object from 3 different points of views:–As a RestrictedFile. This is the most narrow

point of view (the most specific). This point of view ‘sees’ the full functionality of the object.

–As a File. This is a wider point of view (a less specific one). We forget about the special characteristics the object has as a RestrictedFile (we can only open and close the file).

–As a plain Object.

12- 70

Variables can Reference Sub-class Values

• We view an object by using an object reference.• A variable of type ‘reference to File’ can only

refer to any object which is a File.

• But a RestrictedFile is also a File, so f can also refer to a RestrictedFile object.

• The type of the reference we use determines the point of view we will have on the object.

File f = new File(“story.txt”);

File f = new RestrictedFile(“visa.dat”, 12345);

12- 71

RestrictedFile point of view

• If we refer to a RestrictedFile object using a RestrictedFile reference we have the RestrictedFile point of view – we see all the methods that are defined in RestrictedFile and up the hierarchy tree.

RestrictedFile f = new RestrictedFile(“visa.dat”, 12345);

f.close();

f.lock();

f.unlock(12345);

String s = f.toString();

12- 72

File point of view

• If we refer to a RestrictedFile object using a File reference we have the File point of view – which lets us use only methods that are defined in class File and up the hierarchy tree.

File f = new RestrictedFile(“visa.dat”, 12345);

f.close();

f.lock(); //Can’t use this method

f.unlock(12345); //Can’t use this method

String s = f.toString();

12- 73

Object point of view

• If we refer to a RestrictedFile object using an Object reference we have the Object point of view – which let us see only methods that are defined in class Object.

Object f = new RestrictedFile(“visa.dat”, 12345);

f.close(); //Can’t use this method

f.lock(); //Can’t use this method

f.unlock(12345); //Can’t use this method

String s = f.toString();

12- 74

Points of View

RestrictedFile

... isOpen isLocked key

toString() ... isOpen() open() close() lock() unlock(key) isLocked()

12- 75

Compile time-type vs.run-time type

• A variable of a reference type has a declared type that is known at compile time and never changes.

File f;• A reference variable may hold values of any subclass of

its declared type

• The type of the values held may change during the running of the algorithm and is not known during compile time

• The run-time type is always some subclass of the compile-time type.

f = new RestrictedFile(“visa.dat”,12345);

f = new File(“visa.dat”);

12- 76

RestrictedFile referenceRestrictedFile point of view

File referenceFile point of view

Widening

Widening

• Changing our point of view of an object, to a wider one (a less specific one) is called widening.File file;

file = new RestrictedFile(“visa.dat”, 1234);

12- 77

Point – distanceFrom

/** * A point on a grid. */public class Point {

/** * Computes the distance from another point * @param p The given point. */ public double distanceFrom(Point p) { int dx = x-p.x; int dy = y-p.y; return Math.sqrt(dx*dx+dy*dy); } // ... more methods}

12- 78

Pixel

/** * Represents a pixel on a graphical area. */public class Pixel extends Point {

// The color of the pixel private Color color; /** * Constructs a new pixel. * @param x,y The coordinates of the pixel. * @param color The color of the pixel. */ public Pixel(int x, int y, Color color) { super(x,y); this.color = color; } // ... more methods}

12- 79

Widening parameters

• In the following example, the method distanceFrom() expects a ‘reference to Point’ and gets ‘a reference to Pixel’, we are thus widening our point of view of the Pixel object.

Point p1;

Pixel p2;

p1 = new Point(2, 3);

p2 = new Pixel(5, 6, Color.red);

double d = p1.distanceFrom(p2);

12- 80

Compile-time vs. run-time: method invocation

• When we invoke a method on an object we always do it through a reference

• The implementation of the method which is most specific will be chosen.

• Java methods are virtual, i.e. the method which will be invoked is determined by the run-time type of object and not on the compile-time type of reference.

• The identity of the invoked method is determined at runtime.

• There are languages that use different mechanisms for method invocation.

12- 81

Type of Method is Determined at Runtime

File file;

if (Math.random() >= 0.5) file = new File(“visa.dat”);else file = new RestrictedFile(“visa.dat”, 76543); file.open();

Will the file be opened if the number randomly generated is less than 0.5?

12- 82

Another Example:Mouse in a Maze

public class Mouse {private instance variablespublic Point tellLocation( ) { … }public int tellDirection( ) { … }public Mouse(Maze m) { … }public void makeMove( ) { … }private boolean outside ( ) { … }private boolean facingWall( ) { … }private void stepForward( ) { … }private void turnLeft( ) { … }private void turnRight ( ) { … }

}

12- 83

Specialization through Inheritance

• So now we want to create two kinds of mice; only makeMove( ) will change

• RightMouse will have one strategy (right paw on wall)

• StraightMouse will have another strategy (go straight, turn right when can't go straight)

• No need to duplicate code; just make Mouse be a superclass, and RightMouse and StraightMouse only need to provide their own makeMove( ) code

12- 84

abstract

• We'll let the user specify which kind of mouse he wants at runtime

• The Mouse class will have all the methods and instance variables, except makeMove( )

• The Mouse class isn't intended to be used directly; we expect it to be subclassed

• To enforce this, we explicitly specify in Mouse that makeMove( ) is supposed to be implemented in a subclass

12- 85

abstract

public abstract void makeMove( );• This “prototype” is included in the Mouse class• "abstract" tells Java that makeMove( ) is expected

to be defined in a subclass• Any class that includes an abstract method is itself

abstract, and has to be declared abstract itself• Such an abstract class cannot be instantiated by a

client, you just have to subclass it and define its abstract methods

• So the Mouse class will be abstract

12- 86

abstract Class, subclassed

protected boolean _started;protected int _direction; etc.

public abstract void makeMove( ); etc.protected boolean facingWall( ) { return theMaze.checkWall

(_direction, location); }

abstract class Mouse

extends extends

public RightMouse(…) {…}

public void makeMove( ) {…}

RightMouse

public StraightMouse(…) {…}

public void makeMove( ) {…}

StraightMouse

12- 87

The new class Mouse

abstract class Mouse {public final int

NORTH=0, EAST=1, SOUTH=2, WEST=3;

protected Maze _theMaze;protected boolean _started = false;

//true once the maze is enteredprotected Point _location; //location of this mouseprotected int _direction; //direction mouse is facing

public Point tellLocation( ) { return _location; }public int tellDirection( ) { return _direction; }

public Mouse (Maze m) {// Where do I start?_location = m.getStartLocation( );// In what direction do I face initially?_direction = m.getStartDirection( );_theMaze = m;

}

public abstract void makeMove( );

protected boolean outside ( ) {// Am I outside the maze?

return _theMaze.outside(_location);}

protected boolean facingWall ( ) { return _theMaze.checkWall(_direction,

_location);}

protected void stepForward( ) {switch (direction) {

case NORTH: _location.y--; break;case EAST: _location.x++; break;case SOUTH: _location.y++; break;case WEST: _location.x--; break;

}}

protected void turnLeft( ) {_direction = (_direction + 3) % 4;

}

protected void turnRight( ) {_direction = (_direction + 1) % 4;

}}

12- 90

Definition of class RightMouse

class RightMouse extends Mouse {

public RightMouse (Maze aMaze ) { super(aMaze); }

public void makeMove( ) {if (_started) {

if ( !outside( ) ) {turnRight( );while ( facingWall( ) ) {

turnLeft( );}stepForward( );

}}else {

stepForward( );_started = true;

}}

}

12- 91

Definition of class StraightMouse

class StraightMouse extends Mouse {

public StraightMouse (Maze aMaze ) { super(aMaze); }

public void makeMove( ) {if (_started) {

if ( !outside( ) ) {if ( facingWall( ) ) {

turnRight( );makeMove( );

}else stepForward( );

}}

else {

stepForward( );_started = true;

}}

}

12- 92

Dynamic Generationof the Kind of Mouse

• Now, the main( ) method lets the user dynamically specify whether the mouse will be a RightMouse object or a StraightMouse object

• The variable referencing the mouse will be of class "Mouse", but the actual generation of the object (either type) occurs at runtime

12- 93

Runtime Selection

public class MouseMaze {public static void main (String[ ] args) {

Maze theMaze = new Maze( );Mouse speedy = selectMouse(theMaze);…

}private static Mouse selectMouse(Maze theMaze) {

SimpleInput sinp = new SimpleInput(System.in);while (true) { System.out.print("Choose RightMouse (0) "

+ "or StraightMouse (1): "); int i = sinp.readInt( ); if ( i == 0 ) return new RightMouse(theMaze); if ( i == 1 ) return new StraightMouse(theMaze);}

}}

12- 94

Class Inheritance plus Dynamic Method Binding

• speedy is a Mouse, but it might be a RightMouse or a StraightMouse

• When speedy is sent the makeMove( ) message, it will do whatever is appropriate for the kind of mouse it is

• The combination of Class Inheritance plus Dynamic Method binding is very powerful, allowing reuse of code, but flexible response to messages

12- 95

Interfaces

• Java has a way of specifying "classes" that contain nothing but declarations of abstract methods

• These provide no code, just a list of methods that every subclass has to define

• It allows clients to define a method having formal parameters of the abstract "class", but whose actual parameters can belong to any class in its hierarchy

12- 96

Interface Declaration

• This is so common that Java provides a special way of specifying it: interface declarations

• Interface declarations are like abstract classes, but are restricted to containing abstract method declarations and symbolic constant definitions:

interface interface_name {definitions of symbolic constants, and declarations of abstract methods

}

• Like classes, interfaces are placed in separate files, with the .java extension

12- 97

Syntax Differences

• Classes that contain real definitions of these abstract methods write "implements interface_name" instead of "extends…"

• All the methods in the interface are abstract, so you don't write "abstract" in front of them

• All symbolic constants are assumed to be public, static, and final, so don't write those keywords, either

12- 98

More Importantly!

• A class can implement more than one interface, while it can only be a subclass of one class; this allows us to use interfaces more flexibly

• We might have interfaces I1 and I2, with methods that class C defines; even if C is a subclass of B, we could still write:

class C extends Bimplements I1, I2 { … }

12- 99

One Use for Interfaces

• Sometimes interfaces are used to give definitions of symbolic constants to be used in several classes

public interface Direction {int NORTH = 0, EAST = 1, …

}

• Then several other classes implement this interface:

public class Mazeimplements Direction { … }

12- 100

Another use for interfaces

• Define a plotting function that accepts a function as one of its arguments:

void plot (double x0, double x1,double delta, Function f) {

// plot f on values x0, x0+delta, …, x1…

}

• We can't pass a function as an argument

• But we can define different objects that respond to the message "apply( )", and each different kind of object contains a function

12- 101

interface Imposing a Requirement on Classes

double apply(double x);

interface Function

interface

implements implements

double apply(double x ) {…}…

SineFunction EmpiricalFunction

double apply(double x ) {…}…

12- 102

The Role of Interfaces

• Interfaces play a role like the abstract classes we saw in previous slides

• Interfaces are data types in Java, just like classes are

• When a class implements an interface, instances of the class can be assigned to variables of the interface type

12- 103

What it Looks Like (these are in different files)

void plot (double x0, double x1, double delta, Function f) {

// plot f on values x0, x0+delta, …, x1…

}

interface Function{double apply(double x);

}

class SineFunction implements Function {double apply(double x) { return

Math.sin(x); }}

class EmpiricalFunction implements Function {double apply(double x) { … }

}

12- 104

Calling them

• Then these are legal calls (assuming appropriate constructors for SineFunction and EmpiricalFunction):

plot(0.0, 10.0, 0.1, new SineFunction( ));

and

plot(0.0, 10.0, 0.1,new EmpiricalFunction(60, 0.0, 59.0));

12- 105

The Point

• The point is, we can use objects of type SineFunction and of type EmpiricalFunction in the same context (e.g., as an argument of the plot( ) method)

• They'll both implement the interface Function; they both provide a definition of apply( )

• But they may not belong in the same class hierarchy, logically, and we need not require that they be in the same hierarchy

12- 106

Interfaces can also Inherit

• Interfaces can also be organized conveniently into inheritance hierarchies

interface I extends J …

• I actually consists of all the methods and constants in I itself together with those in J

• A class implementing I has to implement all those methods and constants

12- 107

Exception Handling

• Java provides us with a relatively clean way of catching run-time errors — exceptions

• An exception is an object

• An exception is a signal that some unusual situation (like an error) has occurred

• When "something goes wrong", an exception object is generated and passed back in a special way

12- 108

Exceptions in Java

• Java actually uses the notion of exception for 3 related (but different) purposes:– Errors: an internal Java implementation error was

discovered » E.g: out of memory

– Runtime exceptions: a programming logic error was discovered

» E.g. division by 0

– Checked Exceptions: an exceptional case was discovered

» E.g. file not found

12- 109

Exceptions in Java

• Errors and Runtime exceptions will usually cause the program to crash

• Checked exceptions should usually be handled by the programmer

12- 110

Occurrence of a runtime exception

public class ExceptionExample { public static void main(String[] args) { int[] a = {2, 4, 6, 8}; for(int j = 0; j <= a.length ; j++) System.out.println(a[j]); }}

12- 111

Program Crash due to a runtime exception

12- 112

Runtime exceptions in the Java API

• java.lang.ArithmeticException

• java.lang.NullPointerException

• java.lang.IllegalArgumentException

• java.lang.NegativeArraySizeException

• java.lang.ArrayIndexOutOfBoundsException

• java.lang.ClassCastException

12- 113

try, catch, finally

• The try clause establishes a block of code that might have exceptions or abnormal exits

• The try block is followed by zero or more catch clauses that specify code to handle various types of exceptions

• the finally clause specifies code that will always be performed, if any part of the try block is executed (good for cleanup, closing files, etc.)

try {// Normally this code runs from top of block to bottom// without problems. But it sometimes may raise// exceptions or exit the block via a break, continue, or// return statement

}catch (SomeException e1) {

// Handle an exception object e1 of type SomeException// or of a subclass of that type

}catch (AnotherException e2) {

// Handle an exception object e2 of type AnotherException

// or of a subclass of that type}finally {

// Always execute this code, after we leave the try clause,

// regardless of whether we leave it, normally, with an// exception that is caught or not caught, or because of a// break, continue, or return statement

}

12- 115

How are throws caught? Recall the runtime stack, and method calls

Method e( )Where we came from: main, line 4

Method main( )

STACK

Method f( )Where we came from: e, line 3

Method g( )Where we came from: f, line 4

top

void g ( ) { System.out.println(“A!”); System.out.println(“B!”); … System.out.println(“C!”); System.out.println(“D!”);}

void f ( ) { System.out.println(“Hi there!”); System.out.println(“Nice weather!”); ... obj.g( ); System.out.println(“That was fun!”); System.out.println(“Time to move on!”);}

void e ( ) {......obj.f( );...}

main (String[ ] args) {.........obj.e();...}

12- 116

throws are handled upthe calling hierarchy

• If an exception object were generated in g( ) (like an array index was out of bound), the system would first look if it is caught in g( )

• If it's not caught there, the system sees if it is caught in f( ); then in e( ); finally in main( )

• If not caught at all, the exception object causes the Java interpreter to print an error message and a stack trace and exit

void g ( ) { System.out.println(“A!”); System.out.println(“B!”); … System.out.println(“C!”); System.out.println(“D!”);}

void f ( ) { System.out.println(“Hi there!”); System.out.println(“Nice weather!”); ... obj.g( ); System.out.println(“That was fun!”); System.out.println(“Time to move on!”);}

void e ( ) {......obj.f( );...}

main (String[ ] args) {.........obj.e();...}

12- 117

Exception Objects

• An exception in Java is an object that is an instance of some subclass of java.lang.Throwable

• Throwable has two standard subclasses, java.lang.Error and java.lang.Exception.

• Exceptions that are subclasses of Error are generally unrecoverable and need not be caught

• Exceptions that are subclasses of Exception indicate conditions that may be caught and recovered from

12- 118

Exception Objects

• Since exceptions are objects, they can contain data and define methods

• The Throwable object (at the top of the exception hierarchy) includes a String message to describe the exception, and this is inherited by all its descendants; the message is extracted via the method getMessage( )

• A few descendants add their own data (e.g., java.io.InterruptedIOException adds the field

public int bytesTransferred;to signify how much of the I/O was complete before the exception occurred)

12- 119

Exception life-cycle

When a program performs an illegal operation the following happens:– The regular flow of the program stops– An exception object is created, which encapsulates the

information about the problem that occurred– The method may try to catch and handle the exceptional

situation– If the method ignores the exception the method execution

ceases.– An exception then appears at the place in which the method

was called– If the exception is not handled anywhere, the program

crashes.

12- 120

Declaring Exceptions

• Certain kinds of exceptions need to be declared in a method’s declaration, if they are not handled inside the method:public void open_file( ) throws IOException {

// Statements that might generate an// uncaught java.io.IOException

}• You only need to declare exceptions that are not

subclasses of Error or of RuntimeException; these are just too common to require declaring

• An example that does not need to be declared is ArrayIndexOutOfBoundsException

12- 121

Creating our own Exceptions

• We can declare a new exception class, and put it in the hierarchy of the class Exception

• We need two constructors: one with no argument, and one with a single String argument giving a description of the fault

• Let's look at an existing example from the Java API, to understand how to define our own

12- 122

class FileNotFoundException

package java.io;public class FileNotFoundException

extends IOException {

public FileNotFoundException( ) { super( ); }

public FileNotFoundException(String s) {super(s);

}}

12- 123

How would we use it?

package java.io;public class FileInputStream extends InputStream {

public FileInputStream(String name)throws FileNotFoundException {…try {

fd = new FileDescriptor( );open(name);

}catch (IOException e) {

throw new FileNotFoundException(name);

}}

}

12- 124

OK, so let's create our own

• Declare a new class, GetOuttaHereException, and have it extend the Exception class

• Provide it with two constructors, one that takes no arguments and one that takes a string argument (and both call super)

• throw new GetOuttaHereException with or without a string argument

12- 125

GetOuttaHereException definition

public class GetOuttaHereExceptionextends Exception {

public GetOuttaHereException( ) { super( ); }

public GetOuttaHereException(String s) {super(s);

}}

12- 126

Now, use the exception in a method, gateKeeper( )

void gateKeeper (Person candidate)throws GetOuttaHereException {

…if ( isBum(candidate) ) throw new GetOuttaHereException("You're a

bum!");if ( isBroke(candidate) ) throw new GetOuttaHereException("You're

broke!");if ( doesNotKnowJava(candidate) ) throw new GetOuttaHereException("You don't know

Java!");…

}

12- 127

We will catch the exception in the calling method, joinClub

void joinClub (Person candidate) { try {

gateKeeper(candidate); } catch (GetOuttaHereException e) {

System.out.println("No, you can't join the club because "

+ e.getMessage( ));return;

} System.out.println("Welcome to the club!");}

12- 128

Exceptions Hierarchy

• All the classes for indicating run-time errors are derived from the class java.lang.Throwable.

• The object you deliver to the throw statement must be an instance of class Throwable

• The constructor of class Throwable initializes all the information about the location where the exception occurred, the state of the run-time stack etc. In this way this information is set for every exception object.

• The following diagram explains the inheritance hierarchy for exceptions.

12- 129

Throwable class hierarchy

Throwable

ExceptionError

RuntimeException

12- 130

Input / Output

• A program often needs to communicate with other devices. In other words it should receive input and send output.

• There are many types of input sources:– Reading a file from a local disk / diskette

– Receiving a web page from a remote server

– Receiving a communication message through a network. Receiving a signal from a sensor of a robot

– Scanner, video camera, ...

– Mouse, keyboard, joystick, ...

12- 131

Input / Output

• Similarly, there are many types of output destinations:– Writing to a file on a local disk / diskette

– Sending query information to a remote web server

– Sending communication message to a remote host. Sending a command to a robot controller.

– Printing a document to a printer / fax

– Displaying graphics on the screen

– ...

12- 132

GUI inputs and outputs

• GUI related inputs and outputs are usually treated separately. They are given special API

• GUI inputs and outputs include receiving mouse, keyboard and similar events, and displaying graphics on the screen

12- 133

IO API - design goal

• We want to make a distinction between the content of the data an application receives/sends and the source/destination of the data

• The same kind of data can be stored on different types of media

• Similarly a given media can store different types of data

12- 134

Scenario

• Suppose we have an image processing application. It can read images, manipulate them and store them on a permanent storage.

• We want our application to be able to read images from different types of sources:– local image files, remote images from the web, receiving

an image from a scanner, ...

• We want to be able to output the image to various types of destinations:– save the image to a local file, print the image on a

printer, send the image to a fax recipient, ...

12- 135

Scenario

Application

12- 136

IO Streams

• We can achieve the separation by designing a common interface for reading any kind of data, and common interface for writing any kind of data.

• This interface is implemented by the notion of input and output streams.

• Any input can be represented as a sequence of bits. For convenience we divide the sequence into a sequence of bytes.

• Similarly any output can be represented as a growing sequence of bytes.

12- 137

IO Streams

12 72 32 17 83 11 7 91 108

43 55 31 37 34 13 17 1 15

Input stream

Output stream

reading direction

writing direction

12- 138

Input streams

• An input stream is a sequence of bytes that is attached to some input source.

• You can read data from the stream in a sequential order. One byte at a time or several bytes at a time.

• Input streams are represented by the abstract class java.io.InputStream.

• Subclasses of InputStream defines input streams that are related to various data sources

• Class InputStream gives a common interface for receiving data from various types of data sources

12- 139

Specific input streams

InputStream

ByteArrayInputStream

FileInputStream PipedInputStream

. . .

12- 140

Class InputStream

• Class java.io.InputStream defines several methods that support the abstraction of allowing sequential reading from a stream:

Reads the next byte from the stream. Return -1 if the end of the stream was reached.

Reads up to b.length bytes from the stream into the array b. Returns the number of bytes that were read.

public abstract int read() throws IOException

public int read(byte[] b) throws IOException

12- 141

Input streams

Reads up to length bytes from the stream into the array ‘b’ from the index ‘offset’. Returns the number of bytes that were read.

Closes this input stream and releases any system resources associated with the stream.

• Few additional methods (look up in the API)

public int read(byte[] b, int offset, int length)

throws IOException

public void close() throws IOException

12- 142

Output streams

• An output stream is attached to an output destination to which you can write data.

• You can write data to the stream in a sequential order. One byte at a time or several bytes at a time.

• Output streams are represented by the abstract class java.io.OutputStream.

• Subclasses of OutputStream defines output streams that are related to various data destinations

• Class OutputStream gives a common interface for sending data to various types of data destinations

12- 143

Specific output streams

OutputStream

ByteArrayOutputStream

FileOutputStream PipedOutputStream

. . .

12- 144

Class OutputStream

• Class java.io.OutputStream defines several methods that support the abstraction of allowing sequential writing to a stream:

Writes the specified byte (given as an int) to this output stream.

Writes b.length bytes from the specified byte array to

this output stream.

public abstract void write(int b)

throws IOException

public void write(byte[] b) throws IOException

12- 145

Input streams

Writes length bytes from the specified byte array starting at offset off to this output stream.

Closes this output stream and releases any system

resources associated with the stream.

• Few additional methods (look up in the API)

public void write(byte[] b, int offset,

int length) throws IOException

public void close() throws IOException

12- 146

Reading/Writing from/to files

• java.io.FileInputStream is a subclass of InputStream that let you read a file (viewed as a sequence of bytes)

• java.io.FileOutputStream is a subclass of OutputStream that let you write data to a file (as a sequence of bytes)

• Both classes have constructors that get the path of the file as a parameter

12- 147

Writing to a file

import java.io.*;class GenerateDiceData { static final int NUMBER_OF_TOSSES = 100000;

public static void main(String[] args) { try { OutputStream output = new FileOutputStream(“dice.dat”); for (long i=0; i<NUMBER_OF_TOSSES; i++) { int randomThrow = (int)(Math.random()*6)+1; output.write(randomThrow); } output.close(); } catch (IOException ioe) { System.err.println(“Couldn’t write to file”); } }}

12- 148

Reading from a file

import java.io.*;public class Count6Occurrences { static final int LOOK_FOR = 6;

public static void main(String[] args) { long count = 0; try { InputStream input = new FileInputStream(“dice.dat”); int result; while ((result = input.read()) != -1) if (result == LOOK_FOR) count++; input.close(); System.out.println(count + “ occurrences”); } catch (IOException ioe) { System.err.println(“Couldn’t read from file”); } }}

12- 149

Downloading a file from the web page

import java.io.*;import java.net.URL;// This program downloads a file from a given url// and saves it to the local file// Usage: java Download <url> <filename>public class Download {

public static void main(String[] args) { try { download(args[0], args[1]); } catch (ArrayIndexOutOfBoundsException aioobe) {

System.err.println(“Wrong usage.”); } catch (IOException ioe) { System.err.println(“Download failed”); } }

12- 150

Downloading a file from the web (cont.)

// Downloads a remote file to the local disk. // source - The url of the remote file // filename - The name of the target file. private static void download(String source, String filename) throws IOException { InputStream input =(new URL(source)).openStream(); OutputStream output=new FileOutputStream(filename); int b; while ((b=input.read())!=-1) { output.write(b); } output.close(); }}

12- 151

Textual vs. binary data

• We often make a distinction between textual data and other kind of data

• We refer to files that stores text as ‘text files’ and to other files as ‘binary files’.

• Binary files stores their information in various formats. In order to understand the content of a binary file you need to have a viewer that knows how to read the format the file is written with.

• The structure of text files is more simple. It uses an encoding that gives a numeric code for each symbol and the text is stored as a list of numbers.

12- 152

Java & Unicode

• One of the important aspects of Java is its platform independence

• Therefore Java uses Unicode

• However, many environments don’t support Unicode yet but only use ASCII.

• Unicode uses two bytes per character while ASCII uses one byte

• Java IO library overcomes this problem using Readers and Writers that translate between internal Unicode representation and external ASCII representation (with local extensions).

12- 153

Writers

Writer writer = new FileWriter(“mail.txt”);

writer.write(‘a’);

writer.write(‘\u0590’); // Hebrew Aleph

Automatic platform

dependent translation

made by the writer

97

97

1424

224

97 224

conversion to

the platform specific

code for aleph

standard ASCII no

conversion needed

12- 154

Readers

Reader reader = new FileReader(“mail.txt”);

char c = reader.read(); // c = ‘\u0590’

c = reader.read(); // c = ‘a’

Automatic platform

dependent translation

made by the reader

97

97

1424

224

97 224

conversion from

the platform specific

code for aleph

standard ASCII no

conversion needed

12- 155

Readers & Writers

• java.io.Reader is an abstract class that defines a common interface for reading textual data

• It is the counterpart of InputStream

• You can read from a reader characters in a sequential manner. One character at a time, or several characters at a time.

• Similarly, java.io.Writer is an abstract class that defines a common interface for reading textual data.

• It is the counterpart of OutputStream

12- 156

Specific readers

Reader

CharArrayReader

FileReader PipedReader

. . .

StringReader

12- 157

Specific writers

Writer

CharArrayWriter

FileWriter PipedWriter

. . .

StringWriter

12- 158

java.io.Reader

Read a single character. Returns the character as an int or -1 if the end of the stream was reached.

Reads up to buffer.length characters into ‘buffer’, returns the number of characters read.

Closes the reader.

• Few additional methods (look up in the API)

public abstract int read() throws IOException

public int read(char[] buffer) throws IOException

public void close() throws IOException

12- 159

java.io.Writer

Writes a single character given as an int.

Writes a given char array.

Closes the writer.

• Few additional methods (look up in the API)

public abstract void write(int c) throws IOException

public void write(char[] buffer) throws IOException

public void close() throws IOException

12- 160

ToUpper

import java.io.*;// This class reads a text file and writes it into // another text file after converting all letters to// uppercase.// Usage: java ToUpper <source> <target>class ToUpper {

public static void main(String[] args) { if (args.length!=2) { System.err.println(“Invalid usage.”); return; } String sourceName = args[0]; String targetName = args[1];

12- 161

ToUpper (cont.)

try { Reader reader = new FileReader(sourceName); Writer writer = new FileWriter(targetName); int c; while ((c=reader.read())!=-1) { c = Character.toUpperCase((char)c); writer.write(c); } write.close(); //very important !!! } catch (IOException ioe) { System.err.println(“Copying failed.”); } }}

12- 162

Reading “non-primitive” data

• The data we want to read/write usually has more complex structure: primitive data types other than char or short, lines, or even more complex: tables, images, compressed/encrypted data...

• Basic solution: Extend existing input or output streams– Provide methods for handling the non-primitive

data

12- 163

public class ShortInputStream extends

SomeInputStream{

// ...

public short readShort() throws EOFException {

int hi,low;

if ((hi = this.read()) == -1)

throw new EOFException();

if ((low = this.read()) == -1)

throw new EOFException();

return (short)(hi << 8 | low );

}

}

Reading a Short

12- 164

Reading a Line

public class LineReader extends SomeReader {

// ...

public String readLine() throws EOFException {

StringBuffer line = new StringBuffer();int c;

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

if (c!=‘\n’)

line.append((char)c);

else

return line.toString();

}

if (line.equals(“”))

throw new EOFException();

}

}

12- 165

Design Problem

• There are many enhancements for reading/writing data

– Reading complex types of data (lines, objects, ints)

– Buffering

– “pushing back” something that was already read

• There are many types of input/output streams

• If we would include all enhancements in all types of streams we will end up with a lot of duplicated code and it would be hard to add new enhancements or new types of streams.

• We usually don’t need all combinations at once

12- 166

Solution - Decorator Pattern

• Use a “decorator”: a class that is derived from Reader, and has another Reader object as a member (received by the constructor of the new class).

• All Reader methods are “forwarded” to the inner Reader object.

• New attributes (methods) use the inner Reader object as well.• We gain two things: The “old” interface is preserved, and we

can “chain” several functionalities.• Same solution concept for Writer, InputStream and

OutputStream.• In Java, “decorators” are called “Filters”, and the base class

for adding attributes is FilterXXX.

12- 167

Example: BufferedReader

Reader

read()

...

...

BufferedReader

readLine()

BufferedReader

(Reader r)

read()

...

...

12- 168

Example: DataInputStream

InputStream

read()

...

...

DataInputStream

readShort()

read()

...

...

12- 169

Printing a text file

public class type {

public static void main(String[] args) {

try {

BufferedReader reader =

new BufferedReader(new FileReader(args[0]));

String line;

while ((line=reader.readLine())!=null)

System.out.println(line);

} catch (IOException ioe) {

System.err.println(“Reading failed.”);

}

}

}

12- 170

Filters in java.io.*

• DataInputStream & DataOutputStream

– Read and write all primitive Java data types

• ObjectInputStream & ObjectOutputStream

– Read and write full objects

– Objects must be “Serializable”

• BufferedReader/Writer/InputStream/OutputStream

– Provide buffering

– BufferedReader/Writer allow also reading complete lines

• LineNumberReader & LineNumberInputStream

– Allow access to input line numbers

12- 171

Example: Chaining Decorators

readShort()

read() read() read()

BufferedDataFile

try {

DataInputStream input = new DataInputStream(

new BufferedInputStream(

new FileInputStream(args[0])));

} catch (FileNotFoundException fnfe) {

// ...

}

12- 172

InputStreamReader

• InputStreamReader bridges InputStream and Reader classes:

URL url = new URL(“...“);

BufferedReader reader =

new BufferedReader(

new InputStreamReader(url.openStream()));

String line;

while ((line = reader.readLine())!=null) { System.out.println(line);

}


Top Related