java type system and object model horstmann ch.7.1-7.5, 7.7
TRANSCRIPT
Java Type System and Object Model
Horstmann ch.7.1-7.5, 7.7
QUIZstatic/dynamic type
Which – if any – errors arise?
Employee e = null;
a) e.clear();
b) e.setSalary(1000);
No error Compiler 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 typestype object
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!
type value
null type null
Non-primitive type: variables
• Variables of non-primitive type contains reference to object of same typeVehicle b;
b = new Vehicle();
• or of a subtypeVehicle 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 typeVehicle v;
v = new Automobile();
Object obj;
obj = v;
• Compiler looks at static type onlyAutomobile bmw
bmw = v;
• Use type castbmw = (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
QUIZstatic/dynamic type
Which – if any – errors arise?
Employee e = new Driver();
a) e.setBonus(10);
b) ((Manager)e).setBonus(10);
No error Compiler 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
QUIZsubtype
What is written?
Employee e = new Manager();
System.out.println(
(e instanceof Comparable) +” ”+
(e instanceof Manager) +” ”+
e.getClass().getName() );
1. true true Employee
2. true true Manager
3. true false Employee
4. true false Manager
5. false true Employee
6. false true Manager
7. false false Employee
8. false false Manager
9. I don’t know
Types
• Non-primitive types
• Primitive types• Enum types
• Object
• Equals
• Clone
• Generics
Primitive typesType value
int
boolean
char
double
. . .
-13
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; 5n
3.0a
4k
falsegood
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: ArrayListArrayList<Integer> numbers = new ArrayList<Integer>();
Autoboxing Shorthand for
numbers.add(13); numbers.add(new Integer(13));
int n = numbers.get(0); int n = (numbers.get(0)).intValue();
QUIZprimitive types
What is written?
int n1 = 5/2;
double n2 = 5/2;
double n3 = (double)5/2;
System.out.println( n1 +” ”+ n2 +” ”+ n3 );
1. 2 2 2
2. 2.0 2.0 2.0
3. 2.5 2.5 2.5
4. 2 2.5 2.5
5. 2 2.0 2.5
6. 2 2 2.5
7. 2.0 2.0 2.5
8. 2.0 2.5 2.5
9. 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 instancespublic enum Size { SMALL, MEDIUM, LARGE };
– is equivalent topublic 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 Stringint h = 0; for (int i = 0; i < s.length(); i++) h = 31 * h + s.charAt(i);
• Hash code of "eat" is 100184 • Hash code of "tea" is 114704
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(); } ...}
QUIZclone/equals
What output should we expect?
MyClass x = new MyClass();
MyClass y = x.clone();
System.out.println(
x.equals(y) +” ”+ (x == y)
);
1. true true
2. true false
3. false true
4. false 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 ?
QUIZdeep/shallow copy
How much does viggos account hold at end - in case of cloning being
Customer viggo = new Customer(
2412451111,
new Account(1000)
);
Customer twin = viggo.clone();
twin.getAccount().withdraw(200);
Shallow? Deep?
1. 1000 1000
2. 1000 800
3. 800 1000
4. 800 800
5. 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 <E> { public E get(int i) { . . . } public E set(int i, E newValue) { . . . } . . . private E[] elementData;}
• Type variables are instantiated with non-primitive types
ArrayList<Integer> = new ArrayList<Integer>();
ArrayList<int> = new ArrayList<int>();
ArrayList<Object> = new ArrayList<Integer>();
Type variable E is declared
NOTE: If S a subtype of T, ArrayList<S> is not a subtype of ArrayList<T>.
int is primitive
Generic Methods• A generic method in an ordinary (non-generic) class
public class Utils {
public static <E> void fill( ArrayList<E> a, E value, int count) { for (int i = 0; i < count; i++) a.add(value); } }
• Type parameters are inferred in call
ArrayList<String> ids = new ArrayList<String>();
Utils.fill(ids, "default", 10);
Type variable E is declared
calls Utils.<String>fill
Type Bounds• The following method is limited:
public static <E> void append(ArrayList<E> a, ArrayList<E> b) {
for (E elem : b) a.add(elem);}
Cannot append an ArrayList<Rectangle> to an ArrayList<Shape>
• Overcome limitation with type bound:
public static <E, F extends E> void append( ArrayList<E> a, ArrayList<F> b) { for (E elem : b) a.add(elem);
}
Declare 2 type variables E and FMake restriction: F is subtype of E
QUIZgeneric 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 <E, F extends Iterable<E>>
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 <E, F extends E> void append( ArrayList<E> a, ArrayList<F> b) { for (E elem : b) a.add(elem);
}
• Definition of append never uses type F. Can simplify with wildcard:
public static <E> void append( ArrayList<E> a, ArrayList<? extends E> b) {
for (E elem : b) a.add(elem);}
Wildcards• Typical example--start with
public static <E extends Comparable<E>> E getMax(ArrayList<E> a) { E max = a.get(0); for (E elem : a) if (elem.compareTo(max) > 0) max = elem; return max; } • E extends Comparable<E> so that we can call compareTo • Too restrictive--can't call with ArrayList<Manager> • Manager does not implement Comparable<Manager>, only
Comparable<Employee> • Wildcards to the rescue:
public static <E extends Comparable<? super E>> E getMax(ArrayList<E> a)
QUIZgeneric
type/wildcard
How would you expect the Collections.sort(…) method to be defined?
1. public static <E> void sort(List<E> a) { ... }
2. public static <E extends Comparable<E>>
void sort(List<E> a) { ... }
3. public static <E extends Comparable<? super E>>
void sort(List<E> a) { ... }
4. public static <E extends Comparable<E>>
void sort(List<? extends E> a) { ... }
5. public static <E>
void sort(List<? extends Comparable<? super E>> a) { ... }
6. I don’t know