CS242 Advanced Programming Concepts in Java - PowerPoint PPT Presentation

1 / 61
About This Presentation
Title:

CS242 Advanced Programming Concepts in Java

Description:

Prof. Searleman jets_at_clarkson.edu. Outline. Inheritance in Java - upcasting ... 'significant' field f in your object, compute a hash value c for it. ... 37*result ... – PowerPoint PPT presentation

Number of Views:198
Avg rating:3.0/5.0
Slides: 62
Provided by: janicets
Category:

less

Transcript and Presenter's Notes

Title: CS242 Advanced Programming Concepts in Java


1
CS242Advanced Programming Concepts in Java
  • 9/06/07
  • references casting
  • equals()

Prof. Searleman jets_at_clarkson.edu
2
Outline
  • Inheritance in Java
  • - upcasting downcasting
  • - polymorphic variables substitution
  • Effective Java methods common to all objects
  • obey the contract for equals()
  • always override hashCode() when you override
    equals
  • Arrays in Java
  • Comparable interface compareTo()
  • Sorting an array
  • Read OODP, Ch. 7pp.261-280 Effective Java, Ch.
    3pp 25-44
  • HW2, due Tuesday, 9/18/07, will be posted soon

3
UML class diagram
IS-A
IS-A
1
HAS-A
(composition)
IS-A
(inheritance)
4
  • Overloading
  • multiple versions of a method, distinguished by
    their signatures
  • (name and argument list)
  • Overriding
  • when a subclass completely replaces a method that
    it inherits from its superclass (same signature)

5
methods toString(), equals(), getClass(),
methods constructors, get/setCenter(),
get/setRadius(), computeArea() toString()
methods constructors, get/setColor() toString()
6
Overriding Specialization
  • can override an inherited method completely
  • can specialize an inherited method
  • Its common to do both

7
Upcasting downcasting
  • double z 2.75
  • int k (int) z
  • float x (float) k
  • double w 5

// downcast,
ks value is 2
// upcast,
xs value is 2.0f
// OK the int is automatically cast to a double
8
  • Polymorphic variables
  • FilledCircle fc1
  • new FilledCircle(1.5f, 10, 20, Color.red)
  • Circle c1
  • c1 fc1
  • FilledCircle fc2
  • fc2 c1
  • fc2 (FilledCircle) c1

9
  • Circle c2 new Circle(1.5f, 10, 20)
  • fc2 (FilledCircle) c2
  • Objects always know their type
  • can check w/ instanceof operator
  • if (c3 instanceof FilledCircle)
  • fc2 (FilledCircle) c3

10
method getCenter()
method getColor()
  • Circle c1
  • new FilledCircle(2.5f, 100, 200, Color.red)
  • c1.getCenter()
  • c1.getColor()
  • ((FilledCircle) c1).getColor()

// OK
// OK
// error c1s type is Circle (no getColor)
// OK the cast works
11
  • polymorphic variable
  • T ref1 new S()
  • // OK as long as every S is a T
  • principle of substitutability
  • basic idea the type declared for a variable does
    not have to match exactly the type of what it
    refers to, as long as its a substitutable type
  • Circle c1 new FilledCircle()
  • Object obj new Circle()

12
  • instances of a subclass must possess all data
    fields associated with the parent class (may have
    more, of course)
  • instances of a subclass must implement (either by
    overriding or inheriting) all functionality
    defined for the parent class (can add
    functionality)
  • so, an instance of a subclass can mimic the
    behavior of the superclass, and should be
    indistinguishable from an instance of the
    superclass if substituted in a similar situation

13
Static binding
  • static at compile-time

OK
OK
14
Static binding
  • static at compile-time

OK
NOT OK !
OK
15
Current State
TVremote.rewind() // not OK (compile-time) ((TV-V
CRremote)TVremote).rewind() // OK // the type
matches at compile-time the // method works at
run-time
16
OK
Current State
OK
TVremote.rewind() // not OK ((TV-VCRremote)TVremo
te).rewind() // not OK // the type matches at
compile-time, but the // cast fails at run-time
17
OK
OK
OK
18
NOT OK !
OK
OK
19
NOT OK !
NOT OK !
OK
20
Assume that a separate toString() is implemented
for Circle FilledCircle
Object x1 new Circle() System.out.println( x1
) // will call Circle.toString(), even though
the // type of reference x1 is Object // uses
dynamic method binding! // dynamic at run-time
21
Testing for equality
  • Every class needs its own toString() method, but
    not every class needs its own equals()
  • - example Random RNG
  • - the equals() inherited from your superclass
    already tests what you want
  • - the class is private (or package-private) and
    you are certain that equals() will never be
    invoked in that case, an accidental call to
    equals() should be an error (more on exceptions
    later)

22
Testing for equality
  • Override Object.equals() when objects in your
    class can be equal in value in some sense,
    different from equivalent
  • - circles, lines,
  • - dice?
  • - ?
  • value classes
  • Bloch, Effective Java, p. 26

23
Common problems w/ equals()
doesnt override Object.equals()
flawed
  • public class Circle
  • public Boolean equals(Circle o)
  • return (this.radius o.radius)
  • (this.center o.center)

to override a method, must have the same
signature return type
24
Common problems w/ equals()
  • public class Circle
  • public boolean equals(Object o)
  • return (this.radius o.radius)
  • (this.center o.center)

flawed
radius center are private, its OK here, but
may need accessor functions to avoid breaking
encapsulation of other classes
center is a Point cant test for equality w/
25
Item 7 Obey the general contract when overriding
equals()
  • public class Circle
  • public boolean equals(Object o)
  • return ( this.radius o.radius )
  • ( (this.center).equals(o.center) )

flawed
what if o is null? get a NullPointerException
what if object o refers to something other than a
circle, like a die for instance?
26
Rules for equality
  • reflexive x.equals(x) is true
  • symmetric x.equals(y) iff y.equals(x)
  • transitive
  • x.equals(y) y.equals(z) gt x.equals(z)
  • consistent
  • multiple calls to x.equals(y) all give the
    same result
  • cautious x.equals(null) is false

27
  • public class Circle
  • public boolean equals(Object o)
  • if (o null)
  • return false
  • if (o this)
  • return true
  • if (!(o instanceof Circle))
  • return false
  • Circle other (Circle) o
  • return (this.radius other.radius)
  • (this.center).equals(other.center) )

// required, but will be detected by // the
instanceof operator anyway
// not strictly required, but efficient
// this cast cannot fail
28
  • public boolean equals(Object o)
  • if (this o)
  • return true
  • if (!(o instanceof Circle))
  • return false
  • Circle other (Circle) o
  • return (this.radius other.radius)
  • ( (this.center).equals(other.center) )

// include this performance optimization // when
the equals test is complex
// see Effective Java pp. 33-34 for float, double
arrays
29
Template for an equals() method
  • Suppose you are the class designer for a new
    class T
  • T has 3 fields field1, field2, field3 of types
    A, B and C respectively (can generalize to n
    fields).
  • A field1 suppose that A is a primitive type
    (like int)
  • B field2 suppose that you will ignore this when
    testing for equality
  • C field3 suppose that C is an object

30
class T equals() method
  • public boolean equals(Object o)
  • // compares fields 1 and 3 for equality
  • if (!(o instanceof T))
  • return false
  • T other (T) o
  • return ( (this.field1 other.field1)
  • (this.field3).equals(other.field3) )

31
Testing for Equality in Subclasses
  • public class Circle
  • public boolean equals(Circle c)
  • // return true if same center point radius
  • public class FilledCircle extends Circle
  • public boolean equals(FilledCircle fc)
  • return super.equals(fc)
  • (this.fillColor).equals(fc.getColor()) )

flaw doesnt override Object.equals()!!
32
method public boolean equals(Object o)
method public boolean equals(Circle c) //
overloads equals() method
method public boolean equals(FilledCircle c)
// overloads equals() method
33
  • consider a list of containing a variety of shapes
    (circles, lines, squares, arrows)
  • ArrayList shapeList . / list of shapes /
  • FilledCircle fc1 / a given circle /
  • Object aShape
  • Search the list for circle fc1 traverse the list
    with aShape compare each element to fc1
  • if (fc1.equals(aShape))

starting in the FilledCircle class, look for
method w/ signature equals(Object)
34
  • if (fc1.equals(aShape))

starting in the FilledCircle class, look for
method w/ signature equals(Object)
but the equals() method in Object tests for
equivalence, not equality!
35
method public boolean equals(Object o)
method public boolean equals(Object c) //
overrides equals() method
method public boolean equals(Object c) //
overrides equals() method
36
  • if (fc1.equals(aShape))
  • if (fc1.equals(fc2))
  • Its OK to both overload and override a method,
    if it makes sense to do so

starting in the FilledCircle class, look for
method w/ signature equals(Object)
public boolean equals(Object c) matches, so
invoke this code
still matches, because every FilledCircle is an
Object, so invoke FilledCircle.equals()
37
  • public class Circle
  • public boolean equals(Object o)
  • // return true if same center point
    radius
  • public class FilledCircle extends Circle
  • public boolean equals(Object o)
  • if (!(o instanceof FilledCircle)) return false
  • FilledCircle other (FilledCircle) o
  • return super.equals(other)
  • (this.fillColor).equals(other.getColor()) )

flaw can violate symmetry
38
  • When a subclass adds one aspect to its superclass
    theres a fundamental problem with symmetry
  • Circle c1 new Circle(1.5f, 100, 200)
  • FilledCircle fc2
  • new FilledCircle(1.5f, 100, 200, Color.blue)
  • System.out.println( c1.equals(fc2) )
  • System.out.println( fc2.equals(c1) )

prints true (calls Circle.equals() which
ignores color) false (calls FilledCircle.equals
(), and c1 is not
an instance of a FilledCircle)
39
Effective use of inheritance
  • Item 14 Favor composition over inheritance
  • we will look at this issue later

40
Item 8 always override hashCode when you
override equals
  • equal objects should have equal hashcodes
  • unequal objects dont necessarily have
    different hashcodes (although hash tables will be
    more efficient if they do)
  • if you dont override hashCode in this case then
    collections will not work properly for your class

41
hashCode contract
  • hashCode() must be consistent i.e. it always
    returns the same integer whenever it is invoked
    on the same object
  • if 2 objects are equal according to the
    equals(Object) method, then they must have the
    same hashcode i.e. hashCode() returns the same
    integer for each of them
  • if 2 objects are not equal, hashCode() is not
    required to return different integer hashcodes
    for them (but it may be more efficient to do so)

42
  • Bad idea, why?
  • public class Circle
  • public int hashCode()
  • return 42

43
How to write a good hash function
  • 1. Start with a nonzero value, say 17
  • int result 17
  • 2. For each significant field f in your object,
    compute a hash value c for it.
  • How to do this depends on whether the field is a
    primitive or an object
  • 3. Combine the results
  • result 37result c

44
  • / if 2 circles are equal only if they have the
    same radius and center point /
  • public class Circle
  • public int hashCode()
  • int result 17
  • result 37result Float.floatToIntBits(radius
    )
  • result 37 result center.hashCode()
  • return result

45
Template for a hashcode() method
  • Suppose you are the class designer for a new
    class T
  • T has 3 fields field1 is a primitive type A,
    field2 is of type B but wont be used to compare
    equality, and field3 is an object type C
  • Lets suppose that A is float

46
class T hashcode() method
  • public int hashCode()
  • int result 17
  • result 37result
  • Float.floatToIntBits(field1)
  • result 37 result field3.hashCode()
  • return result

see Effective Java, p. 38 for how to compute hash
codes for other primitive values and for arrays
why 37? Its an odd prime why 17? Arbitrary, but
should be relatively prime to 37
47
Arrays in Java
  • int sides // reference, currently null
  • // int sides is also OK
  • sides new int6 // 6 slots in array
  • sides new intnumSides // also OK
  • int6 sides // ERROR (int sides6 also error)
  • for (int i 0 i lt sides.length i)
  • sidesi i 1
  • int sides 1, 2, 3, 4, 5, 6

48
java.util.Arrays
  • provides class methods for sorting searching in
    arrays
  • int sides new intnumSides
  • / initialize the array with random ints /
  • Arrays.sort(sides) // quicksort used
  • // for array of int

49
array of Objects
  • Circle hoops new Circle3
  • for (int i 0 i lt hoops.length i)
  • hoopsi.draw()
  • There arent any actual circles in the array yet

ERROR why?
50
  • Circle hoops new Circle3
  • hoops0 new Circle(1.0f, 1, 1)
  • hoops1 new Circle(2.0f, 2, 2)
  • hoops2 new Circle(3.0f, 3, 3)
  • for (int i 0 i lt hoops.length i)
  • hoopsi.draw() // draws the 3 circles

51
  • Circle hoops
  • new Circle(1.0f, 1, 1),
  • new Circle(2.0f, 2, 2),
  • new Circle(3.0f, 3, 3)
  • for (int i 0 i lt hoops.length i)
  • hoopsi.draw() // draws the 3 circles

52
  • problem want more circles in the array
  • Circle temp new Circle hoops.length 2
  • System.arrayCopy( hoops, 0, temp, 0,
    hoops.length)
  • hoops temp

53
Sorting
  • problem would like to sort the array of
    circles, but
  • how to compare two circles?
  • java.util.Arrays has overloaded sorting methods
  • public static void sort( Object a )
  • is a modified merge sort which needs to compare
    object a1 with object a2, so
  • elements must implement Comparable interface

54
Item 11 Consider implementing Comparable
  • cf. Interfaces, Chapter 6, pp. 277-291
  • public interface Comparable
  • public int compareTo( Object o )
  • Any class that implements the Comparable
    interface MUST have this compareTo() method

55
public int compareTo(Object o)
  • returns
  • -1 if this object lt other object
  • 0 if this object equals other
  • 1 if this object gt other object
  • in some sense of a natural ordering

56
implements
implements
implements
57
  • public class Circle implements Comparable
  • public int compareTo( Object o )
  • // compares radii only
  • Circle other (Circle) o
  • if (this.radius lt other.radius)
  • return -1
  • if (this.radius gt other.radius)
  • return 1
  • return 0

use lt gt to compare primitives invoke
compareTo() method to compare objects
58
  • public class Circle implements Comparable
  • public int compareTo( Object o )
  • // compares center points only
  • // (assumes Point implements Comparable)
  • Circle other (Circle) o
  • return
  • (this.center).compareTo(other.center)

exercise compare 2 circles using radius first,
then center point
59
  • public static void main(String args)
  • Circle hoops new Circle(),
  • Arrays.sort(hoops) // sorts the array

60
Contract for compareTo()
  • sgn(x.compareTo(y)) -sgn(y.compareTo(x))
  • x.compareTo(y) gt 0 y.compareTo(z) gt 0 implies
    x.compareTo(z) gt 0
  • x.compareTo(y) 0 implies that for all z,
    sgn(x.compareTo(z)) sgn(y.compareTo(z))
  • strongly recommended that
  • (x.compareTo(y) 0) (x.equals(y))
  • i.e. consistent with equals

61
Summary
  • Item 9 Always override toString()
  • Item 7 Obey the contract when overriding
    equals()
  • Item 8 Always override hashCode() when you
    override equals()
  • Item 11 Consider implementing the Comparable
    interface write compareTo()
  • Be sure that an array of Objects is initialized
    to actual objects before doing anything with them
  • Make effective use of the Arrays class in
    java.util
Write a Comment
User Comments (0)
About PowerShow.com