Java Type System and Object Model Horstmann ch.7.1-7.3.1, 7.7 - - PowerPoint PPT Presentation
Java Type System and Object Model Horstmann ch.7.1-7.3.1, 7.7 - - PowerPoint PPT Presentation
Java Type System and Object Model Horstmann ch.7.1-7.3.1, 7.7 Types Non-primitive types Primitive types Enum types Object Generics Nonprimitive types type object Rectangle new Rectangle(2,4,8,8) class types String
Types
- Non-primitive types
- Primitive types
- Enum types
- Object
- Generics
Nonprimitive types
type
- bject
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
- Variable of non-primitive type
contains reference to object of
same type
Vehicle b;
b = new Vehicle();
- or of a subtype
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 non-primitive and T2 is Object – or T1 is null type and T2 is non-primitive – or T1 is array type and T2 is Cloneable or Serializable – or T1 is T3[], T2 is T4[] and T3 T4
Subtype Example
Class Hierarchy
Subtype relations:
Integer ≤ Number ≤ Serializable ≤ Object Integer ≤ Comparable<Integer> ≤ Object int[] ≤ Serializable ≤ Object
QUIZ
- 1. Yes 2. No
Comparable<String> is a subtype of Object? Comparable<String> is a subtype of String? String is a subtype of Comparable<String>? boolean is a subtype of Object? boolean[][] is a subtype of Object?
Subtype relation
Type check: compile time
- Static versus dynamic type
Vehicle v; v = new Automobile(); Object obj;
- bj = 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
public void test(Employee e) { e.setBonus(10); ((Manager)e).setBonus(10); } … test(new Driver()); …
QUIZ
No error Compiler error Exception
- n 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 Which – if any – errors arise? Static / dynamic type A B
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
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 What is written ? Type inquiry
Types
- Non-primitive types
- Primitive types
- Enum types
- Object
- Generics
Primitive types
Type 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;
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<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();
QUIZ
int n1 = 5/2; double n2 = 5/2; double n3 = 5/(double)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 Primitive types What is written ?
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! – Implements Comparable ( SMALL < MEDIUM < LARGE) – Defines toString() (returns “SMALL”, “MEDIUM”, “LARGE”)
- Typical use:
Size imageSize = Size.MEDIUM; if (imageSize == Size.SMALL) . . .
Types
- Non-primitive types
- Primitive types
- Enum types
- Object
- 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
- Generics
Generic Types
public class NumberPair { int a; int b; public NumberPair(int x, int y) { a = x; b = y; } public String toString() { return ”[”+a+”,”+b+”]”; } } public class TextPair { String a; String b; public TextPair(String x, String y) { a = x; b = y; } public String toString() { return ”[”+a+”,”+b+”]”; } } public class Pair<T> { T a; T b; public Pair(T x, T y) { a = x; b = y; } public String toString() { return ”[”+a+”,”+b+”]”; } } NumberPair p = new NumberPair(3,5); TextPair s = new TextPair(”a”,”b”); Pair<Integer> p = new Pair<Integer>(3,5); Pair<String> s = new Pair<String>(”a”,”b”); Type variable T is declared
- 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> list1 = new ArrayList<Integer>(); ArrayList<int> list2 = new ArrayList<int>(); ArrayList<Object> list3 = new ArrayList<Integer>();
Generic Types
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
public int countNullNumber( ArrayList<Integer> l) { int count = 0; for (Integer n : l) if (n==null) count++; return count; } public int countNullText( ArrayList<String> l) { int count = 0; for (String s : l) if (s==null) count++; return count; } public <T> int countNull( ArrayList<T> l) { int count = 0; for (T t : l) if (t==null) count++; return count; } ArrayList<Integer> l1 = … ArrayList<String> l2 = … countNullNumber(l1) + countNullText(l2) countNull(l1) + countNull(l2) Type variable T is declared
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 F Make restriction: F is subtype of E
QUIZ
/* @param basket: some kind of container holding elements * @param value: a specific element (value != null) * @return true: if value occurs in basket * false: otherwise */ public <E, F extends Iterable<E>> boolean search(F basket, E value) { for (E elem : basket) if (value.equals(elem)) return true; return false; }
Is method correct? 1. No, compiler error 2. No, it compiles, but it is not correct 3. Yes, it compiles and it is correct 4. I don’t know Generic type
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)
How would you expect the Collections.sort(…) method to be defined – what should replace ?
- 1. <E>
- 2. <E extends Comparable<E>>
- 3. <E super Comparable<E>>
- 4. <E extends Comparable<? extends E>>
- 5. <E extends Comparable<? super E>>
- 6. <E super Comparable<? extends E>>
- 7. <E super Comparable<? super E>>
- 8. I don’t know
QUIZ
public static void sort(List<E> a) { ... } Generic type/wildcard