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 "dProg2" Shape interface types Comparable int[][] new int[3][7] array types String[] {"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 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 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 Subtype relation 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 ?
Type check: compile time • Static versus dynamic type Vehicle v; v = new Automobile(); Object obj; Static type of v is Vehicle obj = v; Dynamic type of v is Automobile • Compiler looks at static type only Automobile bmw compile time error bmw = v; • Use type cast bmw = (Automobile) v; Static type of (Automobile)v is Automobile • Compiler is happy!
Type check: runtime • You may fool the compiler: Vehicle v = new HorseCart(); Automobile bmw = (Automobile) v; Static type of (Automobile)v is Automobile • Compiler is happy • But at runtime Exception in thread "main“ java.lang.ClassCastException: HorseCart cannot be cast to Automobile Dynamic type of v is HorseCart
public void test(Employee e) { QUIZ A e.setBonus(10); ((Manager)e).setBonus(10); B Static / dynamic type } Which – if any – errors arise? … test(new Driver()); … No error Compiler Exception error 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) . . . true if dynamic type of bmw is subtype of Vehicle • Common before casts: Vehicle fourWheeler = (Vehicle) bmw; • Test exact type: if (bmw. getClass () == Vehicle. class ) true if dynamic type of bmw is Vehicle and not a subtype
QUIZ Employee e = new Manager(); System.out.println( (e instanceof Comparable) + Type inquiry (e instanceof Manager) + e.getClass().getName() ); What is written ? 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 • Generics
Primitive types Type value int -13 boolean true char 'k' double 4.567E-3 . . . . . .
Primitive type: variables • Variable of primitive type contains value of same type k 4 int k = 4; boolean good = false; good false • Widening – In assignment, a widening conversion ( char → int → double ) is automatic a 3.0 double a = 3; • Narrowing – Conversion in the other direction (narrowing) requires a cast n 5 int n = (int) 5.7;
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; Primitive types double n3 = 5/(double)2; System.out.println( n1 +” ”+ n2 +” ”+ n3 ); What is written ? 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 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 { public class TextPair { int a; int b; String a; String b; public NumberPair(int x, public TextPair(String x, int y) { String y) { a = x; b = y; a = x; b = y; } } public String toString() { public String toString() { return ”[”+a+”,”+b+”]”; return ”[”+a+”,”+b+”]”; } } } } Type variable T is declared NumberPair p = new NumberPair(3,5); public class Pair<T> { TextPair s = new TextPair(”a”,”b”); T a; T b; public Pair(T x, T y) { a = x; b = y; Pair<Integer> p = } new Pair<Integer>(3,5); public String toString() { Pair<String> s = return ”[”+a+”,”+b+”]”; new Pair<String>(”a”,”b”); } }
Generic Types • A generic type has one or more type variables Type variable E is declared 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>(); int is primitive ArrayList<Object> list3 = new ArrayList<Integer>(); NOTE: If S a subtype of T , ArrayList<S> is not a subtype of ArrayList<T> .
Generic Methods public int countNullNumber( public int countNullText( ArrayList<Integer> l) { ArrayList<String> l) { int count = 0; int count = 0; for (Integer n : l) for (String s : l) if (n==null) count++; if (s==null) count++; return count; return count; } } Type variable T is declared ArrayList<Integer> l1 = … public <T> int countNull( ArrayList<String> l2 = … ArrayList<T> l) { int count = 0; countNullNumber(l1) + for (T t : l) countNullText(l2) if (t==null) count++; return count; } countNull(l1) + countNull(l2)
Generic Methods • A generic method in an ordinary (non-generic) class Type variable E is declared 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); 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> Declare 2 type variables E and F • Overcome limitation with type bound: Make restriction: F is subtype of E public static <E, F extends E > void append( ArrayList<E> a, ArrayList<F> b) { for (E elem : b) a.add(elem); }
QUIZ Generic type /* @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
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); }
Recommend
More recommend