©softmoore consultingslide 1 classes: an advanced summary part 2: inheritance and polymorphism

60
©SoftMoore Consulting Slide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

Upload: anna-hutchinson

Post on 19-Jan-2016

219 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 1

Classes: An Advanced SummaryPart 2: Inheritance and Polymorphism

Page 2: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 2

Inheritance

• Inheritance provides the capability to create new classes from existing classes by defining only the additional facilities required by the new class.

• The new class is said to be a subclass (a.k.a. derived class) of the existing class. The existing class is said to be the superclass (a.k.a. base class) of the new class. The subclass inherits the fields and methods of its superclass.

• Classes support the concept of abstract data types (user-defined types). Inheritance extends this support to allow expression of hierarchical type/subtype relationships.

Page 3: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 3

Inheritance(continued)

• Inheritance makes it easier for a programmer to express commonality among classes.

• Inheritance is a fundamental concept in the study of object-oriented programming.

• Inheritance represents the “is-a” relationship

Page 4: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 4

Inheritance in Java

• Java supports single class inheritance only

• Example:public class Employee { ... }

public class Manager extends Employee { ... }

• Methods defined in the superclass can be inherited or overridden.

• Constructors are not inherited, but the constructor for the superclass can be called by the constructor for the subclass to initialize inherited fields.

Employee

Manager

Page 5: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 5

The Keyword super

• The keyword super refers to superclass of this object.

• Example: Calling a superclass methodpublic class Manager { ... String getName() { return "manager " + super.getName(); } }

• Example: Calling a superclass constructorpublic Manager(int employeeId) { super(employeeId); }

Page 6: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 6

Defining Constructors for Subclasses

• If the constructor for a subclass does not explicitly call a constructor for the superclass, then the default constructor for the superclass is called implicitly prior to the initializations defined in the subclass constructor.public class Manager extends Employee

{ public Manager() { ... // Employee() called implicitly } ...

}

• Note: If the superclass does not have a default constructor, then a superclass constructor must be called explicitly as the first statement.

Page 7: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 7

Recommended Style for Constructors

• Do not initialize inherited fields directly within the statements of a subclass constructor.

• Try to use superclass constructors – either implicitly or explicitly – to initialize inherited fields.

• This style reduces the potential ripple effect of future modifications to the superclass.

Page 8: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 8

Order of Initialization

For any class T, the following order is followed:

• Superclass of T is initialized

• Static/instance initializer is called if present

• Fields of T are initialized in order

• Constructor for T is called

Page 9: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 9

Object Type Equivalence

• Inheritance is used to represent the “is-a” relationship between classes (a Manager is an Employee).

• In general, you can use an object of a subclass in places calling for an object of its superclass without an explicit cast.Employee m = new Manager();

• An Employee is not necessarily a ManagerManager m = new Employee(); // error!

• Given an Employee, you can try to cast it to a ManagerManager m = (Manager) someEmployee;

but if it really isn't, there will be a runtime exceptionManager m = (Manager) (new Employee()); // error!

Page 10: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 10

Class Object(The Mother of all Classes)

• Any class without an explicit superclass extends Object

• Selected methods from class ObjectObject clone()boolean equals(Object obj)void finalize()Class<? extends Object> getClass()int hashCode()String toString()

plus several methods related to threads

Page 11: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 11

Final Methods and Classes

• A subclass cannot override a method that has been declared as final.public final String getName() { return name; }

• A class may be declared final.– may not be extended (i.e., no subclasses)– all methods are automatically finalpublic final class Executive extends Manager { ... }

• Tradeoff: performance versus flexibility

Page 12: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 12

Polymorphism

• Calls to non-static, non-final methods are bound dynamically at run time to the appropriate method.– The method actually called is determined at runtime based on

the object referenced and not the class declared for the variable.

• The word polymorphism is Greek for “many forms.” In object-oriented programming terminology, polymorphism means that we can use a method name that is shared up and down a class hierarchy, with each class in the hierarchy implementing the action in a way appropriate to itself.

• In Java, polymorphism is implemented using non-static, non-final methods.

Page 13: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 13

Abstract Classes

• An abstract class is a class that is defined only for the purpose of deriving subclasses. – encapsulates commonality for all descendant classes– provides a “default” implementation for subclasses– not intended to be used for declaring objects

• An abstract method is a method signature without a corresponding body.

• A class with one or more abstract methods is an abstract class. No objects can be created for an abstract class.

• Any class that extends an abstract class is also abstract unless it overrides all “inherited” abstract methods.

Page 14: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 14

Example: Abstract Class

public abstract class Shape { private int x; private int y; private int width; private int height; private boolean isVisible;

public Shape() { ... }

public boolean isVisible() { return isVisible; }

Page 15: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 15

Example: Abstract Class(continued)

public abstract void draw();

public abstract void erase();

public void moveTo(int newx, int newy) { if (isVisible) erase(); // erase shape with old coordinates

x = newx; y = newy;

if (isVisible) draw(); // redraw shape using new coordinates }

... // other methods applicable to all shapes }

Page 16: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 16

Creating Subclasses of the Abstract Class

public class Rectangle extends Shape { ... // methods draw() and erase() // implemented for rectangles }

public class Circle extends Shape { ... // methods draw() and erase() // implemented for circles }

... other Shape subclasses

The moveTo() method for Shape is applicable todescendant classes, even if they are developed at a later date.

Page 17: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 17

Using the Abstract Class Shape

List<Shape> shapes = new LinkedList<Shape>();

shapes.add(new Circle(...));

shapes.add(new Rectangle(...));

... // add other shapes to the list

for (Shape s : shapes) s.draw();

...

for (Shape s : shapes) s.moveTo(200, 200);

Page 18: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 18

Overloading Versus Overriding

• Overloading a method– same name– same scope– different signatures– calls resolved statically by compiler

• Overriding a method– same name– same signature– different scope– calls resolved dynamically at run-time

Page 19: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting

Using Polymorphism

• Classical procedural programming languages such as C and Pascal encourage the use of “variant records” (structures with unions) that contain a type selector member or discriminant to identify the particular variant.

• Exampleenum ShapeType {CIRCLE, RECTANGLE, TRIANGLE};

Slide 19

continued on next page

Page 20: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting

Using Polymorphism(continued)

struct Shape { ShapeType kind; // kind of shape

union { struct // when shape == CIRCLE { ... // data for a circle } circle_data;

... // structs for other shapes }

Slide 20

Page 21: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 21

Using Polymorphism(continued)

• Classical procedural programming languages such as C and Pascal encourage the use of “variant records” (structures with unions) that contain a type selector member or discriminant to identify the particular variant.

• Code to process such data structures usually takes the form of a multi-way branch.switch (s.kind) { case CIRCLE: // code to process a circle break; case RECTANGLE: // code to process a rectangle break; case TRIANGLE: // code to process a triangle break; }

Page 22: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 22

Using Polymorphism(continued)

• This style of program design leads to maintenance problems when we try to extend the code by adding another kind of shape (e.g., an ellipse). Using this design, we not only have to modify ShapeType and Shape, we must also modify (and recompile and retest) all existing code containing such multi-way branches.

• Small changes can impact many methods that were previously working correctly and were thought to be stable.

Page 23: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 23

Using Polymorphism(continued)

• In many cases, the use of type selector members and multi-way branching constructs can be reworked to avoid these problems by using inheritance and polymorphism.public class Shape { ... }public class Circle extends Shape { ... }public class Rectangle extends Shape { ... }

Page 24: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 24

Using Polymorphism(continued)

• Methods common to all shapes that may need specialization for individual shape subclasses (e.g., draw(), erase(), etc.) should be declared in class Shape.

• If there is no clear default implementation, these methods should be made abstract. The logic that specializes each method to a particular shape is maintained within that shape's own class.

Page 25: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 25

Using Polymorphism(continued)

• This style of program design exploits the object-oriented features of Java. New shapes can be added without modifying existing code. Moreover, existing code designed to process arbitrary shapes will work even with the new shapes.List<Shape> shapes = new LinkedList<Shape>();

... // add shapes to the list

for (Shape s : shapes) s.draw(); // works with new shapes

Page 26: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting

Interfaces

• An interface is a reference type, similar to a class, that can contain only – constants– abstract methods (method signatures only − no implementation)– default methods (new to Java 8; must be declared as default)– static methods– nested types

• No constructors!

• No instance variables (i.e., no state information)!

• All methods in an interface are implicitly public, so the public modifier can be omitted.

Slide 26

Page 27: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 27

Interfaces(continued)

• Examplepublic interface Comparable<T> { int compareTo(T other); }

• An interface may have additional requirements explained in the comments; e.g.,(e1.compareTo((Object)e2) == 0) must have the same boolean value as e1.equals((Object)e2)

• A class can only extend one superclass, but it can implement multiple interfaces.

Page 28: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 28

Implementing an Interface

• To make a class implement an interface1. Declare that the class implements the interface

2. Provide definitions for all abstract methods in the interface.

• Example (uses compareTo() from class String)public class Employee implements Comparable<Employee> { ...

public int compareTo(Employee other) { if (lastName.equals(other.lastName)) return firstName.compareTo(other.firstName) else return lastName.compareTo(other.lastName) } }

Page 29: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 29

Using an Interface

public static void insertionSort(Comparable a[]) { int j; Comparable save;

for (int i = 1; i < a.length; ++i) { // insert a[i] into the sorted slice a[0]..a[i - 1] save = a[i]; j = i - 1; while (j >= 0 && save.compareTo(a[j]) < 0) { a[j + 1] = a[j]; --j; } a[j + 1] = save; // insert saved A[i] } }

Page 30: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 30

Example: Iterator

• Predefined (generic) interface:public interface Iterator<E> { boolean hasNext(); E next(); void remove(); }

• Any data structure can return an iterator.

• Regardless of data type, methods support traversal:void printAll(Iterator<E> iter) { while (iter.hasNext()) System.out.println(iter.next()); }

Page 31: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 31

Example: Using an Iterator

List<String> sl = new LinkedList<String>;

... // add some strings to the list

printAll(sl.iterator());

Page 32: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 32

Interfaces versus Classes

An interface is similar to a class, but there are severalimportant differences:

• An interface can’t contain constructors and therefore can’t be instantiated.

• An interface can’t contain instance variables.

• All methods in an interface type are automatically public.

• A class can extend only one existing class (single inheritance), but it can implement multiple interfaces.

Page 33: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 33

Inner Classes

• An inner class is a class that is defined inside another class.

• May be defined within a method (called a local inner class) or external to (and therefore accessible by) all methods

• Using inner classes– Inner class methods can access data from the scope in which

they are defined, including private data.– Inner classes can be hidden from other classes in the same

package.– Anonymous inner classes can simplify code; e.g., for one-time

use in responding to events.

Page 34: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 34

Characteristics of Inner Classes

• When an inner class is created, the compiler passes the this reference from the outer class to its constructor.

• An inner class method gets automatic access to both its own fields and those of the outer class that created it.

• Within the inner class, the syntax OuterClass.this denotes the reference to the outer class.

• The compiler translated inner classes to regular class files with “$” delimiting outer and inner class names.

• Only inner classes can be private. Regular classes have either package or public visibility.

Page 35: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 35

Example: Inner Class

package java.util;

public class LinkedList<E> ... { ...

public ListIterator<E> listIterator(int index) { return new ListItr(index); }

private class ListItr implements ListIterator<E> { ... // implementation details for ListIter } }

The inner class ListItr uses the reference to itsouter class to check for concurrent modifications.

Page 36: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 36

Anonymous Inner Classes

• An anonymous inner class is a local inner class without a class name

• Used when you need only one object of the class

• Cannot have constructors (but can supply parameters to the superclass constructor)

• Often used to create classes that implement interfaces

• Cryptic (ugly) syntax

Page 37: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 37

Example: Anonymous Inner Class

public class SearchFrame extends JFrame { private JButton helpButton; ...

public SearchFrame() { // make the action listener for the help button helpButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { showHelp(); } }); } ... }

Page 38: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 38

Static Inner Classes

• Occasionally you want to use an inner class to hide one class inside another (limit access), but you don’t need the inner class to have a reference to the outer class object.

• You can suppress generation of the reference to the outer class by declaring the inner class static.

Page 39: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting

Reflection: Motivation

• Suppose s is a reference to an object of some class in an inheritance hierarchy. Can you determine exactly which class the object referenced s belongs to?

• Example: Suppose that we have a list shapes of class Shape, and suppose we need to know how many circles are in the list.int count = 0;for (Shape s : shapes) { if (??? s references a circle ???) ++count; }

• How do we ask if s references a circle?

Slide 39

Page 40: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 40

Reflection(a.k.a., Runtime Type Information)

• Ability to discover and use information about an object (class, methods, fields, other internal details) at runtime

• Provides the foundation for more advanced Java features– Serialization– JavaBeans

• Can manipulate instances of classes based on runtime type information such as – construct objects without calling a constructor– invoke class methods – access arrays without brackets

Page 41: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 41

Reflection(continued)

• Used primarily by tool builders (e.g., jUnit), not application programmers.

• Basic idea– Java objects know their class at runtime

(They have a reference to a Class object.)– In Java, you can ask an object

• if it is an instance of some class

• if it implements an interface

• Related concept: the instanceof operatoremployee instanceof Manager– returns true if employee is an instance of class Manager or any

subclass of Manager– also works with interfaces

Page 42: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 42

The Reflection API

• Supports programmatic inspection, or discovery, of internal Java program components

• Allows a program to dynamically perform tasks not compiled into class file, such as object factories, that create a object dynamically at runtime

• Can be used to– analyze the capabilities of classes at runtime– access/modify fields – invoke methods– access elements of arrays

Page 43: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 43

Relevant Reflection Classes

«utility»Modifier

Array

ClassAccessibleObject

«interface»Member

java.lang.reflectjava.lang

Package

Constructor Field Method

Page 44: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 44

Selected Methods from Class Class

Field getField(String name)

Field[] getFields()

Constructor getConstructor(Class[] parameterTypes)

Constructor[] getConstructors()

Method getMethod(String name, Class[] parameterTypes)

Method[] getMethods()

Class[] getInterfaces()

int getModifiers()

String getName()

Package getPackage()

Class getSuperclass()

boolean isArray()

static Class forName(String className)

Page 45: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 45

Obtaining a Class Object

Three ways

• Using object.getClass()Button button = new Button("OK");Class buttonClass = button.getClass();

• Using Class.forName()Class buttonClass = Class.forName("java.awt.Button");

• Using <className>.classClass buttonClass = Button.class;

Note: this technique works with primitive types.Class intClass = int.class;

Page 46: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 46

Reflection for Primitive Data Types

• Use the TYPE field in the appropriate wrapper class Boolean.TYPE

• Add .class to the end of the primitive data type name. boolean.class

Page 47: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 47

Counting Circles

• AssumeList<Shape> shapes = ...int count = 0;

• Version 1: Counts circles and instances of subclassesfor (Shape s : shapes) { if (s instanceof Circle) ++count; }

• Version 2: Counts only circlesfor (Shape s : shapes) { if (s.getClass() == Circle.class) ++count; }

Page 48: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 48

Reflection Example

/** * Given an object, print out its package declaration, its * class declaration, and all method declarations for each * public method declared in the class */public static void printDeclarations(Object obj) { Class cls = obj.getClass();

// print the package declaration System.out.println("package " + cls.getPackage().getName() + ";");

// print the class declaration System.out.print(Modifier.toString(cls.getModifiers()) + " "); String fullName = cls.getName(); String simpleName = fullName.substring(fullName.lastIndexOf('.') + 1);

(continued on next page)

Page 49: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 49

Reflection Example(continued)

System.out.println(simpleName + ";");

// print all public methods Method[] methods = cls.getDeclaredMethods(); for (int i = 0; i < methods.length; ++i) { Method m = methods[i] if (Modifier.isPublic(m.getModifiers())) { System.out.print(" " + Modifier.toString(m.getModifiers()) + " "); System.out.print(m.getName() + "(");

// print the method's arguments Class[] arguments = m.getParameterTypes(); ... System.out.println(");"); } }

Page 50: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 50

The equals() Method

• The equals() method in class Object tests for equality of object references.– not usually the desired semantics for application classes– consider overriding

• Requirements– reflexive: x.equals(x) should be true for any non-null x– symmetric: x.equals(y) should be true if and only if y.equals(x) is true

– transitive: if x.equals(y) and y.equals(z) are both true, then x.equals(z) should be true

– consistent: if x and y have not changed, then repeated calls to x.equals(y) should return the same value

– if x is not null, then x.equals(null) should return false

Page 51: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 51

Overriding the equals() Method

// in class Studentpublic boolean equals(Object obj) { if (this == obj) return true;

if (obj == null) return false;

if (obj.getClass() != getClass()) return false;

Student student = (Student) obj;

return firstName.equals(student.firstName) && lastName.equals(student.lastName) && studentId == student.studentId; }

Page 52: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 52

The hashCode() Method

• A hash code is an integer derived from an object.– can be negative– used for “hash” based collection classes

• Should “scramble” objects: If x and y are distinct objects, then there should be a high probability that x.hashCode() and y.hashCode() are different.

• The default hash code inherited from Object is based on an object’s address in memory.

• If you override equals(), you should also override hashCode() to make the methods compatibleIf x.equals(y) is true, thenx.hashCode() == y.hashCode() must also be true.

Page 53: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 53

Overriding the hashCode() Method

// in class Student

@Overridepublic int hashCode() { final int prime = 31; int result = 17; result = prime*result + ((firstName == null) ? 0 : firstName.hashCode()); result = prime*result + ((lastName == null) ? 0 : lastName.hashCode()); result = prime * result + studentId; return result; }

(generated by Eclipse with minor modifications)

Page 54: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

Guidelines for Implementing hashCode()(Joshua Bloch)

1. Store some constant nonzero prime value, say 17, in an int variable called result.

2. For each significant field f in your object (each field taken into account by the equals()), do the followinga. Compute an int hashCode c for the field:

i. If the field is a boolean, compute c = (f ? 1 : 0)

ii. If the field is a byte, char, short, or int, compute c = (int) f

iii. If the field is a long, compute c = (int) (f ^ (f >>> 32))

iv. If the field is a float, compute c = Float.floatToIntBits(f)

©SoftMoore Consulting Slide 54

(continued on next page)

Page 55: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

Guidelines for Implementing hashCode()(continued)

v. If the field is a double, compute long l = Double.doubleToLongBits(f);    c = (int)(l ^ (l >>> 32))

vi. If the field is an object reference and equals() calls equals() for this field, compute c =  f.hashCode()

vii. If the field is an array, treat it as if each element were a separate field. That is, compute a hashCode() value for each significant element by applying above rules to each element.

b. Combine the hashCode c computed in step 2.a into result as follows: result = 37 * result + c;

3. Return result.

4. Look at the resulting hashCode() and make sure that equal instances have equal hash codes.

©SoftMoore Consulting Slide 55

Page 56: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 56

• The clone() method is used to create a copy of an existing object.

• Shallow copy versus deep copy(field-by-field copy versus recursive copy)

• Shallow copy acceptable for primitive types and immutable fields (e.g., int, String, Double, etc.)

The clone() Method

e1 :Employee

e2

e1 :Employee

e2 :Employee

Page 57: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

Expectations for the clone() Method

For any object x

• Different objectsx.clone() != x

• Same contentsx.clone().equals(x)

• Same classx.clone().getClass() == x.getClass()

Page 58: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 58

Implementing the clone() Method

To support cloning correctly for subclasses

• Implement the Cloneable interface.– tagging (a.k.a. marker) interface– no methods; only purpose is to allow calls to clone() method

• Redefine the clone() method as public.– declared as private in class Object– required even if calling super.clone() is sufficient for

implementation

• Enclose method body in a try/catch block that catches and ignores CloneNotSupportedException(can’t happen since we are implementing Cloneable, but we

muststill catch it anyway)

Page 59: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 59

Implementing the clone() Method(continued)

• Call super.clone() to obtain an initial object– checks to see if this object implements the Cloneable interface

(if not, throws a CloneNotSupportedException)– creates a new instance of the class of this object– initializes all fields using a shallow copy

• Perform a deep copy of each mutable field– usually implemented by calling the clone() method for that

reference

For primitive types and immutable fields, calling super.clone() is sufficient; i.e., no additional work to implement a deep copy is required.

Page 60: ©SoftMoore ConsultingSlide 1 Classes: An Advanced Summary Part 2: Inheritance and Polymorphism

©SoftMoore Consulting Slide 60

Overriding the clone() Method

public Object clone() { try { Manager result = (Manager) super.clone();

// must handle mutable field dept result.dept = (Department) dept.clone();

return result; } catch (CloneNotSupportedException ex) { return null; // will never happen } }

Assume that class Manager has several primitive and immutablefields plus a mutable field named “dept” of class Department.