You are on page 1of 101

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Advanced Java Programming


Maurizio Cimadamore
mcimadamore@deis.unibo.it
DEIS
Alma Mater StudiorumUniversit`
a di Bologna

Computational Models and Languages, A.A. 2006/2007

Conclusions

Inner Classes

Generics

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Generics in JDK5.0

Runtime Generics

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Outline
1

Inner Classes
Member Inner Classes
Local Inner Classes
Anonymous Inner Classes
Static Inner Classes
Inner Classes Implementation

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Runtime Generics

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Toward Inner Classes


The FixedStack class
public class FixedStack {
Object array[];
int top = 0;
FixedStack(int fixedSizeLimit) {array = new Object[fixedSizeLimit];}
public void push(Object item) {
array[top == array.length ? top - 1 : top++] = item;
}
public Object pop() {
return array[top == 0 ? top : top--];
}
public java.util.Enumeration getEnumeration() {
return new FixedStackEnum(this);
}
}

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Toward Inner Classes


An Enumeration class for FixedStacks
class FixedStackEnum implements java.util.Enumeration {
FixedStack theStack = null;
int count = top;
public FixedStackEnum(FixedStack theStack) {
this.theStack = theStack;
this.count = theStack.top;
}
public boolean hasMoreElements() {
return count > 0;
}
public Object nextElement() {
if (count == 0) {
throw new NoSuchElementException("FixedStack");
}
return theStack.array[--count];
}
}

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Inner Classes

Introduction
JDK 1.1 introduced the key-concept of inner class
An inner class is a class whose declaration appear within:
class declarations
method bodies
expressions
The aim is in enforcing the encapsulation providing a clean

way for structuring classes within a package. . .


. . . well see what it means in a moment!

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Basic Definitions
The Scope of a class
A class is associated to an enclosing scope which can be
a package if the class is a toplevel class
a class/method declaration if the class is an inner class

4 kinds of Inner Classes. . .


Member Inner (MI) Classes
Local Inner (LI) Classes
Anonymous Inner (AI) Classes
Static Inner (SI) Classes

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Member Inner Classes at a Glance


MI sample
public class FixedStack {
...
class FixedStackEnum implements java.util.Enumeration { //MI class!
int count = top; //LI classes can refer outer fields!
public boolean hasMoreElements() {return count > 0;}
public Object nextElement() {
if (count == 0) {
throw new NoSuchElementException("FixedStack");
}
return array[--count];
}
}
public java.util.Enumeration getEnumeration() {
return new FixedStackEnum();
}
}

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Member Inner Classes


Useful for...
Hiding implementation details (private fields of a MI are

only accessible from the enclosing class scope)


Expressing dependency beetween inner/enclosing class

instances (e.g a FixedStackEnum iterates over a given


FixedStack instance)

Properties
A MI always have an enclosing instance which:
must be specified when creating a new instance of a MI
fs.new FixedStackEnum(); //fs is a FixedStack
can be accessed within a MI through the this keyword
FixedStack.this //within FixedStackEnum

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

MI with Private Constructors


Read-only classes
A read-only class is a MI with private constructor(s)!
The user wont be able to instantiate that class directly. . .
. . . but the enclosing class could to that!

A read-only class
public class FixedStack {
class FixedStackEnum implements Enumeration {
private FixedStackEnum() {...} //cannot access it from outside
}
...
}
...
FixedStack fs = new FixedStack(10);
FixedStack.FixedStackEnum it1 = fs.new FixedStackEnum();//error!
FixedStack.FixedStackEnum it1 = fs.getEnumeration();//ok!

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Private MIs
Private MI
What if a read-only class is itself declared as private?
Access forbidden (not only instantiation) from outside. . .
. . . the MI can thus be used only by its enclosing class

A read-only class
public class FixedStack {
/* cannot access it from outside */
private class FixedStackEnum implements Enumeration {
FixedStackEnum() {...} //cannot access it from outside
}
...
}
...
FixedStack fs = new FixedStack(10);
FixedStack.FixedStackEnum it1 = fs.new FixedStackEnum();//error!
FixedStack.FixedStackEnum it1 = fs.getEnumeration();//error!

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Local Inner Classes at a Glance


LI sample
public class FixedStack {
...
public java.util.Enumeration getEnumeration() {
class E implements java.util.Enumeration { //LI class!
int count = top; //LI classes can refer outer fields!
public boolean hasMoreElements() {return count > 0;}
public Object nextElement() {
if (count == 0) {
throw new NoSuchElementException("FixedStack");
}
return array[--count];
}
};
return new E();
}
}

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Local Inner Classes


Useful for...
Embedding a class declaration within the methods body

which it is used
Declaring classes to be used only locally (within the block

they are declared into)

Properties
LI have the same visibility as variables in blocks
LI may access any name available in ordinary expressions

within the same block (with some restrictions as well see)


as MI, LI have an enclosing instance. . .
. . . but remember, LI have an enclosing method!

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Sharing Local Variables


Accessing local variables within LI
LI may access any variable available in ordinary expressions

within the block they are declared into. . .


. . . provided the given variable is declared as final

An LI using a methods argument


public class FixedStack {
...
public static java.util.Enumeration makeEnum(final Object[] array) {
class E implements java.util.Enumeration { //LI class!
int count = array.length; //can access array since its final
public boolean hasMoreElements() {return count > 0;}
...
};
return new E();
}
}

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Anonymous Inner Class at a Glance


AI sample
public class FixedStack {
public java.util.Enumeration getEnumeration() {
return new java.util.Enumeration() { //AI class!
int count = top; //AI classes can refer outer fields!
public boolean hasMoreElements() {return count > 0;}
public Object nextElement() {
if (count == 0) {
throw new NoSuchElementException("FixedStack");
}
return array[--count];
}
}; //we need the ; since its an expression indeed!
}
...
}

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Anonymous Inner Classes


Useful for...
Replacing a LI which would be used only once
Defining the class of a methods actual argument on-the-fly

Properties
An AI is always a subtype of some type specified in the new

expression instantiating it. . .


new Enumeration(){...};//subtype of Enumeration
AI cannot have constructor declarations. . .
. . . The argument list of an AI new expression is passed to a

matching constructor of the superclass.


AI, as LI, may use local variables declared as final

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

More Fun with AI


AI in method calls
There are situations in which we define a class only for

overriding a few methods of its superclass/superinterface


AI and Swing
public class GUI extends JFrame {
public GUI(final String msg) {
Button b;
add(b = new Button("Click Here!"));
b.setActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(GUI.this,"Hello! "+msg);
}
});
pack(); setVisible(true);
}
}

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

More Fun with AI


AI in method calls
This tend to happen very frequently using Swing since we

have to define custom Listener classes for handling events


AI and Swing
public class GUI extends JFrame {
public GUI(final String msg) {
Button b;
add(b = new Button("Click Here!"));
b.setActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(GUI.this,"Hello! "+msg);
}
});
pack(); setVisible(true);
}
}

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Static Inner Classes at a Glance


SI sample
public class Graph {
static class Node { //SI class!
double x_coord;
double y_coord;
...
}
static class Arc { //SI class!
Node from; //we can use Node instead of Graph.Node
Node to;
...
}
private Node[] nodes; //we can use Node instead of Graph.Node
private Arc[] arcs; //we can use Node instead of Graph.Arc
...
}
...
Graph g = new
Graph.Node n1
Graph.Node n2
Graph.Arc a

Graph();
= new Graph.Node(10,20); //full qualified name needed
= new Graph.Node(20,10); //full qualified name needed
= new Graph.Arc(n1, n2); //full qualified name needed

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Static Inner Classes


Useful for...
Modeling tightly coupled entities (a Graph is made up of

some Nodes and some Arcs)


Providing meaningful namespaces (Graph.Node vs. Node)

Properties
A SI is equivalent to a toplevel class (its enclosing scope is

always a package, no enclosing instance)


SI can be instantiated using fully qualified identifiers

(Graph.Node, Graph.Arc, etc.)

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Brief Summary
Declaring an inner class
MI and SI appear within the body of a class
LI and AI appear within the body of a method

Accessing outer fields


Both MI, LI and AI can refer to fields of their enclosing scope
A SI cant, since it doesnt have an enclosing instance!

Creating an inner class


Only MI and SI can be created from outside their scopes
enclosingInstance.new MemberInner();
new EnclosingClass.StaticInner();

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Compiling Inner Classes


Inner classes as toplevel classes
javac translates inner classes into toplevel classes so that

each inner class has its own classfile


This way JVM makes no distinction beetween inner and

toplevel classes at runtime!

Some complications. . .
Must be taken into account that an inner class may access:
one of its enclosing instances (MI, LI, AI)
a final variable of its declaring scope (LI, AI);
a field (even private ones) of its enclosing class(es)
Some of the above aspect are quite not obvious (given two

classes A and B, how can A refer to a Bs private field?)

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Member Inner Classes Revised


FixedStack translated
public class FixedStack {
Object array[];
int top = 0;
FixedStack(int fixedSizeLimit) {array = new Object[fixedSizeLimit];}
public void push(Object item) {
array[top == array.length ? top - 1 : top++] = item;
}
public Object pop() {
return array[top == 0 ? top : top--];
}
public java.util.Enumeration getEnumeration() {
return new FixedStack$FixedStackEnum(this);
}
}

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Member Inner Classes Revised


FixedStackEnum translated
class FixedStack$FixedStackEnum implements java.util.Enumeration {
private FixedStack this$0; //enclosing instance!
int count;
FixedStack$FixedStackEnum(FixedStack this$0) {
this.this$0 = this$0;
int count = this$0.top; //outer field access!
}
public boolean hasMoreElements() {return count > 0;}
public Object nextElement() {
if (count == 0) {
throw new NoSuchElementException("FixedStack");
}
return this$0.array[--count];
}
}

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Translating Inner Classes into Toplevel Classes


Inner classes as toplevel classes
When compiling the example two classfiles are generated:
FixedStack.class
FixedStack$FixedStackEnum.class
Pay attention at how inner class names are encoded using $
And AI names? And name-clashing?

Accessing the enclosing instance


The this$0 field is added by the compiler to the translated

class FixedStack$FixedStackEnum
This way translated inner classes can still access fields of their

enclosing instances (e.g. this$0.top)


What if the field to be accessed is private?

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Can We Do Better Than This?


HelloWorker
public class HelloWorker {
public void startWork() {
new WorkerThread().run();
}
}
class WorkerThread implements Runnable {
public void run() {
System.out.println("Hello World!");
}
}

Properties
WorkerThread is visible to any class . . .
. . . is there any way to make WorkerThread only available

within WorkerThread?

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Can We Do Better Than This?


HelloWorker (2)
public class HelloWorker {
public void startWork() {
new WorkerThread().run();
}
private static class WorkerThread implements Runnable {
public void run() {
System.out.println("Hello World!");
}
}
}

Properties
WorkerThread is only available within WorkerThread. . .
. . . what if we want WorkerThread to be accessed only within

startWork ?

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Can We Do Better Than This?


HelloWorker (3)
public class HelloWorker {
public void startWork() {
class WorkerThread implements Runnable {
public void run() {
System.out.println("Hello World!");
}
};
new WorkerThread().run();
}
}

Properties
WorkerThread is only available within startWork
Its used only once. . . any idea?

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Can We Do Better Than This?


HelloWorker (4)
public class HelloWorker {
public void startWork() {
new Runnable {
public void run() {
System.out.println("Hello World!");
}
}.run();
}
}

Properties
WorkerThread no longer exists. . .
. . . Its definition has been inlined directly into startWork to

achieve better encapsulation!

Inner Classes

Generics

Generics in JDK5.0

Outline
1

Inner Classes

Generics
Why Java Generics?
Generic Classes/Methods
Subtyping vs. Generics
Wildcards

Generics in JDK5.0

Runtime Generics

Conclusions

Runtime Generics

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Without Java Generics?


Numbers in JDK1.4s Collection classes
public int[] toIntArray(Vector v) {
int[] res = new int[v.size()];
for (int i=0; i<v.size(); i++) {
res[i] = ((Number)v.get(i)).intValue();
}
return res;
}
...
Vector numbers;
numbers = new Vector();
numbers.add(new Integer(4));
...
numbers.add("One"); //OK for javac!
...
int[] intArr = toIntArray(numbers);

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Without Java Generics?


Numbers in JDK1.4s Collection classes
Vector numbers;
numbers = new Vector();
numbers.add(new Integer(4));
...
numbers.add("One"); //OK for javac!
...
int[] intArr = toIntArray(numbers);

public int[] toIntArray(Vector v) {


int[] res = new int[v.size()];
for (int i=0; i<v.size(); i++) {
res[i] = ((Number)v.get(i)).intValue();
}
return res;
}

Expressiveness & soundness


Java syntax provides no way to enforce that both numbers

and v are Vectors of Numbers


ClassCastExceptions may occur if:
an element which is not a Number is added to numbers
toIntValue is applied to a Vector whose element are not

Numbers

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

With Java Generics


Numbers in JDK5.0s Collection classes
public int[] toIntArray(Vector<Number> v) {
int[] res = new int[v.size()];
for (int i=0; i<v.size(); i++) {
res[i] = v.get(i).intValue();
}
return res;
}
...
Vector<Number> numbers;
numbers = new Vector<Number>();
numbers.add(new Integer(4));
...
numbers.add("One"); //wont compile!
...
int[] intArr = toIntArray(numbers);

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

With Java Generics


Numbers in JDK5.0s Collection classes
Vector<Number> numbers;
numbers = new Vector<Number>();
numbers.add(new Integer(4));
...
numbers.add("One"); //wont compile!
...
int[] intArr = toIntArray(numbers);

public int[] toIntArray(Vector<Number> v) {


int[] res = new int[v.size()];
for (int i=0; i<v.size(); i++) {
res[i] = v.get(i).intValue();
}
return res;
}

Expressiveness & soundness


Both numbers v are declared as Vectors of Numbers
The compiler can check that:
each element added to numbers is indeed a Number
toIntArray is applied to a Vector of Numbers
No more explicit cast is required!

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Generics Types in JDK5.0


Generics are useful for. . .
Abstracting code from types
Improving compile-time support and code readability

(List<String> is more expressive than just List)

History
the GJ (Generic Java) project, started in 1996, aimed to bring

support for parametric polymorphism into the Java language


Since 2004 officially part of the JDK5.0 platform!

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Declaring Generic Classes


A simple generic class
class List<E> {
E head;
List<E> tail;
List(E head, List<E> tail) {
this.head = head;
this.tail = tail;
}
List<E> append(E el) {
return nonEmpty() ? new List<E>(head, tail.append(el))
: new List<E>(el,new EmptyList<E>());
}
public boolean nonEmpty() {return true;}
}
class EmptyList<E> extends List<E> {
EmptyList() {super(null,null);}
public boolean nonEmpty() {return false;}
}

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Declaring Generic Classes


A simple generic class
class List<E> {
E head;
List<E> tail;
List(E head, List<E> tail) {
this.head = head;
this.tail = tail;
}
List<E> append(E el) {
return nonEmpty() ? new List<E>(head, tail.append(el))
: new List<E>(el,new EmptyList<E>());
}
public boolean nonEmpty() {return true;}
}

Properties
List<E> is a generic class declaring a type variable E
E is a placeholder for concrete Java types

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Using Generic Classes

Sample using a generic class


List<Integer> li = new List<Integer>(0, new EmptyList<Integer>());
li = li.append(1);
Integer res = li.tail.head;

Properties
When creating an instance of List<E> a concrete

instantiation must be provided for E (e.g. [E/Integer])


Generic objects can be used as other Java objects!

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Declaring Generic Methods


A simple generic method
class ListUtil {
public static <Z> List<Z> reverseList(List<Z> l) {
return l.nonEmpty() ? reverseList(l.tail).append(l.head)
: new EmptyList<Z>();
}
...
}

Properties
<Z>reverseList is a generic method declaring a type

variable Z
Z can only be referenced within the body of reverseList

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Using Generic Methods

Sample with a generic method call


List<String> ls = new List<String>("one",null);
ls = ls.append("two");
ls = ls.append("three");
List<String> rls2 = ListUtil.<String>reverseList(ls);

Properties
When invoking <Z>reverseList a concrete instantiation

must be provided for Z (e.g. [Z/String])


Alternatively, we could rely on type inference . . .

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Type-Inference Sounds Good. . .


Type-inference in method calls
In a generic method call, there could be cases where

specifying the instantiation of the type parameter is useless


JDK5.0 supports 2 ways of calling generic methods:
type parameters can be specified programatically. . .
. . . or they are inferred automatically by the compiler!

A sample with type-inference


EmpryList<String> els = new EmptyList<String>();
EmpryList<List<String>> ells = new EmptyList<List<String>>();
List<String> ls = new List<String>("one", els);
List<List<String>> lls = new List<List<String>>(ls,ells);
...
List<String> rls = ListUtil.<String>reverseList(ls); //[Z->String]
List<List<String>> rlls = ListUtil.reverseList(lls); //[Z->List<String>]

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

. . . But Not That Good!


Always the best?
There are cases which dont fit well with the inference scheme
Often is better specifying method type parameters explicitly

(rather than relying on type inference)


When type-inference fails. . .
class ListUtil {
...
public static <Z> List<Z> make(Z head, List<Z> tail) {
return new List<Z>(head,tail);
}
public static <Z> List<Z> empty() {
return new EmptyList<Z>();
}
}
...
List<Float> lf = ListUtil.make("One", new EmptyList<Float>()); //[Z->?]
List<Object> lo = ListUtil.empty(); //default: [Z->Object]

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

More on Type Variables


Bounded polymorphism
Instantiation of method/class type variable T can be

constrained by stating that T must:


extend a given class (through extends)
implement a given set of interfaces (through &)

If no bound is specified, T extends Object is assumed

Bounded polymorphism in action


class List<E extends Number & Comparable<E>> {...}
class EmptyList<E extends Number & Comparable<E>> {...}
...
List<Integer> li = new List<Integer>(1, new EmptyList<Integer>()); //ok
List<Double> ld = new List<Double>(1, new EmptyList<Double>()); //ok
List<Float> lf = new List<Float>(1, new EmptyList<Float>()); //ok
...
List<String> ls = new List<String>("one", new EmptyList<String>());//ko!

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Generic Quiz
A generic Cell
class Cell<E extends Number> {
E e;
public Cell(E e) {this.e = e;}
public static <K> Cell<K> makeCell(K k) {
return new Cell<K>(k);
}
}

Which statement is correct?


Cell can be instantiated to Cell<String>
Cell can only be instantiated to Cell<Number>
Cell can only be instantiated to any Cell<T>, T <: Number
This program compiles successfully

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Generic Quiz
A generic Cell
class Cell<E extends Number> {
E e;
public Cell(E e) {this.e = e;}
public static <K> makeCell(K k) {
return new Cell<K>(k);
}
}

Solutions
Cell can only be instantiated to any Cell<T>, T <: Number
This program wont compile because of the type variable K in

makeCell. . . do you see why?


Clue: it has to do with bounded polymorphism. . .

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Using Subtyping in Java


Playing with Pets
abstract class Pet {
String name;
Pet(String name) {this.name = name;}
abstract void sayHello();
}
class Doggy extends Pet {
Dog(String name) {super(name);}
void sayHello() {System.out.println("Woof");}
}
class Kitten extends Pet {
Kitten(String name) {super(name);}
void sayHello() {System.out.println("Meeow");}
}

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Inclusive Polymorphism in Java


Inclusive polymorphism through subtyping
Inheritance is a powerful tool for factorizing similar properties

into a common supertype:


is-a relation: Doggy and Kitten are Pets in the since they

have all Pets properties (e.g. name)


Code working on Pets also works on Kittens and Doggys

Playing with Pets


class Pets {
static void petGreetings(Pet[] pets) {
for (int i=0;i<pets.length;i++) {
pets[i].sayHello();
}
}
...
}

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Extending Subtyping to Generic Types


Subtyping vs. generics
Generics and subtyping are orthogonal
With generics, you reuse code
With subtyping, you reuse classes

Subtyping beetween generic types?


Given a generic class List<E> is there some useful relation

beetween List<Pet> and List<Kitten>?


The answer is NO! But would be useful such a relation?
If we could factorize List<Doggy>, List<Kitten>, . . . into a

common supertype we would be able to define functions


working with Lists of any Pet

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Java Arrays
Subtyping beetween Java arrays
There is a similarity beetween Java arrays and generic types. . .
. . . Pet[], Kitten[] can be thought of as Array<Pet>,

Array<Kitten>
if S is a subtype of T (S <: T) then S[] <: T[] as well
This is called covariance

Covariance in Java arrays


Does covariance provide a sound subtyping beetween arrays?
NO! Assigning an element to an array is unsafe!

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

ArrayStoreCheck Required for Soundness


Arrays are unsafe
String[] as = new String[] {"One", "Two"};
Object[] ao = as; //this is legal
ao[0] = new Integer(2); //throws ArrayStoreException!

Making safe arrays


The JVM enforce soundness in arrays assignments through a

runtime check
This means that when an element is assigned to an array it is

checked to be type-compatible with the arrays type


If check fails a runtime exception is thrown!

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Factorizing Generic Types


Should generics be covariant?
Factorizing generic types would be useful for defining more

general functions
Covariance could be useful in factorizing generic types
List<Kitten> <: List<Pet> since Kitten <: Pet!

This leads to an unsound type system (as for arrays)

A different approach
Instead of enforcing direct subtyping we could introduce new

types in order to factorize existing generic types


This is called use-site variance (Igarashi, Viroli, ECOOP 2004)
This is the approached exploited by JDK5.0s wildcards!

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Covariant Types in JDK5.0


Covariant Pets in action
class Pets {
static void petGreetings(List<? extends Pet> pets) {
while (pets.nonEmpty()) {
pets.head.sayHello();
pets = pets.tail;
}
}
...
}
...
List<Kitten> lk = ...
List<Doggy> ld = ...
List<Integer> li = ...
Pets.petGreetings(lk); //ok!
Pets.petGreetings(ld); //ok!
Pets.petGreetings(li); //NO!

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Covariant Types in JDK5.0


Syntax and use of covariant types
List<? extends T> is a covariant type which is supertype of

all List<S> where S <: T


List<Kitten>, List<Doggy> <: List<? extends Pet>
An element of type List<Kitten>, List<Doggy> can be

passed where a List<? extends Pet> is expected


Useful for defining read-only functionalities

Covariant Pets in action


class Pets {
static void petGreetings(List<? extends Pet> pets) {
while (pets.nonEmpty()) {
pets.head.sayHello();
pets = pets.tail;
}
}
...
}

List<Kitten> lk = ...
List<Doggy> ld = ...
List<Integer> li = ...
Pets.petGreetings(lk); //ok!
Pets.petGreetings(ld); //ok!
Pets.petGreetings(li); //NO!

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Contravariant Types in JDK5.0


Contravariant Pets in action
class Pets {
static void replaceWithDogs(List<? super Doggy> l) {
while (l.nonEmpty()) {
l.head = new Doggy("NewDog");
l = l.tail;
}
}
...
}
...
List<Object> lo = ...
List<Pet> lp = ...
List<Kitten> lk = ...
Pets.replaceWithDogs(lo); //ok!
Pets.replaceWithDogs(lp); //ok!
Pets.replaceWithDogs(lk); //NO!

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Contravariant Types in JDK5.0


Syntax and use of contravariant types
List<? super T> is a contravariant type which is supertype

of all List<S> where T <: S


List<Object>, List<Pet> <: List<? super Doggy>
An element of type List<Object>, List<Pet> can be passed

where a List<? super Doggy> is expected


Useful for defining write-only functionalities

Contravariant Pets in action


class Pets {
static void replaceWithDogs(List<? super Doggy> l) {
while (l.nonEmpty()) {
l.head = new Doggy("NewDog");
l = l.tail;
}
}
...
}

List<Object> lo = ...
List<Pet> lp = ...
List<Kitten> lk = ...
Pets.replaceWithDogs(lo); //ok!
Pets.replaceWithDogs(lp); //ok!
Pets.replaceWithDogs(lk); //NO!

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Bivariant Types in JDK5.0


Bivariant Pets in action
class Pets {
static int countPets(List<?> l) {
int petCount = 0;
while (l.nonEmpty()) {
petCount+ = (l.head instanceof Pet) ? 1 : 0;
l = l.tail;
}
return petCount;
}
...
}
...
List<Kitten> lk = ...
List<Doggy> ld = ...
List<Integer> li = ...
Pets.countPets(lk); //ok!
Pets.countPets(ld); //ok!
Pets.countPets(li); //ok!

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Bivariant Types
Syntax and use of bivariant types
List<?> is a bivariant type which is supertype of all List<S>

for every S.
List<Object>, List<Pet>, List<Doggy> <: List<?>
An element of type List<Object>, List<Pet>, List<Doggy>

can be passed where a List<?> is expected


Useful for defining functionalities which do not read nor write

Bivariant Pets in action


class Pets {
static int countPets(List<?> l) {
int petCount = 0;
while (l.nonEmpty()) {
petCount+ = (l.head instanceof Pet) ? 1 : 0;
l = l.tail;
}
return petCount;
}
...
}

List<Kitten> lk = ...
List<Doggy> ld = ...
List<Integer> li = ...
Pets.countPets(lk); //ok!
Pets.countPets(ld); //ok!
Pets.countPets(li); //ok!

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Wildcards as Intervals
An useful metaphore
You can think of a wildcard C<? [(extends|super) T]> as

a mathematical interval defined in the type space


This interval is made up of all types S for which C<S> is a

subtype of the above wildcard type


Consider as an example:

List<? extends Pet>


List<? super Pet>
List<?>
List<Doggy>

=
=
=
=

[Pet,nulltype]
[Object,Pet]
[Object,nulltype]
[Doggy,Doggy]

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Drawing Wildcards
List<?>

List<? super Pet>

List<? extends Pet>

List<Doggy>

Object

Pet

Doggy

nulltype

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Interval Intuition Useful for Subtyping


Generics vs. wildcards
Wildcard subtyping can be thought of as an interval

containment test
Given a generic type T and a wildcard W,if Ws interval
contains T then T <: W
List<Doggy> <: List<?>
List<Doggy> <: List<? extends Pet>

Wildcards vs. wildcards


Given two wildcards W and Y,if Ys interval contains Ws

interval then W <: Y


List<? extends Doggy> <: List<? extends Pet>
List<? super Pet> <: List<? super Kitten>
List<? extends Pet> <: List<?>

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Subtyping at a Glance
List<?>

List<? super Pet>

List<? extends Pet>

List<Doggy>

Object

Pet

Doggy

nulltype

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Wildcards Quiz
1
List<?>

Object

Number

nulltype

2
List<? extends Number>

Object

Number

nulltype

3
List<? super Number>

Object

Number

nulltype

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Wildcards Quiz Solved


1
List<?>

Object

Number

nulltype

2
List<? extends Number>

Object

Number

nulltype

3
List<? super Number>

Object

Number

nulltype

Inner Classes

Generics

Generics in JDK5.0

Outline
1

Inner Classes

Generics

Generics in JDK5.0
Java Collection Framework
Remarkable Generic Interfaces
Java Reflection API

Runtime Generics

Conclusions

Runtime Generics

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Generics and Wildcards in JDK5.0


The generified JDK
Some part of the standard JDK have been generified
That is they have been extended so to exploit generic types

and wildcards

Samples
Java Collection Framework
core Java interfaces (e.g. Comparable)
Java Reflection API

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Generic Collection Framework


How JCF has been generified
All collection classes have been generified!
Some remarkable examples are:
Vector<E>
ArrayList<E>
HashSet<E>
HashMap<K,V>
...
All collection classes are subtype of Collection<E>
Since Collection<E> implements Iterable<E> all collection

classes can be used within enhanced for loops!

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Generic JCF Samples


Pets and Vectors
Vector<Pet> vp = new Vector<Pet>();
vp.add(new Doggy("MyDog");
vp.add(new Kitten("MyKitten");
...
for (int i=0;i<vp.size();i++) {
vp.get(i).sayHello();
}

Pets and HashMaps


HashMap<String,Pet> map = new HashMap<String,Pet>();
map.put("Simon", new Doggy("Snoopy");
map.put("Paul", new Kitten("Kitty");
...
Set<Map.Entry<String,Pet>> entries = map.entrySet();
Iterator<Map.Entry<String,Pet>> entryIterator = entries.iterator();
while (entryIterator.hasNext()) {
entryIterator.next().getValue().sayHello();
}

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Iterating Collections in JDK1.4


Obtaining an Iterator
JCF provides a mechanism for iterating elements of a given

collection class
Every collection class must implements the iterator method
This method returns an Iterator object whose methods can

be used for iterating through the collections elements:


The JDK1.4s Iterator interface
interface Iterator {
boolean hasNext()
Object next()
void remove()
}

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Iterating Collections in JDK5.0

The Iterable interface


Collection<E> now implements the interface Iterable<E>
Iterable<E> is a one-method interface defining the method

Iterator<E> iterator()
The JDK5.0s Iterator class
interface Iterator<E> {
boolean hasNext()
E next()
void remove()
}

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

A Pattern for Iterating Collections

Iterating a Collection
For iterating all elements of a given collection c you can use

the following pattern


1.
2.
3.
4.

retrieve an Iterator object i through c.iterator()


if i.hasNext() = false were done; otherwise. . .
retrieve next cs element through i.next()
repeat from step 2

Or you can let Java do the task for you!

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

JCF Sample Revised


Without enhanced for
HashMap<String,Pet> map = new HashMap<String,Pet>();
map.put("Simon", new Doggy("Snoopy");
map.put("Paul", new Kitten("Kitty");
...
Set<Map.Entry<String,Pet>> entries = map.entrySet();
Iterator<Map.Entry<String,Pet>> entryIterator = entries.iterator();
while (entryIterator.hasNext()) {
entryIterator.next().getValue().sayHello();
}

With enhanced for


HashMap<String,Pet> map = new HashMap<String,Pet>();
map.put("Simon", new Doggy("Snoopy");
map.put("Paul", new Kitten("Kitty");
...
for (Map.Entry<String,Pet> entry : map.entrySet()) {
entry.getValue().sayHello();
}

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Enhanced for Loop


Iterating Iterable classes
All classes implementing the Iterable interface can be used

within enhanced for loops


The enhanced for loop is a brand new feature of JDK5.0
Other languages already have similar capabilities
e.g. C#s foreach statement

for (VarDecl : Expression)


Iterates through all the elements of the Iterable object

specified in Expression
each round assigning an element to the variable in VarDecl

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Building an Iterable List


Extending our List
class IterableList<E> extends List<E> implements Iterable<E> {
IterableList(E head, List<E> tail) {super(head, tail);}
public java.util.Iterator<E> iterator() {
class IterableListIterator<K> implements java.util.Iterator<K> {
List<K> list = null;
IterableListIterator(IterableList<K> l) {this.list = l;}
public boolean hasNext() {return list.nonEmpty();}
public K next() {
K temp = list.head;
list = list.tail;
return temp;
}
public void remove() {throw UnsupportedOperationException();}
};
return new IterableListIterator<E>(this);
}
...
}

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

The Comparable interface


Comparing Objects
All comparable objects must implements the Comparable<E>

interface
Comparable<E> is a one-method interface defining the

method int compareTo(E o)


Use of Comparable in java.util.Collections
<T extends Comparable<? super T>> T sort(List<T> list)
<T extends Comparable<? super T>> T min(Collection<? super T> coll)
<T extends Comparable<? super T>> T max(Collection<? super T> coll)
<T> int binarySearch(List<? extends Comparable<? super T>> list, T key)

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

The Comparator Interface


Another way of comparing Objects
Objects can also be compared by the means of an object

implementing the Comparator interface


Comparator<E> is an interface defining the methods int

compare(E e1, E e2) and boolean equals(E e)


Use of Comparator in java.util.Collections
<T> void sort(List<T> list, Comparator<? super T> c)
<T> void min(Collection<? extends T> list, Comparator<? super T> c)
<T> void max(Collection<T extends T> list, Comparator<? super T> c)
<T> int binarySearch(List<? extends T> l, T k, Comparator<? super T> c)

Inner Classes

Generics

Generics in JDK5.0

Comparing Pets
Another Pet class
abstract class Pet implements Comparable<Pet> {
String name;
Pet(String name) {
this.name = name;
}
public int compareTo(Pet pet) {
return name.compareTo(pet.name);
}
abstract void sayHello();
}

Sorting Pets
ArrayList<Doggy> ald = new ArrayList<Doggy>();
ald.add(new Doggy("3:Snoopy"));
ald.add(new Doggy("1:Pippo"));
ald.add(new Doggy("2:Pluto"));
java.util.Collections.sort(ald);
System.out.println(ald);

Runtime Generics

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Again on Generics in JCF


java.util.Collections
<T> void fill(List<? super T> list, T obj)
<T> void copy(List<? super T> dest, List<? extends T> src)
boolean disjoint(Collection<?> c1, Collection<?> c2)
int frequency(Collection<?> c, Object o)
int indexOfSubList(List<?> source, List<?> target)
void shuffle(List<?> list)

java.util.Collection<E>
boolean addAll(Collection<? extends E> c)
boolean removeAll(Collection<?> c)
boolean retainAll(Collection<?> c)

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Generics in the Reflection API


Not only Collections!
Class<T> is a parameterized class in the JDK5.0
Here, T stands for the class represented by the Class object
A number of methods in Class<T> have been redefined in

order to match with the new generic signature

Class<? super T> getSuperclass()


T newInstance()
isAssignableFrom(Class<?> cls)
<U> Class<? extends U> asSubclass(Class<U> clazz)

Moreover, the Objects Class getClass() method has

been redefined as <T> Class<? extends T> getClass()

Inner Classes

Generics

Generics in JDK5.0

Outline
1

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics
Compile time vs. Runtime Approach
Type Erasure in JDK5.0
Generic Types at Runtime
A Case Study: Generic Arrays

Conclusions

Runtime Generics

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Choosing the Right Implementation


Compile time approach
Generic code can be translated into plain Java leaving

bytecode generation phase untouched


Once compiled, generic code can run on every JVM!

This is the implementation scheme exploited in JDK5.0

Runtime approach
Direct support for generics into the JVM affects:
core classes (e.g. ClassLoader)
classfile format
JVMs runtime type system
Generic code only runs on generic JVMs
Better performances but compatibility issues!

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Type Erasure in JDK5.0


Generic types erased by javac!
In JDK5.0 generics are implemented through a compile time

technique called erasure


Erasure transform a generic Java as follows:
1. Type variables are removed from generic class/method
declarations (e.g. class List<E> class List)
2. Type variables within a generic class are replaced by their
bounds (e.g. E Object)
3. Generic expressions are replaced with non-generic ones (e.g.
new List<String> new List)
4. Synthetic cast added to preserve soundness

Inner Classes

Generics

Generics in JDK5.0

Erasing Lists
Generic List
class List<E> {
E head;
List<E> tail;
List(E head, List<E> tail) {
this.head = head;
this.tail = tail;
}
List<E> append(E el) {
return nonEmpty()
? new List<E>(head, tail.append(el))
: new List<E>(el,new EmptyList<E>());
}
public boolean nonEmpty() {
return true;
}
}
class EmptyList<E> extends List<E> {
EmptyList() {super(null,null);}
public boolean nonEmpty() {return false;}
}

Runtime Generics

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Erasing Lists
Generic List translated
class List {
Object head;
List tail;
List(Object head, List tail) {
this.head = head;
this.tail = tail;
}
List append(Object el) {
return nonEmpty()
? new List(head, tail.append(el))
: new List(el,new EmptyList());
}
public boolean nonEmpty() {
return true;
}
}
class EmptyList extends List {
EmptyList() {super(null,null);}
public boolean nonEmpty() {return false;}
}

Runtime Generics

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

The Need of Synthetic Cast


Correctness of the erased code
Correctness of Java bytecode has to be preserved when:
calling a method whose return type has been erased
accessing a field whose type has been erased
The compiler must ensure type-safety with an explicit cast!

Generic List client


List<Integer> li = new List<Integer>(0, new EmptyList<Integer>());
li = li.append(1);
List<Integer> tail = li.tail;
Integer res = tail.head;

Generic List client translated


List li = new List(0, new EmptyList());
li = li.append(1);
List tail = li.tail;
Integer res = (Integer)tail.head;

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Runtime Generics

Generic types not available at runtime


Unfortunately, erasing types through erasure means that the

JVM knows nothing about generics!


Both generic and wildcard types are said to be non-reifiable

types (not available at runtime)


Cannot test if a given object is of a non-reifiable types
Cannot create an array of a non-reifiable type
Cast to non-reifiable types allowed but not safe!

In other words, no type-dependent operation allowed for

generic/wildcard types

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Unchecked Type Conversion Lead to Heap Pollution


Unckecked warnings
A cast to a generic type raises an unchecked warning
This tells us that the compiler has no way to statically check

the correctness of the type conversion operation


Bad generic cast
List<Integer> li = new List<Integer>(0, new EmptyList<Integer>());
Object unknownList = li;
List<String> ls = (List<String>)unknownList; //unchecked warning!
String s = ls.head; //ClassCastException

Bad generic cast translated


List li = new List(0, new EmptyList());
Object unknownList = li;
List ls = (List)unknownList; //ok!
String s = (String)ls.head; //ClassCastException

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Generics Arrays not Allowed

Generic arrays are unsound


If compiler would let us create generic arrays even legal code

(no warnings raised at compile time) might fail at runtime


The resulting type system would be unsound!

Getting rid of generic arrays


List<Integer>[] liarr = new List<Integer>[5];//wont compile
liarr[0] = new List<Integer>(0, new EmptyList<Integer>());
List[] rawarr = liarr;
rawarr[1] = new List<String>("one", new EmptyList<String>());
Integer i = liarr[1].head; //would fail at runtime

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

The Problem of Generic Arrays


A (non-working) generic FixedStack
public class FixedStack<E> {
E[] array;
int top = 0;
FixedStack(int fixedSizeLimit) {
array = new E[fixedSizeLimit]; //wont compile!
}
public void push(E item) {
array[top == array.length ? top - 1 : top++] = item;
}
public E pop() {
return array[top == 0 ? top : top--];
}
...
}

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

A Possible Workaround
Another generic FixedStack
public class FixedStack<E> {
Object[] array;
int top = 0;
FixedStack(int fixedSizeLimit) {
array = new Object[fixedSizeLimit]; //ok!
}
public void push(E item) {
array[top == array.length ? top - 1 : top++] = item;
}
public E pop() {
return (E)array[top == 0 ? top : top--]; //unchecked warning!
}
...
}

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Another Workaround
Yet another generic FixedStack
public class FixedStack<E> {
E[] array;
int top = 0;
FixedStack(int fixedSizeLimit) {
array = (E[])new Object[fixedSizeLimit]; //unchecked warning!
}
public void push(E item) {
array[top == array.length ? top - 1 : top++] = item;
}
public E pop() {
return array[top == 0 ? top : top--]; //ok!
}
...
}

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

How do We Write A Generic Stack?

Lack of generic arrays as a huge problem


Classes as FixedStack cannot be generified!
All workarounds ends up in raising unchecked warnings!
To be used only if you know what youre doing!
JDK5.0 itself contains classes (e.g. Vector<E>) raising

unchecked warning!
Is this a problem?

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Breaking the JCF


An UnsafeVector
class UnsafeVector<E> extends java.util.Vector<E> {
/* java.util.Vector stores its elements into an array
* called elementData
*/
public boolean add(E o) {
super.add(o); //first, we add the element
elementData[size()-1] = o.toString();//then we replace it!
return true;
}
}

UnsafeVector is... unsafe!


UnsafeVector<Integer> uv = new UnsafeVector<Integer>();
uv.add(new Integer(1));
Integer i = uv.get(0); //throws a class cast exception - see why?

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Outline

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Runtime Generics

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Now That You Are An Advanced Java Programmer. . .


What you should have learned in this talk
Inner Classes
The need for inner classes
How to improve your code exploiting inner classes
How inner classes are supported by the JDK
Generics & Wildcards
The need for generics/wildcards
Writing reusable code exploiting generics/wildcards
How generics/wildcards are implemented in JDK5.0

Putting things together


Its time for something more challenging. . .

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Do You Remember This?. . .

The PermutationUtility class


import alice.tuprolog.*;
import java.util.*;
class PermutationUtility{
private static String theory =
"remove([X|Xs],X,Xs). \n" +
"remove([X|Xs],E,[X|Ys]):-remove(Xs,E,Ys). \n" +
"permutation([],[]). \n" +
"permutation(Xs,[X|Ys]):-remove(Xs,X,Zs),permutation(Zs,Ys).";
public static Iterable<List<Integer>> permutations(...) {...}
private static class PermutationIterable ... {...}
public static void main(...) {...}
}

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Conclusions

Do You Remember This?. . .


The permutations method
static Iterable<List<Integer>> permutations(Collection<Integer> c) {
String list="[";
boolean first=true;
for (Integer i : c){
list = list+((!first)?",":"")+i;
first=false;
}
list=list+"]";
try {
Prolog engine=new Prolog();
Term goal=new Struct("permutation",engine.toTerm(list),new Var("X"));
System.out.println(goal);
engine.setTheory(new Theory(theory));
return new PermutationIterable(engine,goal);
}
catch(Exception e) {
e.printStackTrace();
return null;
}
}

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Do You Remember This?. . .


The PermutationIterable inner class
static class PermutationIterable implements Iterable<List<Integer>>{
private Prolog p;
private SolveInfo s;
PermutationIterable(Prolog p, Term goal){
this.p=p;
try{
s=p.solve(goal);
}
catch (Exception e) {
s=null;
};
}
public Iterator<List<Integer>> iterator() {...}
}

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Do You Remember This?. . .


The PermutationIterables iterator method
public Iterator<List<Integer>> iterator(){
return new Iterator<List<Integer>>(){
public boolean hasNext(){
return (s!=null) && s.isSuccess() && p.hasOpenAlternatives();
}
public List<Integer> next(){
List<Integer> l=new LinkedList<Integer>();
try{
Iterator i=((Struct)s.getTerm("X")).listIterator();
for (;i.hasNext();){
l.add(new Integer(((Int)i.next()).intValue()));
}
s=p.solveNext();
} catch (Exception e){e.printStackTrace();}
return l;
}
public void remove(){} //not implemented yet!!
};
}

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Do You Remember This?. . .


The PermutationUtilitys main method
public static void main(String[] s) throws Exception{
List<Integer> l=new LinkedList<Integer>();
l.add(1);
l.add(2);
l.add(3);
l.add(4);
l.add(5);
l.add(6);
l.add(7);
/* since PermutationIterable is an Iterable class...
* ...we can use it within an enhanced for loop!
*/
for (List<Integer> lout : permutations(l)){
System.out.println(lout);
}
}

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Any Question?

Runtime Generics

Conclusions

Inner Classes

Generics

Generics in JDK5.0

Runtime Generics

Advanced Java Programming


Maurizio Cimadamore
mcimadamore@deis.unibo.it
DEIS
Alma Mater StudiorumUniversit`
a di Bologna

Computational Models and Languages, A.A. 2006/2007

Conclusions

You might also like