0% found this document useful (0 votes)
351 views101 pages

Adv Java

Inner Classes Generics Generics in JDK5 Runtime Generics Conclusions Toward Inner Classes An Enumeration class for FixedStacks class FixedStackEnum implements java.util.Enumeration FixedStack theStack = null; int count = theStack; public boolean hasMoreElements() return theStack.array[--count]; throw new NoSuchElementException("FixedStack");

Uploaded by

Sukumar Chandran
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
351 views101 pages

Adv Java

Inner Classes Generics Generics in JDK5 Runtime Generics Conclusions Toward Inner Classes An Enumeration class for FixedStacks class FixedStackEnum implements java.util.Enumeration FixedStack theStack = null; int count = theStack; public boolean hasMoreElements() return theStack.array[--count]; throw new NoSuchElementException("FixedStack");

Uploaded by

Sukumar Chandran
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Inner Classes Generics Generics in JDK5.

0 Runtime Generics Conclusions

Advanced Java Programming

Maurizio Cimadamore
[email protected]

DEIS
Alma Mater Studiorum—Università di Bologna

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


Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

1 Inner Classes

2 Generics

3 Generics in JDK5.0

4 Runtime Generics

5 Conclusions
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

Outline

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

2 Generics

3 Generics in JDK5.0

4 Runtime Generics

5 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 Conclusions

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];
}
}
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

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. . .
• . . . we’ll see what it means in a moment!
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

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
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 Conclusions

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
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

MI with Private Constructors

Read-only classes

• A read-only class is a MI with private constructor(s)!


• The user won’t 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!
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

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!
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

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();
}
}
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

Local Inner Classes


Useful for...
• Embedding a class declaration within the method’s 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 we’ll see)
• as MI, LI have an enclosing instance. . .
• . . . but remember, LI have an enclosing method!
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 method’s 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 it’s final
public boolean hasMoreElements() {return count > 0;}
...
};
return new E();
}
}
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

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 it’s an expression indeed!
}
...
}
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

Anonymous Inner Classes


Useful for...
• Replacing a LI which would be used only once
• Defining the class of a method’s 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
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

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);
}
}
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 Conclusions

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();
Graph.Node n1 = new Graph.Node(10,20); //full qualified name needed
Graph.Node n2 = new Graph.Node(20,10); //full qualified name needed
Graph.Arc a = new Graph.Arc(n1, n2); //full qualified name needed
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

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.)
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 can’t, since it doesn’t 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 Conclusions

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 B’s private field?)
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 Conclusions

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];
}
}
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 Conclusions

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?
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 Conclusions

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


• It’s used only once. . . any idea?
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. . .


• . . . It’s definition has been inlined directly into startWork to
achieve better encapsulation!
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

Outline

1 Inner Classes

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

3 Generics in JDK5.0

4 Runtime Generics

5 Conclusions
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

Without Java Generics?

Numbers in JDK1.4’s 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);
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

Without Java Generics?

Numbers in JDK1.4’s Collection classes


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

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
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

With Java Generics

Numbers in JDK5.0’s 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"); //won’t compile!
...
int[] intArr = toIntArray(numbers);
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

With Java Generics

Numbers in JDK5.0’s Collection classes


Vector<Number> numbers; public int[] toIntArray(Vector<Number> v) {
numbers = new Vector<Number>(); int[] res = new int[v.size()];
numbers.add(new Integer(4)); for (int i=0; i<v.size(); i++) {
... res[i] = v.get(i).intValue();
numbers.add("One"); //won’t compile! }
... return res;
int[] intArr = toIntArray(numbers); }

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!
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 Conclusions

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;}
}
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

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
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

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!
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

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
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

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 . . .
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 don’t 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 won’t 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 Conclusions

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");}
}
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 Pet’s 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 array’s 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.0’s wildcards!
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

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!
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) { List<Kitten> lk = ...
while (pets.nonEmpty()) { List<Doggy> ld = ...
pets.head.sayHello(); List<Integer> li = ...
pets = pets.tail; Pets.petGreetings(lk); //ok!
} Pets.petGreetings(ld); //ok!
} Pets.petGreetings(li); //NO!
...
}
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

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!
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) { List<Object> lo = ...
while (l.nonEmpty()) { List<Pet> lp = ...
l.head = new Doggy("NewDog"); List<Kitten> lk = ...
l = l.tail; Pets.replaceWithDogs(lo); //ok!
} Pets.replaceWithDogs(lp); //ok!
} Pets.replaceWithDogs(lk); //NO!
...
}
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

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!
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;
List<Kitten> lk = ...
while (l.nonEmpty()) {
List<Doggy> ld = ...
petCount+ = (l.head instanceof Pet) ? 1 : 0;
List<Integer> li = ...
l = l.tail;
Pets.countPets(lk); //ok!
}
Pets.countPets(ld); //ok!
return petCount;
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> =⇒ [Pet,nulltype]
List<? super Pet> =⇒ [Object,Pet]
List<?> =⇒ [Object,nulltype]
List<Doggy> =⇒ [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 Conclusions

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 W’s interval
contains T then T <: W
• List<Doggy> <: List<?>
• List<Doggy> <: List<? extends Pet>

Wildcards vs. wildcards


• Given two wildcards W and Y,if Y’s interval contains W’s
interval then W <: Y
• List<? extends Doggy> <: List<? extends Pet>
• List<? super Pet> <: List<? super Kitten>
• List<? extends Pet> <: List<?>
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 Runtime Generics Conclusions

Outline

1 Inner Classes

2 Generics

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

4 Runtime Generics

5 Conclusions
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

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
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 Conclusions

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();
}
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 collection’s elements:

The JDK1.4’s 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.0’s 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. retrieve an Iterator object i through c.iterator()
2. if i.hasNext() = false we’re done; otherwise. . .
3. retrieve next c’s element through i.next()
4. repeat from step 2
• Or you can let Java do the task for you!
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

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();
}
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 Runtime Generics Conclusions

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);
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

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)
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 Object’s Class getClass() method has
been redefined as <T> Class<? extends T> getClass()
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

Outline

1 Inner Classes

2 Generics

3 Generics in JDK5.0

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

5 Conclusions
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

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
• JVM’s runtime type system
• Generic code only runs on generic JVMs
• Better performances but compatibility issues!
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 Runtime Generics Conclusions

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;}
}
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

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;}
}
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

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;
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];//won’t 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 Conclusions

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]; //won’t compile!
}

public void push(E item) {


array[top == array.length ? top - 1 : top++] = item;
}

public E pop() {
return array[top == 0 ? top : top--];
}
...
}
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

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!
}
...
}
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

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!
}
...
}
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

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 you’re doing!
• JDK5.0 itself contains classes (e.g. Vector<E>) raising
unchecked warning!
• Is this a problem?
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

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?
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

Outline

1 Inner Classes

2 Generics

3 Generics in JDK5.0

4 Runtime Generics

5 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

• It’s time for something more challenging. . .


Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

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(...) {...}
}
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 Conclusions

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() {...}


}
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

Do You Remember This?. . .


The PermutationIterable’s 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!!
};
}
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

Do You Remember This?. . .

The PermutationUtility’s 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);
}
}
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

Any Question?
Inner Classes Generics Generics in JDK5.0 Runtime Generics Conclusions

Advanced Java Programming

Maurizio Cimadamore
[email protected]

DEIS
Alma Mater Studiorum—Università di Bologna

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

You might also like