Java Type System and Object Model Horstmann ch , 7.7
QUIZ static/dynamic type Which – if any – errors arise? Employee e = null; a) e.clear(); b) e.setSalary(1000); No errorCompiler error Exception on runtime 1.a),b) 2.a)b) 3.a)b) 4.b)a) 5.a),b) 6.a)b) 7.b)a) 8.b)a) 9.a),b) 10. I don’t know
Types Non-primitive types Primitive types Enum types Object Equals Clone Generics
Nonprimitive types typeobject class types Rectangle String new Rectangle(2,4,8,8) "dProg2" interface types Shape Comparable array types int[][] String[] new int[3][7] {"dIntProg","dProg2"} no objects of interface type! typevalue null type null
Non-primitive type: variables Variables of non-primitive type contains reference to object of same type Vehicle b; b = new Vehicle(); or of a sub type Vehicle c; c = New Automobile(); Vehicle d; d = new HorseCart();
Subtype Relationship T1 is subtype of T2, T1 T2 –if T1 is the same type as T2 –or T1 implements T2 –or T1 extends T2 –or there is T3 such that T1 T3 and T3 T2 –or T1 is T3[], T2 is T4[] and T3 T4 –or T1 is array type and T2 is Cloneable or Serializable –or T1 is non-primitive and T2 is Object –or T1 is null type and T2 is non-primitive
Subtype Examples Container is a subtype of Component JButton is a subtype of Component FlowLayout is a subtype of LayoutManager ListIterator is a subtype of Iterator Rectangle[] is a subtype of Shape[] Iterator is a subtype of Object
QUIZ 1 Comparable is a subtype of Object ? 2 Comparable is a subtype of String ? 3 String is a subtype of Comparable ? 4 int[] is a subtype of Object ? 5 int[] is a subtype of Object[] ? 6 Serializable[] is a subtype of Object[] ? 7 int[][] is a subtype of Serializable[] ? Yes/No
Type check: compile time Static versus dynamic type Vehicle v; v = new Automobile(); Object obj; obj = v; Compiler looks at static type only Automobile bmw bmw = v; Use type cast bmw = (Automobile) v; Compiler is happy! compile time error Static type of v is Vehicle Dynamic type of v is Automobile Static type of (Automobile)v is Automobile
Type check: runtime You may fool the compiler: Vehicle v = new HorseCart(); Automobile bmw = (Automobile) v; Compiler is happy But at runtime Static type of (Automobile)v is Automobile Exception in thread "main“ java.lang.ClassCastException: HorseCart cannot be cast to Automobile Dynamic type of v is HorseCart
QUIZ static/dynamic type Which – if any – errors arise? Employee e = new Driver(); a) e.setBonus(10); b)((Manager)e).setBonus(10); No errorCompiler error Exception on runtime 1.a),b) 2.a)b) 3.a)b) 4.b)a) 5.a),b) 6.a)b) 7.b)a) 8.b)a) 9.a),b) 10. I don’t know
Type Inquiry Test subtype: if (bmw instanceof Vehicle)... Common before casts: Vehicle fourWheeler = (Vehicle) bmw; Test exact type: if (bmw.getClass() == Vehicle.class) true if dynamic type of bmw is subtype of Vehicle true if dynamic type of bmw is Vehicle and not a subtype
QUIZ subtype What is written? Employee e = new Manager(); System.out.println( (e instanceof Comparable) +” ”+ (e instanceof Manager) +” ”+ e.getClass().getName() ); 1.true Employee 2.true Manager 3.truefalseEmployee 4.truefalseManager 5.falsetrueEmployee 6.falsetrueManager 7.false Employee 8.false Manager 9. I don’t know
Types Non-primitive types Primitive types Enum types Object Equals Clone Generics
Primitive types Typevalue int boolean char double true 'k' 4.567E-3...
Primitive type: variables Variable of primitive type contains value of same type int k = 4; boolean good = false; Widening –In assignment, a widening conversion ( char → int → double ) is automatic double a = 3; Narrowing –Conversion in the other direction (narrowing) requires a cast int n = (int) 5.7; 5 n 3.0 a 4 k false good
Wrapper Classes Primitive types aren't classes Use wrappers when objects are expected Wrapper for each type: Integer Short Long Byte Character Float Double Boolean Example: ArrayList ArrayList numbers = new ArrayList (); AutoboxingShorthand for numbers.add(13);numbers.add(new Integer(13)); int n = numbers.get(0);int n = (numbers.get(0)).intValue();
QUIZ primitive types What is written? int n1 = 5/2; double n2 = 5/2; double n3 = (double)5/2; System.out.println( n1 +” ”+ n2 +” ”+ n3 ); I don’t know
Types Non-primitive types Primitive types Enum types Object Equals Clone Generics
Enumerated Types Finite set of values –Example: { SMALL, MEDIUM, LARGE } Modelled by class with fixed number of instances public enum Size { SMALL, MEDIUM, LARGE }; –is equivalent to public class Size { private Size() {} public static final Size SMALL = new Size(); public static final Size MEDIUM = new Size(); public static final Size LARGE = new Size(); } –Private constructor! Typical use: Size imageSize = Size.MEDIUM; if (imageSize == Size.SMALL)...
Types Non-primitive types Primitive types Enum types Object Equals Clone Generics
Object : The Cosmic Superclass All classes extend Object Selected methods: String toString() boolean equals(Object obj) Object clone() Class getClass() int hashCode()
Types Non-primitive types Primitive types Enum types Object Equals Clone Generics
equals(…) a == b is false a.equals(b) false, if equals inherited from Object maybe true, if equals is overridden
Overriding equals(…) public Class Vehicle { private int noOfWheels; private String name; … public boolean equals(Object obj) { ? }
Overriding equals(…) public Class Vehicle { private int noOfWheels; private String name; … public boolean equals(Object obj) { if (obj instanceof Vehicle) { Vehicle other = (Vehicle) obj; return (noOfWheels == other.noOfWheels) && name.equals(other.name); } else return false; }
equals(…) and inheritance public Class Automobile extends Vehicle { private PowerSource power; … public boolean equals(Object obj) { ? }
equals(…) and inheritance public Class Automobile extends Vehicle { private PowerSource power; … public boolean equals(Object obj) { if (obj instanceof Automobile) { Automobile other = (Automobile) obj; return super.equals(other) && power.equals(other.power); } else return false; }
equals(…) and inheritance Asymmetry: –X.equals(Y) returns true –Y.equals(X) returns false
Requirements for equals Method equals must be equivalence relation reflexive: x.equals(x) symmetric: x.equals(y) if and only if y.equals(x) transitive: if x.equals(y) and y.equals(z), then x.equals(z) x.equals(null) must return false
perfect equals(…) public Class Vehicle { private int noOfWheels; private String name; … public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Vehicle obj = (Vehicle) obj; return (noOfWheels == other.noOfWheels) && name.equals(other.name); }
equals(…) and hashing hashCode method used in HashMap, HashSet Computes an int from an object Example: hash code of String int h = 0; for (int i = 0; i < s.length(); i++) h = 31 * h + s.charAt(i); Hash code of "eat" is Hash code of "tea" is
equals(…) and hashing Must be compatible with equals: if x.equals(y), then x.hashCode() == y.hashCode() Object.hashCode hashes memory address NOT compatible with redefined equals Remedy: Hash all fields and combine codes: public class Vehicle { public int hashCode() { return 11 * name.hashCode() + 13 * new Double(noOfWheels).hashCode(); }... }
QUIZ clone/equals What output should we expect? MyClass x = new MyClass(); MyClass y = x.clone(); System.out.println( x.equals(y) +” ”+ (x == y) ); 1.true 2.truefalse 3.falsetrue 4.false 5. I don’t know
Types Non-primitive types Primitive types Enum types Object Equals Clone Generics
Shallow copy Assignment x = y;
Deep copy cloning x = y.clone();
Shallow cloning clone inherited from Object makes shallow cloning x = y.clone();
Deep cloning Override clone to make deep cloning x = y.clone();
Overriding clone() public Class Vehicle { private int noOfWheels; private PowerSource power; … public Vehicle clone() { Vehicle twin = (Vehicle) super.clone(); twin.power = power.clone(); return twin; } Shallow cloning Deep cloning Actually, the compiler won’t accept this
Overriding clone() Public class Object { protected Object clone() { … } } public Class Vehicle implements Cloneable { public Vehicle clone() { try { Vehicle twin = (Vehicle) super.clone(); twin.power = power.clone(); return twin; catch (CloneNotSupportedException e) { return null; } } Why so complicated ? Never happens
Overriding clone() Deep cloning ?
QUIZ deep/shallow copy How much does viggos account hold at end - in case of cloning being Customer viggo = new Customer( , new Account(1000) ); Customer twin = viggo.clone(); twin.getAccount().withdraw(200); Shallow?Deep? I don’t know
Types Non-primitive types Primitive types Enum types Object Equals Clone Generics
Generic Types A generic type has one or more type variables public class ArrayList { public E get(int i) {... } public E set(int i, E newValue) {... }... private E[] elementData; } Type variables are instantiated with non-primitive types ArrayList = new ArrayList (); Type variable E is declared NOTE: If S a subtype of T, ArrayList is not a subtype of ArrayList. int is primitive
Generic Methods A generic method in an ordinary (non-generic) class public class Utils { public static void fill( ArrayList a, E value, int count) { for (int i = 0; i < count; i++) a.add(value); } } Type parameters are inferred in call ArrayList ids = new ArrayList (); Utils.fill(ids, "default", 10); Type variable E is declared calls Utils. fill
Type Bounds The following method is limited: public static void append(ArrayList a, ArrayList b) { for (E elem : b) a.add(elem); } Cannot append an ArrayList to an ArrayList Overcome limitation with type bound: public static void append( ArrayList a, ArrayList b) { for (E elem : b) a.add(elem); } Declare 2 type variables E and F Make restriction: F is subtype of E
QUIZ generic type Is method correct? 1.No, compiler error 2.No, it compiles, but it is not correct 3.Yes, it compiles and it returns true precisely when value occurs in basket 4.I don’t know public > boolean search(F basket, E value) { for (E elem : basket) if (value.equals(elem)) return true; return false; }
Wildcards Overcome limitation with type bound: public static void append( ArrayList a, ArrayList b) { for (E elem : b) a.add(elem); } Definition of append never uses type F. Can simplify with wildcard: public static void append( ArrayList a, ArrayList b) { for (E elem : b) a.add(elem); }
Wildcards Typical example--start with public static > E getMax(ArrayList a) { E max = a.get(0); for (E elem : a) if (elem.compareTo(max) > 0) max = elem; return max; } E extends Comparable so that we can call compareTo Too restrictive--can't call with ArrayList Manager does not implement Comparable, only Comparable Wildcards to the rescue: public static > E getMax(ArrayList a)
QUIZ generic type/wildcard How would you expect the Collections.sort(…) method to be defined? 1. public static void sort(List a) {... } 2. public static > void sort(List a) {... } 3. public static > void sort(List a) {... } 4. public static > void sort(List a) {... } 5. public static void sort(List > a) {... } 6. I don’t know