89
Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient Java for the Impatient

Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Embed Size (px)

Citation preview

Page 1: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Lecture 3: More Constructors, Scope, Wrappers, Inheritance, andObject Oriented

Design.

Java for the ImpatientJava for the Impatient

Page 2: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

• Extending classes & inheriting fields/methods– Using this and super– Constructor chaining– Polymorphism & casting– Single and multiple inheritance– Visibility modifiers

Object Oriented Design

Page 3: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Inheritance

Natural, hierarchical way of organizing things.

Staff Member

Employee Volunteer

Hourly Salaried

Consultant

Think in terms of “is a” relationships: An Employee is a Staff Member, as is a Volunteer. An Hourly worker is a Employee. A Consultant is a(n) Hourly employee.

(subclass of Hourly)

(subclass of Employee)

(subclass of Staff)

(superclass)

Page 4: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

class Animal { protected String strName = “”; protected String strNoise = “”; protected int iNumTimesPerformed = 0; // constructors, accessors & modifiers go here public void identifySelf( ) { System.out.println(“My name is “ + strName); } // of identifySelf public void perform ( ) { doYourThing( ); iNumTimesPerformed++; } // of perform public void doYourThing( ) { ; // ‘no-op’ method } // of doYourThing

} // of Animal

Example

Page 5: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Subclasses(Dog extends Animal

i.e. “A dog is an animal” or“All dogs are animals”)

class Dog extends Animal { public Dog() { strNoise = “Woof”; } // of constructor

public void doYourThing ( ) { identifySelf(); System.out.println(“I am a dog”); System.out.println(strNoise); } // of doYourThing

} // of Dog

Recall: The Animal class had a no-op method for doYourThing()

Animal

Dog Cat Human

Page 6: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Subclasses(Cat extends Animal

i.e. “A cat is an animal” or“All cats are animals”)

class Cat extends Animal { public Cat() { strNoise = “Miaow”; } // of constructor

public void doYourThing ( ) { identifySelf(); System.out.println(“I am a cat”); System.out.println(strNoise); } // of doYourThing

} // of Cat

Animal

Dog Cat Human

Page 7: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Example (Cont’d)Dog pickles = new Dog();pickles.setName(“Pickles”);pickles.doYourThing();// output:// “My name is Pickles”// “I am a dog”// “Woof”

Cat abby = new Cat();abby.setName(“Abby”);abby.doYourThing();// output:// “My name is Abby”// “I am a cat”// “Miaow”

Page 8: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Subclasses(Human extends Animal

i.e. “A human is an animal” or“All humans are animals”)

class Human extends Animal { public Human() { strNoise = “I think therefore I am”; } // of constructor

public void doYourThing ( ) { identifySelf(); System.out.println (“I am a sentient being”); System.out.println(strNoise); } // of doYourThing

} // of Human

Animal

Dog Cat Human

Page 9: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Example (Cont’d)

Human descartes = new Human();descartes.setName(“Rene”);descartes.doYourThing();// output:// “My name is Rene”// “I am a sentient being”// “I think therefore I am”

Page 10: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Inheritance and ScopeVariables (e.g. strNoise):• Java first examines current method, looks for local variable or parameter;• Java then examines current class (e.g. Dog);• Java then examines superclass (e.g. Animal); • Java continues up the class hierarchy until no more superclasses to examine.

Methods (e.g. doYourThing() or identifySelf()):• Java first examines current class;• Java then examines superclass;• Java continues up inheritance hierarchy until no more superclasses to examine.

Page 11: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Specifying ScopeSpecifying Scope

Java allows you to override the scope rules by saying which variable/method you’re referring to:

Keyword super:keyword for specifying method or variable from superclass, e.g., super.doYourThing( )

Keyword this:keyword for specifying method or variable in current object, e.g., this.doYourThing( )

Page 12: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

class Dog extends Animal { public Dog() { super.strNoise = “Woof”; } // of constructor

public void doYourThing ( ) { super.identifySelf(); System.out.println(“I am a dog”); System.out.println(strNoise); } // of doYourThing

} // of Dog

Same (in this case) asstrNoise = “Woof”;andthis.strNoise = “Woof”;

Same (in this case) asidentifySelf();orthis.identifySelf();

Page 13: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Using super

class Dog extends Animal { // constructor as before

public void doYourThing() {identifySelf();System.out.println(strNoise);

} // of doYourThing

public void identifySelf() { super.identifySelf();

System.out.println(“I am a dog”); } // of identifySelf

} // of Dog

Animal

Dog Cat Human

I.e.this.identifySelf()(newly defined below)

I.e. theidentifySelf()(defined in Animal)

Page 14: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

class Shape {

public final double PI = 3.14159; protected String name; public String getName () { return (this.name); } // getName

public int area () { return (0); } // area

} // Shape

A geometry example

Shape

CircleRectangle

Page 15: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

class Rectangle extends Shape { private int length, width; Rectangle () { this(0, 0); } // constructor

Rectangle (int l, int w) { this( l, w, “rectangle”); } // constructor

Rectangle (int l, int w, String n) { length = l; width = l; name = n; } // constructor

public int area () { return (length * width); } // area

public String getName () { if (length == width) return ("square"); else return (super.getName()); } // getName

public String toString () { String s; s = new String ("A " +

getName() + " with length " + length + " and width " + width);

return (s); } } // toString

} // Rectangle

Page 16: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Java’s rule:

• If first line of constructor is not an explicit call to a superclass constructor, Java will implicitly put super( ) as the first line, calling the superclass default constructor.

public Dog() { strNoise = “Woof”; } // of constructor

• An exception to this rule: chained constructor call tothis(params)

will defer super( ) call

• To use superclass constructors with params, call them explicitly, e.g., super(strName)

Constructors and Inheritance

implied call to Animal() here

Page 17: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Inheritance and ScopingInheritance and Scoping

Examples:

super(xxx) // calls a superclass constructorsuper.xxx // accesses superclass’ variablesuper.xxx( ) // calls superclass’ method

this(xxx) // calls a current-class constructorthis.xxx // accesses current class’s variablethis.xxx( ) // calls current class’ method

Note: cannot do super.super<something>

(can achieve this effect via casting, but rarely should; details later...)

Page 18: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Inheritance and Scopingclass StaffMember { String strName;

public StaffMember( ) { System.out.println (“in default StaffMem constr; No Name”); setName(“No Name”); } // of constructor

public StaffMember(String strName) { System.out.println (“in 2nd StaffMem constructior; have a Name”); setName(strName); } // of constructor

public void setName(String strName) { this.strName = strName; } // of setName

}// of StaffMember

Page 19: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

class Employee1 extends StaffMember { public Employee1(String strName) { setName(strName); } // of constructor } // of Employee1

What happens???

Inheritance and Scoping

Note: Employee has no local setName() method

class Employee2 extends StaffMember { public Employee2(String strName) { setName(strName); } // of constructor

public void setName(String strName) { super.setName(strName); System.out.println (“Name set”); }} // of Employee2

Page 20: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Class Object

• Java provides a base class, Object

• All classes that do not have an extends clause implicitly inherit directly fromclass java.lang.Object

Examples:

public boolean equals (Object o)

public boolean String toString ()

• When you create your own toString( ) method for a class, you are overriding the toString( ) provided by Object.

Page 21: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Object HierarchyObject Hierarchy

Animal

Dog Cat Human

Object

Employee

Salaried Hourly

class Object methods: String toString() boolean equals(Object obj) and a few others...

Animal

Dog Cat Human

Object

Employee

Salaried Hourly

Or how about...

Page 22: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Primitive types (e.g., int) are not classes

But sometimes, we may have need to make use of primitive types in a context that requires that we manipulate objects, not primitivese.g. many collection classes are collections of Objects

Java provides a set of wrapper classes (a.k.a. type wrappers, a.k.a. envelope classes) to support treating primitives as objects.

It does this by providing a specific class that corresponds to each primitive data type

They are in java.lang, so the names are universally available

Wrapper ClassesWrapper Classes

Page 23: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Wrapper ClassesWrapper Classes

Class corresponds to Primitive

Boolean boolean Character char Byte byte Short short Integer int Long long Float float Double double

Each one:• allows us to manipulate primitives as objects• contains useful conversion methods.

E.g. Integer containsstatic Integer valueOf(String s)Integer.valueOf(“27”)is the object corresponding to int 27

• contains useful utility methods (e.g. for hashing)

Page 24: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Using wrappers to bridge between objects and primitives:

// create and initialize an int int i = 7;

// create an Integer object and convert the int to it Integer intObject = new Integer( i );

// retrieve the int by unwrapping it from the object System.out.println( intObject.intValue );

// convert a string into an Integer object String strS = “27”; Integer intObject intObject = new Integer (Integer.valueOf(strS) ); // then to an int i = intObject.intValue;

Wrapper ClassesWrapper Classes

A classmethod

Page 25: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

InstanceInstance vs. vs. ClassClass Methods Methods

• Use instance methods whenever each object should have its own behavior. e.g.,

pickles vs. descartes vs. abby doYourThing( ).

• Use a class method whenever the class itself should maintain a single behavior for all instances of the class. e.g.,

converting from one type to another.

• Class methods cannot be used to access instance variables

•So you can sayInteger.valueOf(strValue);but notintObject.valueOf(strValue);

Page 26: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Polymorphism• Several subclasses may have different

methods for accomplishing the same/similar behavior– You don’t care about the details when you call

a method, provided you know that the object can perform a method with that signature

– E.g. you have a simulated ecology

with animals in it (SimZoo) and

want to make the animals move• But animals move in diffrerent ways

Page 27: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

PolymorphismPolymorphismclass Animal { public void move ( ) { System.out.println(“I am an animal and am moving.”); } // of move} // of Animal

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

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

Page 28: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Polymorphism (cont’d)

class Dog extends Animal{ public void move ( ) { System.out.println(“Sniff sniff woof woof”); } // of move

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

} // of Dog

Page 29: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

class Driver { public static void main (String[ ] argv) { Animal[ ] animalArray = new Animal[3]; int iIndex; animalArray[0] = new Bird( ); animalArray[1] = new Dog( ); animalArray[2] = new Fish( ); for (iIndex=0; iIndex < animalArray.length; iIndex++) { animalArray[iIndex].move( ); } // of for

} // of main} // of Driver

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

Polymorphism

All animals can move, so any member of the array can move

Page 30: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

PolymorphismPolymorphism• Polymorphism means “taking many forms” ... an object of a given class can adapt take the formof any of its subclasses.

• Polymorphism means that the correct move( ) method will always be called.

• 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.

• A single interface for multiple behaviors: Only one interface for the method call. Multiple behaviors based on the subclass.

Page 31: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

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

Polymorphism

We cast before calling bark() because only dogs can bark. So some array members cannot execute the method

Page 32: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Casting:• used here to give an object of a superclass the form of the appropriate subclass, e.g.,

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

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

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

Polymorphism

Page 33: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Keyword instanceof: Used to interogate an object to see if it is an instance of the specified class, e.g.

“Is this particular animal of class Dog?”

Casting … Why?

Question: If Java can determine that a given Animal is or is not a Dog (via instanceof), then:

• Why the need to cast it to a Dog object before Java can recognize that it can bark?

• Why can’t Java do it for us?

Page 34: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Sourcecode

CompileBytecode

JVMInterpreter

Programruns

errors errors

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

Casting… Why?

Page 35: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Casting (con’td)

Compile-time Errors:

• Those that are discernable without the program executing.

• Question of language legality: “Is this a legal statement?” e.g.,

iIndex = chVariable;

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 is legal, but particular index value isn’t.

Page 36: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

if (animalArray[iIndex] instanceof Dog) { animalArray[iIndex].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. We want most checking at compile-time for performance and correctness.

Casting… Why?

Page 37: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Casting (Cont’d)if (animalArray[iIndex] instanceof Dog) { d = (Dog) animalArray[iIndex]; d.bark( );

}

• 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.

Page 38: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Multiple Inheritance

Some languages allow multiple inheritance:

Animal Pet (two superclasses)

Dog (a subclass of two)

• Multiple inheritance leads to many potentially confusing naming problems (e.g. Pet.doYourThing() vs. Animal.doYourThing())

•Growing consensus: the benefits of multiple inheritance aren’t worth the problems.

• Java has single inheritance onlyonly.•Java doesn’t allow multiple inheritance•Well, there is a restricted kind that avoids most of the problems. It involves using interfaces, which we’ll cover later)

Page 39: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Visibility and AccessVisibility and Access

Visibility Modifier:

Access by: public protected private

Every class Yes No No

A subclass Yes Yes No

An instance of the class Yes Yes Yes

Always specify a visibility modifier.

Guidelines: Only make public methods that are in the class’s “contract” Make all fields private Make all other “private” methods protected Don’t leave off the modifier unless you know about packages

Can an object use a field or call a method?

Page 40: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Animals (again!)class Animal {

protected String strName = “”; protected String strNoise = “”; // constructors, accessors & modifiers go here

public void identifySelf( ) { System.out.println(“My name is “ + strName); } // of identifySelf

public void doYourThing( ) {; // ‘no-op’ method

} // of doYourThing } // of Animal

So, any object can ask ananimal to identify itself,or do its thing.

Page 41: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Exception Handling:

When Bad ThingsHappen to Good Code

Page 42: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Error HandlingSo far:• have done very little error handling• have assumed that things will work as intended

Rules of Thumb:• programmers must test and debug to find and correct compile-time errors

• compiler doesn’t solve the problem of run-time errors (e.g., incorrect values or state)

• programmer must insure that run-time errors result in “graceful” program behavior

• “graceful” means “the program doesn’t just produce wrong effects or blow up!

Exceptions--Why?Exceptions--Why?

Page 43: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

• In traditional procedural programming languages, there were various ways of handling run-time errors.

• One way is to return some kind of value indicating whether the procedure succeeded or not.

For example:

public boolean someMethod( ) { // if this method suceeded, return true // otherwise return false }

Note the blurring of the logical distinction betweenprocedures and functions… a bad engineering habit!

Exceptions--Traditional MethodsExceptions--Traditional Methods

Page 44: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

• Traditional means of error handling can quickly become ugly, complex and unmanageable.

For example:

If we intend to do the sequence of calling three procedures followed by one or more instructions, e.g.,

someMethod( );

someOtherMethod( );

someThirdMethod( ); /* do some intended actions*/ we can find ourselves with code that looks like . . .

Exceptions--Traditional MethodsExceptions--Traditional Methods

Page 45: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

if (someMethod( ) == true) { if (someOtherMethod( ) == true) {

if (someThirdMethod( ) == true) { // have not encountered errors; do intended actions } else { // handle some error caused by someThirdMethod( ) } } else { // handle some error caused by someOtherMethod( ) } } else { // handle some error caused by someMethod( ) }

Exceptions--Traditional MethodsExceptions--Traditional Methods

Page 46: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

int iErrorValue = 0; public void someMethod( ) { // do someMethod’s stuff here // if there is an error, then set iErrorValue = 1 }

public void someOtherMethod( ) { // do someOtherMethod’s stuff here // if there is an error, then set iErrorValue = 2 }

public void someThirdMethod( ) { // do someThirdMethod’s stuff here // if there is an error, then set iErrorValue = 3 }

• Another way error handling is to have the value of a global variable represent the error.

Exceptions--Global VariablesExceptions--Global Variables

Page 47: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

public void doIt() { someMethod(); someOtherMethod(); someLastMethod();

if (iErrorValue == 1) ... if (iErrorValue == 2) ... if (iErrorValue == 3) ... }

But: What if the run-time error stopped us from continuing?

For example: What if someMethod( ) failed in such a way that we cannot go on to someOtherMethod( )?

To cope, we find ourselves with code that’s nearly as messy as the earlier example which featured multiple nested-ifs:

Exceptions--Global VariablesExceptions--Global Variables

Page 48: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

public void doit( ) { someMethod( ); if (iErrorValue == 1) { ... } // if else { someOtherMethod( ); if (iErrorValue == 2) { ... } // if else { someThirdMethod( ); if (iErrorValue == 3) { … } // if else { do intended actions } // else } // else }// else

Exceptions--Global VariablesExceptions--Global Variables

Note: with this techniquewe potentially must wrapthe ENTIRE programin a series of if/else clauses,duplicating code in places.

(Do we prefer robustnessor clarity/maintainability?)

Page 49: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

• As you can see, it gets convoluted very fast even for such a simple sequence of steps.

• Historically, the way programmers got around this was simply to not do any error handling at all!

• Instead, they generally used one of two approaches:

• Upon detecting an error, simply terminate the program, i.e., “recognizethe error but don’t handle it, just quit”, or else …

• Don’t even attempt to detect the error; i.e., “let the program react in anarbitrary and unpredictable manner”(blow up? bad values? wrong behavior?)

• Both of these violate a basic tenet of structured programming:

“Allow only a single point of exit from any procedure or function.”

Exceptions: Traditional ApproachesExceptions: Traditional Approaches

Page 50: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Both of these traditional approaches boil down to a case of the programmer simply ignoring the real problem, which is:

When a run-time error occurs in a method,

• how can we stop the method without allowing it to do any damage?

• how can we take appropriate actions to handle the error without having the program simply blow up or do something else that’s bad?

It is not acceptable for programs to fail or to do “bad behavior”!

• Safety critical programs

• Customer satisfaction

We require some mechanism to recover from unexpected or abnormal run-time situations.

Exceptions: The Real ProblemExceptions: The Real Problem

Page 51: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Exception Handling: the modern programming concept for dealing with run-time errors

Exception: “a run-time event that may cause a method to fail or to execute incorrectly”

Purpose of Exception Handling: “to allow graceful handling of and recovery from run-time errors”

Common examples in Java:

• NullPointerException

• ArithmeticException

• ArrayIndexOutOfBoundsException

• Java API contains over two dozen exceptions provided by Java.

Exceptions and Exception HandlingExceptions and Exception Handling

Page 52: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Exception Terminology:

• When an exceptional condition occurs, an exception is “thrown” (i.e., the exception has been recognized).

• The flow of control is tranferred to the point where the exception is “caught” (I.e., where the exception-handling code responds to it).

In the jargon of some other programming languages, when an exception is recognized, an exception is:

• “raised” (in place of “thrown”), then

• “handled” (in place of “caught”).

Same ideas, different jargon.

Exceptions: TerminologyExceptions: Terminology

Page 53: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

One is usually more interested in

the type of the exceptionthan in manipulating it as an object,

so “e” is just an object often thrown away.

The general structure of Java’s exception handling:

try { // here goes the code that attempts to perform the // intended action, but that could throw an exception ... } // try catch (ExceptionType1 e) { // here goes the code to handle exception type 1 ... } // catch Type1 catch (ExceptionType2 e) { // here goes the code to handle exception type 2 ... } // catch Type2

Exceptions: General FormatExceptions: General Format

Page 54: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

int iDivisor; int iDividend; float fResult;

try { // get input for divisor and dividend ... fResult = (float) iDividend / iDivisor; System.out.println(fResult); } catch (ArithmeticException e) { System.out.println("The divisor was 0"); ... }

Exceptions: Simple ExampleExceptions: Simple ExampleAn example showing the structure of Java’s exception handling:

See, we don’tCare about the exception,

Just about its type being arithmetic error.

Page 55: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

How Java handles Exceptions:

If an exception is thrown in a method, then you can do one of two things in response:

1. Catch the exception right then and there, and handle the exception yourself.

You would do this if you have enough information to know how to handle the error.

2. Declare in the method header that whoever called the method has to handle the error.

You would do this if you don't have enough information to know how to handle the error.

Exceptions: How in JavaExceptions: How in Java

Page 56: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Given a full Queue, where a client tries to enqueue an item . . .

• What should you have the Queue do? • How do you know what it should do? • Should it print out a message? • Should it try to increase the Queue’s size? • Should it not enqueue the item? • Should it dequeue an item to make room for the new item?

What should you do? To put it simply, you don't know.

Solution:

1. Your design/documentation for enqueue should state a precondition:

/** PRE/POST: The queue is not full */

2. The code will let the exception propagate.

Exceptions: ExampleExceptions: Example

Page 57: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

When an exception is thrown, it must be caught immediately or declared to be allowed to propagate.

An example of code that will not compile:

class Queue { ... public boolean isEmpty( ) { ... } // isEmpty

public void dequeue(Object o) { if (isEmpty( ) == true) throw new QueueEmptyException( ); ... } // dequeue ...} // class Queue

Exceptions: PropagationExceptions: Propagation

Dequeue is not allowed to do this

Page 58: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

• Results in an error saying that dequeue must catch or declare QueueEmptyException.

• To resolve this, modify dequeue so that the exception is declared to be thrown:

public void dequeue(Object o) throws QueueEmptyException { if (isEmpty( ) == true) throw new QueueEmptyException( ); ... }

• The method header above declares that this method can throw a

QueueEmptyException

and that the method calling dequeue( ) must plan on catching the QueueEmptyException.

Exceptions: PropagationExceptions: Propagation

Page 59: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Suppose you want to use this Queue class to simulate a line of Customers, and you do:

class Customer { ...} // Customer

class Cashier { Queue customerQueue = new Queue( ); ...

public void getNextCustomer( ) { Customer cust; ... cust = (Customer) customerQueue.dequeue( ); ... } // getNextCustomer ...} // Cashier

Exceptions: ExampleExceptions: Example

Page 60: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

This will result in a compile-time error because method getNextCustomer must:

• catch exception QueueEmptyException, or

• declare that QueueEmptyException propagates upwards

Thus, we can repair getNextCustomer in one of two ways:

• Option 1: have it catch exception QueueEmptyException

• Option 2: have it declare that this method allows QueueEmptyException to propagate

Exceptions: Example (cont’d)Exceptions: Example (cont’d)

Page 61: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

public void getNextCustomer( ) { Customer cust;

try { ... cust = (Customer) customerQueue.dequeue( ); ... } // try

catch (QueueEmptyException e) { // handle the QueueEmptyException here ... } // catch

} // getNextCustomer

An Exception: Catching ItAn Exception: Catching ItOption 1

Page 62: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

public void getNextCustomer( ) throws QueueEmptyException { Customer cust;

... cust = (Customer) customerQueue.dequeue( ); ... } // getNextCustomer

This option dictates that whoever calls method getNextCustomer( ) has the responsibility of handling the exception.

An Exception:An Exception:

Declaring that it will propagateDeclaring that it will propagate

Option 2

Page 63: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

public class Test { public static void A( ) { int array[ ] = new int[5]; try { System.out.println( "In A's try." ); array[ 5 ] = 1; } // try catch( ArrayIndexOutOfBoundsException error ) { System.out.println( "In A's catch." ); } // catch } // A() public static void main( String argv[ ] ) { try { A( ); } // try catch( Exception e ) { System.out.println( "In main's catch." ); } // catch System.out.println( "After try in main." ); } // class Test

Exceptions: Another ExampleExceptions: Another Example

Output:

In A's try. In A's catch.

After try in main.

What happens here?

Page 64: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

• To recognize the exceptional state, use standard if-else logic.• To respond to them, you can create your own Exceptions.

Exceptions are objectsSo you really define your own classes of exception

• All Exceptions you create are extensions of java.lang.Exception

For example:

class QueueEmptyException extends Exception { public QueueEmptyException( ) { }

public QueueEmptyException(String strMessage) { super(strMessage); } }

Exceptions: Creating Your OwnExceptions: Creating Your Own

Page 65: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

• You can take advantage of inheritance when dealing with exceptions.

• Suppose we had an inheritance hierarchy of exceptions like this:

• You can have more than one catch block for a try block.

• A catch block will only catch that exception or a subclass of that exception.

Exception

IOException QueueFullException

EOFExceptionFileNotFoundException

Inheritance and ExceptionsInheritance and Exceptions

Page 66: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

try { ... } // try

catch (QueueFullException e) { ... } // catch QueueFull Exception

catch (FileNotFoundException e) { ... } // catch FileNotFound Exception

catch (IOException e) { ... } // catch IO Exception

Inheritance and ExceptionsInheritance and Exceptions

This sequence of catches works:

Exception

IOException QueueFullException

EOFExceptionFileNotFoundException

Page 67: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

try { ... } // try

catch (IOException e) { ... } // catch IOException

catch (FileNotFoundException e) { ... // this code can never be reached because // FileNotFound is subclass of IOException } // catch FileNotFound Exception

This sequence of catches doesn’t work:

Inheritance and ExceptionsInheritance and Exceptions

Exception

IOException QueueFullException

EOFExceptionFileNotFoundException

Page 68: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Something you can do with exceptions: try { ... } // try

catch (QueueFullException e) { ... } // catch QueueFullException

catch (IOException e) { ... } // catch IOException

catch (Exception e) { ... // this will catch any other kind of exception // since all exceptions extend Exception } // catch base Exception

Inheritance and ExceptionsInheritance and Exceptions

“catch-all” handler

Page 69: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

• In Java, there are actually two types of Exceptions: • those subclassed from Exception• those subclassed from RuntimeException

A technoid annoyance: Both kinds deal with run-time errors

• Those subclassed from RuntimeException do not have to be

explicitly caught or declared in the method header.

• This is good. It prevents code from being cluttered with exception handling:

// possible ArrayIndexOutOfBounds customerArray[10] = new Customer( );

// possible ArithmeticException x = y / z; • These may still be caught and/or propagated

upwards like normal exceptions.

Exception & RuntimeExceptionException & RuntimeException

Page 70: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

• There is a problem with the internal state of the program

• A contract is violated

• A security risk arises (SecurityException)

• There is an error with an object or the data it manipulates. • Coping with bad parameters

• Dealing with Truly Exceptional conditions (memory, stack).

Exceptions: When to UseExceptions: When to Use

Page 71: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

When to use exceptions: Internal StateWhen to use exceptions: Internal StateFor example:

public int getAge(int iSocialSecurityNumber) throws RecordKeepingException

{int index = getHashKey(iSocialSecurityNumber);int iAge = myArray[index].getAge(iSocialSecurityNumber);

/* Similar to util.ASSERT( ) statement. */if (iAge <= 0)

throw new RecordKeepingException (“Exception: Age for “ + iSocialSecurityNumber +

“ not in range: “ + iAge);else

return iAge;}

Page 72: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

public TreeNode getNodeRecursively (int index, TreeNode currentNode) throws MissingNodeException { if (currentNode == null) { throw new MissingNodeException (“Exception: No node with ” + index + “ found”); } // if else if (currentNode.getNumber() == index) { return currentNode; } // else else if (currentNode.getNumber() > index) { return getNodeRecursively (index, currentNode.getLeftChild()); } // if else { return getNodeRecursively (index, currentNode.getRightChild()); } // else

}// getNodeRecursively

When to Use Exceptions: Contract ViolatedWhen to Use Exceptions: Contract Violated

Page 73: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

public void initializeTreeNode(int iNumberNodes) { if (myTree == null) { if (DEBUG)

System.out.println (“Null tree found!”); throw new NullPointerException (“Null tree found”);

/* NOTE: Runtime exception; no need to declare propagation */ } else { for (int i=0; i < iNumberNodes; i++) { { TreeNode newNode = new TreeNode( i ); tree.insertNode(newNode); } }

} // initializeTreeNode

When to Use Exceptions: Error with objectsWhen to Use Exceptions: Error with objects

Page 74: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

public Integer convertNumber (String strToConvert) {

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

char chTemp = strToConvert.charAt(i);

if (!Character.isDigit(chTemp)) {

if (DEBUG) System.out.println (“Bad input String: “ + strToConvert);

throw new NumberFormatException(“Exception: “ + strToConvert + “ is not numeric”);

} } } // convertNumber

When to Use Exceptions: Bad ParametersWhen to Use Exceptions: Bad Parameters

Page 75: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

public class Chat { public static void doStuff() { Listener.count(”Yes it is "); try { Chit.doStuff(); } //try catch (StackOverflowError e){ System.exit(0); } // catch }} // Chat

When to Use Exceptions:When to Use Exceptions:

Truly Exceptional CircumstancesTruly Exceptional Circumstances

public class Chit { public static void doStuff() { Listener.count(”No it isn’t "); try { Chat.doStuff(); } // try catch (StackOverflowError e) { System.exit(0); } // catch }} // Chit

public class Listener { static int iCount; public static void count(String strSpeaker){ iCount++; System.out.println (strSpeaker + " is number " + iCount); }} // Listener

Page 76: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

When to Use Exceptions:When to Use Exceptions:

Truly Exceptional CircumstancesTruly Exceptional Circumstances

public TreeNode getNode(int index){ TreeNode tempNode; try { tempNode =

myTree.getNodeRecursively(new TreeNode(index)); } // try

catch(StackOverflowError e) {System.exit(1);

} // catch

return tempNode;} // getNode Or less obviously

Page 77: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

• Print an error message

• Log the exception

• Retry the method(maybe with default parameters)

• Restore the system to some previouslyknown "good" state.

• Set the system to some "safe" state.

•Let exception propagate to whoever called the method in which the exception arose

• Catch it and ignore it

“Catch it and ignore it” is generally bad: If the error was serious enough to throw an exception, it should be dealt

with, not ignored.

When Catching Exceptions you can . . .When Catching Exceptions you can . . .

OOA/OOD/OOP“Who”/what knowsenough to handlethe exception?

local?

high-level?

Page 78: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Exception Defined:

Object that defines an unusual or erroneous situation

What to do?

Not handle the exception (program halts. Ugh!) Handle the exception where it occurs (try...catch...) Handle the exception at another point in the program

(exception propagation)

Throwing an exception:

Part of the contract of a method (throws) Responsibility of the client to handle (try…catch…)

Exceptions: ReviewExceptions: Review

Page 79: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

A Few Words on Vectors

Page 80: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

VectorsVectors• An array (list) that dynamically resizes itself to whatever size is needed.

• A partial API for Vector:class Vector { public void addElement( Object obj ) public boolean contains(Object elem) public Object elementAt(int index) public Object firstElement() public int indexOf(Object elem) public void insertElementAt(Object obj, int index) public boolean isEmpty() public Object lastElement() public int lastIndexOf(Object elem) public void removeAllElements() public boolean removeElement(Object obj) public void removeElementAt(int index) public void setElementAt(Object obj, int index) public int size()} // of Vector

Page 81: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

VectorsVectors• Vector is a class.• Must have an object of type Vector instantiated via new( ) to get an instance of Vector.• All rules of good OO programming apply.• Thus, access by requesting services via methods, not via direct access (such an array).

size( ) returns current number of elements.

elementAt(int index) returns reference to element at specified index.

insertElementAt( Object obj, int index ) insertion into linked list (but slower);

addElement (Object obj) adds to end.

CommonExamples

Page 82: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

VectorsVectorsVectors:

• Can be populated only with objects;

• Cannot be populated with primitives;

• Can be populated with objects that contain primitives;

• If you need to populate them with primitives, use type wrapper classes e.g., Integer for int, etc.

• Will allow you to populate them with any type of object . . .

• Thus, good programming requires that the programmer enforce typing within a Vector, because Java doesn’t.

Page 83: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

VectorsVectorsVectors and casting:

• Vectors are a subclass of class Object.• Thus, vectors can handle any class of object (i.e., no type checking)

• Thus, must cast any object obtained from a Vector before invoking any methods not defined in class Object.

Vector v = new Vector ( );

Student s = new Student( “Joe” );Student otherStudent;

v.addElement( s );

otherStudent = (Student) v.elementAt(0);

Page 84: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

// Assume we have vector v and int k.// Assume int k is an index within the// range [0..(v.size( ) - 1)].

Object o;o = v.elementAt(k); // no cast needed, already Object

if (o instanceof Student){ // do stuff for Student}

if (o instanceof Cafeteria){ // do stuff for Cafeteria}

VectorsVectorsVectors and instanceof:

Design issue:This example is legal Java, but is it good programming?

Page 85: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Vectors and ArraysVectors and Arrays

Arrays: statically sizedVectors: dynamically sized

Arrays: can directly access, e.g., myArray[6]

but shouldn’t (except maybe within the class in which they’re declared IF efficiency concerns; or for testing purposes.)

Vectors: must use methods to access.

Vector services provide a good model forthe Array services you should implement.

Page 86: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Vectors versus Linked ListsVectors versus Linked ListsCan use Vectors to simulate a Linked List:

• Don’t want direct access to data, so . . .

• Provide methods for getPrevious( ), getNext( ), etc. that do the std. Linked List things.

• While the list is implemented as a Vector, the client uses it as if it’s a Linked List.

BUT . . .

There are performance implications (that may or may not matter for a given instance).

What is the cost of:

• insertion?

• deletion?

Page 87: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Vectors versus Linked ListsVectors versus Linked Lists

For ordered Linked Lists:• cost of traversal to locate target: O(N)• cost of insert/delete: O(1)• total cost: O(N)

For ordered Vector:• cost of traversal to locate target: O(N) (if accessible via direct access, then O(1) )• insertion or deletion of element implies (average case), moving O(N) elements• total cost: O(N)

Thus, at first glance, equivalent…

But what does Big Oh hide here?• Linked Lists: search thru N/2, plus insert/delete• Vectors: search thru N/2, plus moving N/2

Thus, Vectors imply twice

the work

Page 88: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Vector CapacityVector Capacity

• Capacity is dynamic

• Capacity can grow and shrink to fit needs

• Capacity grows upon demand

• Capactiy shrinks when you tell it to do so via method trimToSize( )

• Using trimToSize( ) implies performance costs upon subsequent insertion.

• When extra capacity is needed, then it grows by how much?

• Depends on which of three constructors is used . . .

Page 89: Lecture 3: More Constructors, Scope, Wrappers, Inheritance, and Object Oriented Design. Java for the Impatient

Vector CapacityVector CapacityThree Vector constructors:• public Vector (int initialCapacity, int capacityIncrements);• public Vector (int initialCapacity);• public Vector( );

First constructor (2 parameters):• begins with initialCapacity• if/when it needs to grow, it grows by size capacityIncrements.

Second constructor( 1 parameter):• begins with initialCapacity• if/when needs to grow, it grows by doubling current size.

Third construtor (no parameters):• begins with capacity of 10• if/when needs to grow, it grows by doubling current size.