550 likes | 903 Views
Wildcards in the Java ™ Programming Language Neal Gafter with thanks to Mads Torgersen, University of Aarhus. Wildcards. Genericity Improves type system expressiveness Based on parametric abstraction The abstraction gap: Clashes with object-oriented (subtype) abstraction Wildcards
E N D
Wildcards in the Java™ Programming Language Neal Gafter with thanks to Mads Torgersen, University of Aarhus
Wildcards • Genericity • Improves type system expressiveness • Based on parametric abstraction • The abstraction gap: • Clashes with object-oriented (subtype) abstraction • Wildcards • Mediate the two modes of abstraction • Address deep type-theoretic issues
The Wildcards Project • University of Aarhus • Mads Torgersen, Erik Ernst, Peter von der Ahé and Christian Plesner Hansen • Sun Microsystems • Gilad Bracha and Neal Gafter • Based on previous research by • Mads Torgersen & Kresten Krab Thorup • Mirko Viroli & Atsushi Igarashi
Project Results • Design of the wildcard mechanism • Mediation of the abstraction gap • Integration with other language features • Implementation • javac, the Java compiler • Java Platform APIs • Part of JDK1.5 (Tiger)
Java Genericity interface List extends Collection { void add(Object element); Object get(int index); ... }
Java Genericity interface List extends Collection { void add(Object element); Object get(int index); ... } List numbers = new ArrayList(); numbers.add(new Integer(7)); Number n = (Number)numbers.get(0);
Java Genericity interface List<T> extends Collection<T> { void add(T element); T get(int index); ... } List numbers = new ArrayList(); numbers.add(new Integer(7)); Number n = (Number)numbers.get(0);
Java Genericity interface List<T> extends Collection<T> { void add(T element); T get(int index); ... } List<Number> numbers = new ArrayList<Number>(); numbers.add(new Integer(7)); Number n = numbers.get(0);
Static typecheck List numbers = ... numbers.add(”Seven”); Number n = (Number)numbers.get(0); List<Number> numbers = ... numbers.add(”Seven”); Number n = numbers.get(0);
Static typecheck Runtime type error! List numbers = ... numbers.add(”Seven”); Number n = (Number)numbers.get(0); List<Number> numbers = ... numbers.add(”Seven”); Number n = numbers.get(0);
Static typecheck List numbers = ... numbers.add(”Seven”); Number n = (Number)numbers.get(0); Compile time error List<Number> numbers = ... numbers.add(”Seven”); Number n = numbers.get(0);
Object-Oriented Abstraction Common view on common properties Collection Set List
Object-Oriented Abstraction Common view on common properties Collection Set List List l = ...; Collection c = l;
Object-Oriented Abstraction Pointwise subtyping Collection<Number> Set<Number> List<Number> List<Number> nl = ...; Collection<Number> nc = nl;
Parametric Abstraction What is the common view? ? List<String> List<Number>
In the ”old” days... ...any List was just a List List List List List numbers = ...; List things = numbers; things.add(”Seven”); Number n = (Number)number.get(0);
Runtime type error! In the ”old” days... ...any List was just a List List List List List numbers = ...; List things = numbers; things.add(”Seven”); Number n = (Number)number.get(0);
The Array approach Runtime store check on every assignment Object[] String[] Number[] Number[] numbers = ...; Object[] things = numbers; things[0] = ”Seven”; Number n = numbers[0];
The Array approach Runtime store check on every assignment Object[] String[] Number[] Runtime type error! Number[] numbers = ...; Object[] things = numbers; Things[0] = ”Seven”; Number n = numbers[0];
Can we do the same for List? List<Object> ? List<String> List<Number> Runtime type error? List<Number> numbers = ...; List<Object> things = numbers; things.add(”Seven”); Number n = numbers.get(0);
Can we do the same for List? Erasure: No type argument info at runtime List<Object> ? List<String> List<Number> Runtime type error? List<Number> numbers = ...; List<Object> things = numbers; things.add(”Seven”); Number n = numbers.get(0);
Can we do the same for List? Erasure: No type argument info at runtime List<Object> List<String> List<Number> Runtime type error! List<Number> numbers = ...; List<Object> things = numbers; things.add(”Seven”); Number n = numbers.get(0);
Can we do the same for List? No type argument info at runtime List<Object> List<String> List<Number> Compile time error! List<Number> numbers = ...; List<Object> things = numbers; things.add(”Seven”); Number n = numbers.get(0);
The raw types approach List ? List<String> List<Number> List<Number> numbers = ...; List things = numbers; things.add(”Seven”); Number n = numbers.get(0);
The raw types approach Compile time type check undermined List ? List<String> List<Number> List<Number> numbers = ...; List things = numbers; things.add(”Seven”); Number n = numbers.get(0); Runtime type error!
The raw types approach Compile time type check undermined List List<String> List<Number> Compile time warning List<Number> numbers = ...; List things = numbers; things.add(”Seven”); Number n = numbers.get(0);
The raw types approach Compile time type check undermined List List<String> List<Number> Compile time warning List<Number> numbers = ...; List things = numbers; things.add(”Seven”); Number n = numbers.get(0);
The GJ approach Object List<String> List<Number> List<Number> numbers = ...; Object things = numbers; things.add(”Seven”); Object o = things.get(0);
The GJ approach Object List<String> List<Number> List<Number> numbers = ...; Object things = numbers; things.add(”Seven”); Object o = things.get(0); Compile time error!
The GJ approach Cannot use common interface Object List<String> List<Number> List<Number> numbers = ...; Object things = numbers; things.add(”Seven”); Object o = things.get(0); Compile time error!
The GJ approach Cannot use common interface Object List<String> List<Number> List<Number> numbers = ...; Object things = numbers; things.add(”Seven”); Object o = things.get(0); Compile time error!
Requirements for a common view • It should be some kind of List • so that we can safely get elements out of it • It should prevent insertion of wrong elements • to avoid heap pollution • It should do so at compile time • because we have no runtime type argument info • It must prevent insertion of any elements • because it is a share view of all Lists
Wildcards ”List of something ” ? List< > List<String> List<Number>
Wildcards ”List of something ” ? List< > List<String> List<Number>
Wildcards ”List of something ” List<?> List<String> List<Number> List<Number> numbers = ...; List<?> things = numbers; things.add(”Seven”); Object o = things.get(0);
Wildcards ”List of something ” List<?> List<String> List<Number> List<Number> numbers = ...; List<?> things = numbers; things.add(”Seven”); Object o = things.get(0);
Wildcards in Collections package java.util; public interface Collection<E> { boolean containsAll(Collection<?> c); boolean removeAll(Collection<?> c); ... }
Can we do better? Integer and Float are related List<?> List<Float> List<Integer>
Bounded Wildcards Numbers come out List<? extends Number> List<Float> List<Integer> List<Integer> ints = ...; List<? extends Number> numbers = ints; Number n = numbers.get(0); numbers.add(.7F);
Bounded Wildcards Adding still prohibited List<? extends Number> List<Float> List<Integer> List<Integer> ints = ...; List<? extends Number> numbers = ints; Number n = numbers.get(0); numbers.add(.7F);
Extends-bounds in Collections package java.util; public interface Collection<E> { boolean containsAll(Collection<?> c); boolean removeAll(Collection<?> c); boolean addAll(Collection<? extends E> c); ... }
What can we do about adding? Adding still prohibited List<? extends Number> List<Number> List<Integer>
Super-bounded Wildcards List<? super Integer> List<Number> List<Integer> List<Number> numbers = ...; List<? super Integer> ints = numbers; ints.add(7); Integer i = ints.get(0);
Super-bounded Wildcards Only Objects come out List<? super Integer> List<Number> List<Integer> List<Number> numbers = ...; List<? super Integer> ints = numbers; ints.add(7); Integer i = ints.get(0);
TreeSet Constructors package java.util; public class TreeSet<E> implements OrderedSet<E> { public TreeSet(OrderedSet<E> c); public TreeSet(Collection<? extends E> c); public TreeSet(Comparator<? super E> c); ... }
T Collections utility methods package java.util; public class Collections { public static void reverse(List<?> list); public static void shuffle(List<?> list); public static <T> void fill( List<? super T> list, T obj); public static <T> void copy( List<? super T> dest, List<? extends T> src); ... }
Subtyping with wildcards List<?> List<? extends Number> List<? extends Integer> List<Number> List<Integer>
Subtyping with wildcards List<?> List<? super Integer> List<? super Number> List<Integer> List<Number>
Type inference Better types to choose from <T>T choose(T fst, T snd) { ... } List<Number> numbers = ... Set<String> strings = ... Collection<?> c = choose(numbers,strings)
Type inference Built-in condition expression Boolean b = ... List<Number> numbers = ... Set<String> strings = ... Collection<?> c = b ? numbers : strings