Generics in Java and Beyondjava.ociweb.com/javasig/knowledgebase/2001May/JavaGenerics.pdfspeed,...

Post on 04-Jul-2020

8 views 0 download

Transcript of Generics in Java and Beyondjava.ociweb.com/javasig/knowledgebase/2001May/JavaGenerics.pdfspeed,...

1

Generics in Java and Beyond

Martin Buechi

© 2001 by Martin Büchi

2

Overview

Generics• Abstraction of generic concepts.

• C++ templates (STL), parameterized types, ML polymorphic datatypes and functions, Beta virtual types

• First usage: CLU 1977

Talk overview• Introduction to generic programming• Implementation techniques for generics• Generics in JDK 1.5 (2003)

3

Stack: Generic Pattern & Generics

class Stack {void push(Object o) {…}

Object pop() {…}…

}

// stack of String

Stack s = new Stack();st.push(“Hello”);…

…s = (String)st.pop();

unnecessary cast

st.push(new Object()); // ok

run-time exception

class Stack<A> {void push(A o) {…}

A pop() {…}…

}

// stack of String

Stack<String> s = new Stack<String>();st.push(“Hello”);…

…s = st.pop(); // no cast needed

st.push(new Object()); // compile-time error

public Stack(Class t) {this.t = t;}

private Class t;

if(t.isInstanceOf(o))

exception

4

Bounded Polymorphism

interface Priority {int getPriority();

}class A implements Priority {

public int getPriority() {…}

}class PriorityQueue<E > {

E queue[];

void insert(E e) {…if(e.getPriority() < queue[i].getPriority()) {…}

…}

}

PriorityQueue<A> p = new PriorityQueue<A>();p.insert(new A());

implements Priority

5

F-Bounded Polymorphism

interface Comparable<I> {boolean lessThan(I o);

}class A implements Comparable<A> {

public boolean lessThan(A o) {…}

}class SortedList<E implements Comparable<E>> {

E list[];

void insert(E e) {…if(e.lessThan(list[i])) {…}

…}

}

6

Mix-Ins

interface LessAndEqual<I> {boolean lessThan(I o);

boolean equal(I o);}class A implements LessAndEqual {…}

class Relations<C implements LessAndEqual<C>> extends C {boolean lessThanEqual(Relations<C> a) {

return lessThan(a) || equal(a);

}}

Relations<A> x = new Relations<A>();Relations<A> y = new Relations<A>();if(x.lessThanEqual(y)) {…}

7

Parameterized Methods

public final class Std { public static <T implements Comparable> T min(T a, T b) {

if(a.compareTo(b) <= 0) return a; else return b; }

}

public class Main {

public static void main(String[] args) { Integer b1 = new Integer(2); Integer b2 = new Integer(5); Integer bMin = Std.min(b1, b2);

Date d1 = new Date(101, 05, 10); Date d2 = new Date(101, 03, 8); Date dMin = Std.min(d1, d2); System.out.println("The minimums are: " + bMin + " and " + dMin);

}}

8

Bounds: Name vs Structural Subtyping

class PriorityQueue<E implements Priority> {… e.getPriority() …}

class A implements Priority {int getPriority() {…}

}

class B {int getPriority() {…}

}

//okPriorityQueue<A> p = new PriorityQueue<A>();

// compile-time error with name equivalence, ok with structural equivalencePriorityQueue<B> p = new PriorityQueue<B>();

class PriorityQueue<E where {int getPriority();}> {…}

9

Insufficient Bounds: Duplicates/Overriding

Duplicate methodsclass C<A implements I> {

int m(A s) {return 1;}int m(String s) {return 2;}

}

• Instantiation C<String> illegal: two methods m(String).

Overriding errorclass C<A implements I> extends A {

int m() {return 1;}

}class X implements I {

void m() {…}

}• Instantiation C<X> illegal: int m() cannot override void m().• Negative type information would be a solution

10

Insufficient Bounds: Instance Creation

class C<A implements I> {void f() {

A a = new A();}

}

Actual parameter must be a concrete class• abstract class X implements I {…} C<X> x = new C<X>()

Actual parameter must have an accessible defaultconstructor• class Y implements I {Y(int i) {};} C<Y> y = new C<Y>()

Bound is insufficient• Instantiation that satisfies bound visible from interface may be illegal.

11

Subtyping

Subtyping of parameterized class impliessubtypingclass Collection<A> {…}

class Set<A> extends Collection<A> {…}Collection<X> x = new Set<X>

Instantion with subtype does not imply subtypingclass Collection<A> {…}class Y extends X {…}Collection<Y> y = new Collection<Y>;

Collection<X> x = y; // compile-time errorx.insert(new X()); // would violate soundness

Y[] y = new Y[10];

X[] x = y; // legalx[0] = new X(); //ArrayStoreExc.

12

Implementation: Textual Substitution

Generic declaration treated as textual macro• Source code necessary for instantiation

Big and fast• Every instantiation consumes secondary & primary storage• Speed optimization possible at compile time (limited usefulness)

Full reflective inquiry supportPackage-based accessibility too restrictive• Instantiation of generic class p.x accessing package-protected class p.y

with package-protected class q.z is not possible

Runs on current JVM• Reflection does not reveal genericity (Generic class, instantiation

parameters(s))

C++ templates based on textual substitution

13

Implementation: Heterogeneous Translation

Generic class compiled into extended class file• Compilation of generic class produces generic class file

• Normal class file generated upon instantiation

Rest as textual substitution

14

Implementation: Load-Time Instantiation

Compilation of generic class into class file withextensions for compiler and loader• Class loader creates instantiations

• Change of class loader required, but not of verifier/interpreter (security)

Small in secondary, big at run-time, pretty fast• Only one class file in secondary storage, fast to transmit (applets)

• Run-time memory needed for each instantiation• Run-time (loader, JIT, adaptive) speed optimizations possible

Full reflectionPackage-based accessibility too restrictive• Generic class p.x accessing package-protected class p.y instantiated with

package-protected class q.z is not possible

Minimal changes to JVM required

15

Implementation: Generic JVM

Compilation of generic class into class file withextensions for compiler and JVM• JVM loads, verifies, and executes generic class file

• Change of JVM, including verifier/interpreter (security)

Small in secondary, small at run-time, pretty fast• Only one class file in secondary storage, fast to transmit (applets)

• JVM can optimize run-time memory vs. speed

Full reflectionBig change to JVM required

16

Implementation: Homogeneous Translation

Compilation of generic class into class file withextensions for compiler only• Formal type parameters replaced by bound

• Loss of type safety at run time (e.g., can push Object on stack of Strings)

Small and slow• Only one class file in secondary storage, fast to transmit (applets)

• Only one instance at run time• No speed optimizations possible (small problem for reference types)• Speed penalty due to casts

Limited reflectionRuns on current JVM

17

Generics in Java

Last minute consideration by Gosling and Joy• Scrapped due to time pressure, immature proposal, complexity

Several proposals to add (ECOOP, OOPSLA)Java Community Process• JSR14• Most wanted language feature in Bug Parade

Most likely in JDK 1.5 in 2003Based on GJ• Published in OOPSLA 1998• Basis for javac in JDK 1.3

• GJ contains generic version of Collection API• Binary freely available for download

18

GJ: Overview

F-bounded polymorphismNo mix-ins (parameter as superclass)No change of the virtual machineHomogeneous translationLittle support for reflectionNo instantiation with primitive typesNo non-type parameters (functors, constants, …)Solves the generic legacy problem

19

GJ: Old Code and New Generic Libraries

Compilation: replacement of parameter by bound// GJ source

class PQ<E implements Priority> {E queue[];E removeFirst() {…}

}PQ<A> p = new PQ<A>();p.insert(new A());

A a = p.removeFirst();

Combination with old code• For JVM, generic code is like code adhering to generic pattern

– Code compiled for non-generic version of Collection API works withcompilation of generic API

Compilation of new generic instantiations• Class file extension contains bound and parameter

// Equivalent byte-code for JVM

class PQ {Priority queue[];Priority removeFirst() {…}

}PQ p = new PQ();p.insert(new A())

A a = (A)p.removeFirst();

20

GJ: Retrofitting Old Code

Retrofitting of non-generic binary code// Non-generic class

// only binary available// PriorityQueue.classclass PriorityQueue {

Priority queue[];Priority removeFirst() {…}

}

gjc PriorityQueue.java -retro PathOfClassFile• Adds generic type information from PriorityQueue.java to

PriorityQueue.class.• Does not change byte code used by JVM, only adds information for

correct compilation of instantiations of generic class.

Current GJ comes with retrofitted Collection API

// Typing information for retrofitting

// No/dummy implementation// PriorityQueue.javaclass PriorityQueue<E implements Priority> {

E queue[];E removeFirst() {return null;}

}

21

Try It!

JDK 1.5 now: GJ• http://www.cs.bell-labs.com/~wadler/pizza/gj/

C++ templates (STL)• Unbounded

For the brave: gbeta• Generics in form of virtual types.

• Run-time instantiation of generics• http://www.daimi.aau.dk/~eernst/gbeta/

22

Read More!

Genericity in Java• Java Specification Request 14:

http://java.sun.com/aboutJava/communityprocess/

• Bank, Liskov, and Myers. Parameterized Types and Java. POPL ‘97.• Thorup. Genericity in Java with Virtual Types. ECOOP ‘97.• Agesen, Freund, and Mitchell. Adding Type Parameterization to the

Java Language. OOPSLA 97.

• Bracha, Odersky, Stoutamire, and Wadler. Making the future safe forthe past: Adding Genericity to the Java Programming Language.OOPSLA ‘98.

• Cartwright and Steele. Compatible Genericity with Run-time Typesfor the Java Programming Language. OOPSLA ‘98.

Type theory• Fisher and Mitchell. The Development of Type Systems for Object-

Oriented Languages. Theory and Practice of Object Systems, 1(3):189–220.

23

Summary & Conclusions

Generics are useful• Reuse through instantiation of generic concept

• More compile-time error checking and fewer run-time exceptions• Fewer casts: easier to write and faster to execute

Implementations• Different tradeoffs with respect to secondary and primary memory,

speed, safety, reflection accuracy, and need for changes to the JVM.

Generics in Java• Official support in JDK 1.5, scheduled for 2003• GJ available now, generated code interoperable with normal Java