0% found this document useful (0 votes)
40 views34 pages

Java: Generics and Annotations

Generics allow you to abstract over types. The most common examples are container types, the collection hierarchy. A generic interface takes a type as a parameter.

Uploaded by

slave0405
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
40 views34 pages

Java: Generics and Annotations

Generics allow you to abstract over types. The most common examples are container types, the collection hierarchy. A generic interface takes a type as a parameter.

Uploaded by

slave0405
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 34

8.

Java: Generics and Annotations

P2 Clients and Servers

Generics and Annotations

Sources
> David Flanagan, Java in a Nutshell, 5th Edition, OReilly.
> GoF, Design Patterns. Elements of Reusable ObjectOriented Software, Addison Wesley,1997.
> Gilad Bracha, Generics in the Java Programming
Language, 2004

O. Nierstrasz, O. Greevy, A. Kuhn

8.2

P2 Clients and Servers

Roadmap

Generics
> Annotations
> Model-Driven Engineering
>

O. Nierstrasz, O. Greevy, A. Kuhn

8.3

P2 Clients and Servers

Roadmap

Generics
> Annotations
> Model-Driven Engineering
>

O. Nierstrasz, O. Greevy, A. Kuhn

8.4

P2 Clients and Servers

Why do we need generics?

Generics allow you to abstract over types.


The most common examples are container types,
the collection hierarchy.

O. Nierstrasz, O. Greevy, A. Kuhn

8.5

P2 Clients and Servers

Motivating Example Old Style

List stones = new LinkedList();


stones.add(new Stone(RED));
stones.add(new Stone(GREEN));
stones.add(new Stone(RED));
Stone first = (Stone) stones.get(0);

The cast is annoying


but essential!

public int countStones(Color color) {


int tally = 0;
Iterator it = stones.iterator();
while (it.hasNext()) {
Stone stone = (Stone) it.next();
if (stone.getColor() == color) {
tally++;
}
}
return tally;
}
O. Nierstrasz, O. Greevy, A. Kuhn

8.6

P2 Clients and Servers

Motivating example new style using generics


List is a generic
interface that
takes a type
as a parameter.

List<Stone> stones = new LinkedList<Stone>();


stones.add(new Stone(RED));
stones.add(new Stone(GREEN));
stones.add(new Stone(RED));
Stone first = /*no cast*/ stones.get(0);
public int countStones(Color color) {
int tally = 0;
/*no temporary*/
for (Stone stone : stones) {
/*no temporary, no cast*/
if (stone.getColor() == color) {
tally++;
}
}
return tally;
}

O. Nierstrasz, O. Greevy, A. Kuhn

8.7

P2 Clients and Servers

Compile Time vs. Runtime Safety


List stones = new LinkedList();
stones.add(ceci nest pas un stone);

Old
way

...
Stone stone = (Stone) stones.get(0);

New
way

No check, unsafe

List<Stone> stones = new LinkedList<Stone>();


stones.add(ceci nest pas un stone);

Runtime error

Compile time check

...
Stone stone = stones.get(0);

O. Nierstrasz, O. Greevy, A. Kuhn

Runtime is safe

8.8

P2 Clients and Servers

Stack Example

public interface StackInterface {


public boolean isEmpty();
public int size();
public void push(Object item);
public Object top();
public void pop();
}

public interface StackInterface<E> {


public boolean isEmpty();
public int size();
public void push(E item);
public E top();
public void pop();
}
O. Nierstrasz, O. Greevy, A. Kuhn

Old way

New way:
we define a
generic
interface that
takes a type
parameter
8.9

P2 Clients and Servers

Linked Stack Example


public class LinkStack<E> implements StackInterface<E> {

public class Cell {


public E item;
public Cell next;
public Cell(E item, Cell next) {
this.item = item;
this.next = next;
}
}

public E top() {
assert !this.isEmpty();
return top.item;
}
O. Nierstrasz, O. Greevy, A. Kuhn

8.10

P2 Clients and Servers

Creating a Stack of Integers

Stack<Integer> myStack = new LinkedStack<Integer>();


myStack.push(42); // autoboxing

When a generic is instantiated, the actual


type parameters are substituted for the
formal type parameters.

O. Nierstrasz, O. Greevy, A. Kuhn

8.11

P2 Clients and Servers

Generics and Subtyping

Bar

G<Bar>

Foo

G<Foo>

In Java, Foo is a subtype of Bar only if Foos interface strictly includes


Bars interface. Instantiated generics normally have different interfaces.
(I.e., if the type parameters are used in the public interface.)
O. Nierstrasz, O. Greevy, A. Kuhn

8.12

P2 Clients and Servers

Generics and Subtyping (II)

List<String> ls = new ArrayList<String>();

List<Object> lo = ls;

Compile error as
it is not type safe!

lo.add(0, new Object()); // legal?!


ls.get(0); // Not a string?!

O. Nierstrasz, O. Greevy, A. Kuhn

8.13

P2 Clients and Servers

In other words

Object

List<Object>

String

List<String>

O. Nierstrasz, O. Greevy, A. Kuhn

8.14

P2 Clients and Servers

Wildcards

void printCollection(Collection c) {
Iterator i = c.iterator();
while (i.hasNext()) {
System.out.println(i.next());
}
}

void printCollection(Collection<Object> c) {
for (Object e: c){
System.out.println(e);
}
}

printCollection(stones);
O. Nierstrasz, O. Greevy, A. Kuhn

We want a
method that
prints our all
the elements
of a collection

Here is a
nave attempt
at writing it
using generics
Wont compile!
8.15

P2 Clients and Servers

What type matches all kinds of collections?

Collection<?>

collection of unknown is a collection


whose element type matches
anything a wildcard type

void printCollection(Collection<?> c) {
for (Object e: c){
System.out.println(e);
}
}

printCollection(stones);
stone(java.awt.Color[r=255,g=0,b=0])
stone(java.awt.Color[r=0,g=255,b=0])
stone(java.awt.Color[r=0,g=255,b=0])
O. Nierstrasz, O. Greevy, A. Kuhn

8.16

P2 Clients and Servers

Pitfalls of wildcards

String myString;
Object myObject;
List<?> c = new ArrayList<String>();
// c.add("hello world");
// c.add(new Object());
((List<String>) c).add("hello world");
((List<Object>) c).add(new Object());

// compile error
// compile error

// String myString = c.get(0);


myString = (String) c.get(0);
myObject = c.get(0);
myString = (String) c.get(1);

// compile error

O. Nierstrasz, O. Greevy, A. Kuhn

// no compile error!

// run-time error!

8.17

P2 Clients and Servers

Bounded Wildcards
Consider a simple drawing application to draw shapes
(circles, rectangles,)
Shape

Canvas

draw(Canvas)

draw(Shape)
drawAll(List<Shape>)

Circle

O. Nierstrasz, O. Greevy, A. Kuhn

Rectangle

Limited to
List<Shape>
8.18

P2 Clients and Servers

A Method that accepts a List of any kind of


Shape

public void drawAll(List<? extends Shape>) {}

a bounded wildcard

Shape is the upper bound of the wildcard


O. Nierstrasz, O. Greevy, A. Kuhn

8.19

P2 Clients and Servers

More fun with generics

import java.util.*;

public void pushAll(Collection<? extends E> collection) {


for (E element : collection) {
All elements must
this.push(element);
be at least an E
}
}
public List<E> sort(Comparator<? super E> comp) {
List<E> list = this.asList();
Collections.sort(list, comp);
return list;
}

The comparison method


must require at most an E

O. Nierstrasz, O. Greevy, A. Kuhn

8.20

P2 Clients and Servers

Roadmap

Generics
> Annotations
> Model-Driven Engineering
>

O. Nierstrasz, O. Greevy, A. Kuhn

8.21

P2 Clients and Servers

Annotations

>

Annotations are a special kind of comment


As with comments, annotations do not change or affect the
semantics of the program, i.e. the runtime behavior.

>

Annotations are meta-descriptions


Unlike comments, annotations can be accessed and used by
third-party tools (e.g. JUnit) or even your program itself.

O. Nierstrasz, O. Greevy, A. Kuhn

8.22

P2 Clients and Servers

JUnit uses annotations

@Before
public void setup() {
@Test
public void someTest() {
@Test(expected=IOException.class)
public void anotherTest() {

JUnit uses annotations to find out which methods are test


methods, and which are part of the setup. You may even
pass parameters to the annotations.

O. Nierstrasz, O. Greevy, A. Kuhn

8.23

P2 Clients and Servers

Roadmap

Generics
> Annotations
> Model-Driven Engineering
>

O. Nierstrasz, O. Greevy, A. Kuhn

8.24

P2 Clients and Servers

The Vision of MDE

Platform
Independent
Model
software
developer
automatic
translation

O. Nierstrasz, O. Greevy, A. Kuhn

8.25

P2 Clients and Servers

Example: a model-driven UI

>

We want a UI to edit any kind of object with any kind of


properties (i.e. Model-driven Engineering)

>

The example requires these steps


Define custom annotations for getters and setters.
Annotate our classes with these annotations
Write a UI class that access these annotations at runtime to
create a custom UI

O. Nierstrasz, O. Greevy, A. Kuhn

8.26

P2 Clients and Servers

Model-driven Engineering

:Book
title: String
author: String

model-driven

Model

Model-driven UI

can be any kind of object


with any kind of properties

labels and field are automatically


created based on the model

O. Nierstrasz, O. Greevy, A. Kuhn

8.27

P2 Clients and Servers

Defining our custom annotations

import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface GetProperty {
public String value();
}

This defines a @GetProperty annotation for methods.


The annotation is accessible at runtime.

O. Nierstrasz, O. Greevy, A. Kuhn

8.28

P2 Clients and Servers

Annotating our domain classes

@GetProperty(Titel)
public void getTitle() {
return title;
}
@GetProperty(Autor)
public void getAuthor() {
return author;
}

O. Nierstrasz, O. Greevy, A. Kuhn

8.29

P2 Clients and Servers

Use reflection to access the annotations of any


object
import java.reflect.Method;
public void printAnnotatedMethods(Object obj) {
for (Method m : obj.getClass().getMethods()) {
if (m.isAnnotationPresent(GetProperty.class)) {
this.processProperty(obj, m);
}
}
}

The for loop iterates over all methods of objs Class.


The if block is only entered for annotated methods.

O. Nierstrasz, O. Greevy, A. Kuhn

8.30

P2 Clients and Servers

Use reflection to call any method of any object

import java.reflect.Method;
public void processProperty(Object obj, Method m)
throws Exception {
GetProperty g = m.getAnnotation(GetProperty.class);
this.add(new Jlabel(g.value()));
String value = (String) m.invoke(obj);
this.add(new JTextField(value));
}

We use reflection to invoke the method m on the


object obj.

O. Nierstrasz, O. Greevy, A. Kuhn

8.31

P2 Clients and Servers

What you should know!

Why do I need generics?


Why is casting dangerous?

How do I use generics?


Can I subtype a generic type?
When is the Abstract Factory pattern useful?
Some uses of Annotations?
A Model-Driven Engineering Example

O. Nierstrasz, O. Greevy, A. Kuhn

8.32

P2 Clients and Servers

Can you answer these questions?

Why is List<Object> not the supertype of List<String>?


Which pattern could we use to implement a Windowing Toolkit that

supports multiple look-and-feel user interfaces?


What are the advantages and disadvantages of using the Abstract
Factory Pattern?

O. Nierstrasz, O. Greevy, A. Kuhn

8.33

Safety Patterns

License
http://creativecommons.org/licenses/by-sa/2.5/

Attribution-ShareAlike 2.5
You are free:
to copy, distribute, display, and perform the work
to make derivative works
to make commercial use of the work

Under the following conditions:


Attribution. You must attribute the work in the manner specified by the author or licensor.

Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting
work only under a license identical to this one.
For any reuse or distribution, you must make clear to others the license terms of this work.
Any of these conditions can be waived if you get permission from the copyright holder.
Your fair use and other rights are in no way affected by the above.
Oscar Nierstrasz

34

You might also like