Sei sulla pagina 1di 75

CSE/IT 213 New Mexico Tech

September 23, 2011

Interfaces as Callbacks
A callback is reference to executable code that is passed
as an argument to other code.
Specify an action whenever an event occurs.
For example, a user clicks a button or selects a Menu
option.
Your program is listening for these events.
In Java, an object passes a reference to one or more of
its methods to another object.
In C and C++ use function pointers. Java uses interfaces.
1

Example
You have two classes: DisplayData which displays the
data it receives from DataSource. DataSource sends
any new numeric data it gathers to DisplayData for
display.
Design 1 - DataSource stores a reference to a DisplayData object.
Problem I am lazy. What happens when I want to
use DataSource to send its data to other objects?
Have to subclass DataSource to handle the new types.
Design 2 - the lazy way. DisplayData receives data
from the sender DataSource. Create an interface for
the receiver.
2

interface DataReceiver {
void receiveData(long i);
}
class DisplayData implements DataReceiver {
public void receiveData(long i) {
System.out.println("integer received: " + i);
}
}

class DataSource {
private DataReceiver receiver;
DataSource(DataReceiver r) {
this.receiver = r;
}
public void sendData(long i) {
this.receiver.receiveData(i);
}
}

class DataTest {
public static void main(String[] args) {
DisplayData displaydata = new DisplayData();
DataSource datasource = new DataSource(displaydata);
for(int i = 0; i < 10; i++) {
double d = 1000 * Math.random();
datasource.sendData(Math.round(d));
}
}
}
5

$ java DataTest
integer received:
integer received:
integer received:
integer received:
integer received:
integer received:
integer received:
integer received:
integer received:
integer received:

655
492
48
472
709
213
600
99
417
208

Now its easy to add another display.


class DifferentDisplay implements DataReceiver {
public void receiveData(long i) {
System.out.println("divide by 10: " + i/10.0);
}
}

class DataTest {
public static void main(String[] args) {
DisplayData displaydata = new DisplayData();
DifferentDisplay differentdisplay = new DifferentDisplay();
DataSource datasource = new DataSource(displaydata);
DataSource datasource2 = new DataSource(differentdisplay);
for(int i = 0; i < 10; i++) {
double d = 1000 * Math.random();
if (d < 500)
datasource.sendData(Math.round(d));
else
datasource2.sendData(Math.round(d));
}
}
}
8

divide by 10: 90.1


integer received: 455
divide by 10: 99.0
divide by 10: 90.1
divide by 10: 57.7
integer received: 306
integer received: 440
integer received: 267
integer received: 437
divide by 10: 86.6

Subinterfaces
You can extend interfaces.
interface BigDog extends LittleDog {...}
Use extends not implement. Not implmenting anything.
Can extend multiple interfaces
interface BigDog extends LittleDog, MediumDog { ...
Classes that implement BigDog would have to implement
LittleDog, and MediumDog as well.
For polymorphism can use interface subtypes the same
way you do as subclasses. An instance of BigDog can
be assigned to the variable LittleDog
10

Sorting - an example

Goal sort a set

of longs
import java.util.*;
class SortLongs {
public static void main(String[] args) {
ArrayList<Long> aLong = new ArrayList<Long>();
for (int i = 0; i < 10; i++) {
aLong.add(Math.round((Math.random()*100)));
}
for (int i = 0; i < aLong.size(); i++) {
System.out.println(aLong.get(i));
}
11

}
}
$ java SortLongs
33
11
79
44
15
33
18
6
36
17

Autoboxing
Long 6= long
ArrayList does not work on primitives (i.e boolean,
byte, char, short, int, long, float, double).
Long, and Byte, Character, Integer, Short, Float, Double, Boolean are called wrapper classes.
Wrapper classes are declared final - cannot subclass
them
Java automatically converts the primitive types to their
appropriate wrapper class.
12

aLong.add(Math.round((Math.random()*100)));
a long, is automatically converted to a Long object
aLong.add(new Long(Math.round((Math.random()*100))));
and Long objects
System.out.println(aLong.get(i));
are automatically converted to primitive longs
System.out.println(aLong.get(i).longValue());
This is called autoboxing

Autoboxing works with arithmetic expressions


This is valid
Integer i;
i++
Compiler un-boxes the Integer to an int, increments it,
and the boxes it back up.

Have to be careful about equality.


== tests for identical memory locations
This fails
Integer i = 100;
Integer j = 100;
if (i == j)
Need to use equals
if (i.equals(j))
13

Also, wrapper classes contain basic conversion of Strings


to appropriate data types
String s;
....
int i = Integer.parseInt(s);
Similar calls found in Byte, Short, Long, Float, and
Double

14

Back to our sort problem


ArrayList stores the elements in the order they were
inserted. add() keeps adding to the end of the list.
No sort method found in ArrayList javadoc.
But there is hope, ArrayList implements List
public class ArrayList<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, Serializable
And ArrayList and List are part of the Java Collections
framework.
15

The class Collections provides static methods that operate on the class Collection
One of the methods is
static <T extends Comparable<? super T>>
void sort(List<T> list)
Sorts the specified list into ascending order,
according to the natural ordering of its elements.
Ignoring the strange syntax since ArrayList
implements List can call the sort method with an
ArrayList

import java.util.*;
class SortLongs {
public static void main(String[] args) {
ArrayList<Long> aLong = new ArrayList<Long>();
for (int i = 0; i < 5; i++) {
aLong.add(Math.round((Math.random()*100)));
}
System.out.println("Unsorted ArrayList");
for (int i = 0; i < aLong.size(); i++) {
System.out.println(aLong.get(i));
}
16

System.out.println("\nSorted ArrayList");
Collections.sort(aLong);
for (int i = 0; i < aLong.size(); i++) {
System.out.println(aLong.get(i));
}
}
}

17

Unsorted ArrayList
80
68
15
77
42
Sorted ArrayList
15
42
68
77
80

18

What about sorting objects.


Lets sort a Book object
class Book {
Book (String title, String author) {
this.title = title;
this.author = author;
}
public void printBook() {
System.out.println(this.title);
System.out.println(" By " + this.author);
}
19

private String title;


private String author;
}

import java.util.*;
class SortBooks {
public static void main(String[] args) {
ArrayList<Book> bookList = new ArrayList<Book> ();
bookList.add(new Book("Huckleberry Finn", "Mark Twain"));
bookList.add(new Book("Tom Sawyer", "Mark Twain"));
bookList.add(new Book("Catch 22", "Joseph Heller"));
bookList.add(new Book("The Great Gatsby",
"F. Scott Fitzgerald"));
bookList.add(new Book("The Sun Also Rises",
"Ernest Hemingway"));
20

System.out.println("Unsorted Books");
for (int i = 0; i < bookList.size(); i++) {
bookList.get(i).printBook();
}
}
}

Unsorted Books
Huckleberry Finn
By Mark Twain
Tom Sawyer
By Mark Twain
Catch 22
By Joseph Heller
The Great Gatsby
By F. Scott Fitzgerald
The Sun Also Rises
By Ernest Hemingway

21

Lets add the sort


import java.util.*;
class SortBooks {
public static void main(String[] args) {
ArrayList<Book> bookList = new ArrayList<Book> ();
bookList.add(new Book("Huckleberry Finn", "Mark Twain"));
bookList.add(new Book("Tom Sawyer", "Mark Twain"));
bookList.add(new Book("Catch 22", "Joseph Heller"));
bookList.add(new Book("The Great Gatsby",
"F. Scott Fitzgerald"));
bookList.add(new Book("The Sun Also Rises",
"Ernest Hemingway"));
22

System.out.println("Unsorted Books");
for (int i = 0; i < bookList.size(); i++) {
bookList.get(i).printBook();
}
System.out.println("\nSorted ArrayList");
Collections.sort(bookList);
for (int i = 0; i < bookList.size(); i++) {
bookList.get(i).printBook();
}
}
}

$ javac SortBooks.java
SortBooks.java:20: cannot find symbol
symbol : method sort(java.util.ArrayList<Book>)
location: class java.util.Collections
Collections.sort(bookList);
^
1 error

Why does the sort fail?


Of course, what is the object sorting on?

23

Back to Syntax
What does
static <T extends Comparable<? super T>>
void sort(List<T> list)
mean?

24

Generics
Generics introduced with Java SE 5.0. Prior to this
collections could hold anything. Generics impose some
sanity type-checking. Force you to declare collections
of a single type.
Most code involving generics involve collections.

25

The declaration for Array list looks like this


public class ArrayList<E> extends AbstractList<E> implements
List<E> ....
boolean add(E e) and whole bunch of other methods
What the heck is <E>
The <E> syntax tells you that the interface is generic.
<E> just a placeholder for the type you supply. Once
a type is provided, say ArrayList<Book> the types for
AbstractList and List are defined.
26

When you specify the type, the compiler checks to make


sure all types put into the collection are of the same
type.
At compile time, the compiler translate ArrayList<Book>
into the class
public class ArrayList<Book> extends AbstractList<Book>
implements List<Book> ...add(Book e) etc.
Another placeholder <T>
Is <T> different than <E>? Fortunately not. <T> stands
for type and <E> stands for type of the Element the
collection will hold. Both signify generic classes.

Generic Methods
Straight forward variety using the type parameter defined in the class definition
boolean add(E e), the E is replace with what you defined
it to be for the class.
Not so straight forward variety type parameter not
defined in class definition
public <T extends Book> void addPublishers(ArrayList<T>
aList)
This says T is of type Book, and ArrayList<T> is referring
to types of ArrayList<Book>
This has to occur before the return type not after.
27

But, these are different


public <T extends Book> void addPublishers(ArrayList<T>
aList)
and
public void addPublishers(ArrayList<Book> aList)
Suppose you have the following classes
class Paperback extends Book \{...\}
class Hardcover extends Book \{...\}
class CoffeeTable extends Book \{ ... \}
28

Then you could invoke the first method


public <T extends Book> void
addPublishers(ArrayList<T> aList)
by passing
ArrayList<Paperback>
ArrayList<Hardcover>
ArrayList<CoffeeTable>
to the methods.
On the other hand, the second method,
public void addPublishers(ArrayList<Book> aList)
only takes ArrayList<Book> types and none of its subclasses. That is it is not polymorphic.

Why does the second method fail to be polymorphic?


Because you could then write code that inserted objects
that werent of the same type.
Seems reasonable you could pass ArrayList<Paperback>
to the addPublishers() method. After all it takes an
ArrayList<Book> as a parameter and Paberback extends
Book. But if this is allowed then you could write code
like the following:
public void addPublishers(ArrayList<Book> aList) {
aList.add(new CoffeeTable());
}
That is, you could change the type of your ArrayList
at run-time and defeat type-checking by the compiler.
Generics need to be of a single type.
29

Why does the sort fail?


static <T extends Comparable<? super T>>
void sort(List<T> list)
Sort is looking for objects of Type Comparable or its
subclass. (Just ignore <? super T> for the time being.
Comparable is an interface, how does it extend <T>? It
doesnt. In this context extends means implements and
<T extends Comparable> translates into T must be of a
type that implements Comparable.
The interface Comparable has only one method to implement.
30

int compareTo(T o)
Compares this object with the specified object for order.
Compares this object with the specified object for order.
Returns a negative integer, zero, or a positive integer as
this object is less than, equal to, or greater than the
specified object.

To sort then, add Comparable interface to Book


class Book implements Comparable<Book>{
Book (String title, String author) {
this.title = title;
this.author = author;
}
public void printBook() {
System.out.println(this.title);
System.out.println(" By " + this.author);
}
31

//interface method
public int compareTo(Book b) {
//title is a String which has its own compareTo method
return title.compareTo(b.getTitle());
}
public String getTitle() {
return title;
}
private String title;
private String author;
}
32

import java.util.*;
class SortBooks {
public static void main(String[] args) {
ArrayList<Book> bookList = new ArrayList<Book> ();
bookList.add(new Book("Huckleberry Finn", "Mark Twain"));
bookList.add(new Book("Tom Sawyer", "Mark Twain"));
bookList.add(new Book("Catch 22", "Joseph Heller"));
bookList.add(new Book("The Great Gatsby",
"F. Scott Fitzgerald"));
bookList.add(new Book("The Sun Also Rises",
"Ernest Hemingway"));
33

System.out.println("Unsorted Books");
for (int i = 0; i < bookList.size(); i++) {
bookList.get(i).printBook();
}
System.out.println("\nSorted ArrayList");
//Sorts the specified list into ascending order,
//according to the natural ordering of its elements
Collections.sort(bookList);
for (int i = 0; i < bookList.size(); i++) {
bookList.get(i).printBook();
}
}
}

$ java SortBooks
Unsorted Books
Huckleberry Finn
By Mark Twain
Tom Sawyer
By Mark Twain
Catch 22
By Joseph Heller
The Great Gatsby
By F. Scott Fitzgerald
The Sun Also Rises
By Ernest Hemingway

34

Sorted ArrayList
Catch 22
By Joseph Heller
Huckleberry Finn
By Mark Twain
The Great Gatsby
By F. Scott Fitzgerald
The Sun Also Rises
By Ernest Hemingway
Tom Sawyer
By Mark Twain

35

What about if you want to sort on Author, rather than


Title?
One Way
Could set a sort flag and switch on the flag in the
compareTo sort method, but there is an easier way.
Collections interface has an overloaded sort method
public static <T> void
sort(List<T> list, Comparator<? super T> c)
Sorts the specified list according to the order
induced by the specified comparator.
36

Comparator is not the same as a Comparable


Comparable compares the elements of a list to each other
using the compareTo method.
Comparator is an interface so can create lots of classes
that have different comparators. AuthorComparator,
YearComparator, PublisherComparator, etc
Comparator uses the compare method.
No need to implement the interface Comparable if using
Comparators
37

Another advantage of using Comparator over implementing Comparable is if you dont have the source code of
a class.
If you are given a class without source code and it
doesnt include a way to sort its objects, you can create
a Comparator for the class and compare objects.

38

Create separate classes that implement Comparator


import java.util.*;
class TitleCompare implements Comparator<Book> {
public int compare(Book a, Book b) {
return a.getTitle().compareTo(b.getTitle());
}
}

39

and

import java.util.*;
class AuthorCompare implements Comparator<Book> {
public int compare(Book a, Book b) {
return a.getAuthor().compareTo(b.getAuthor());
}
}

40

add getAuthor() method to class Book


class Book {
Book (String title, String author) {
this.title = title;
this.author = author;
}
public void printBook() {
System.out.println(this.title);
System.out.println(" By " + this.author);
}
public String getTitle() {
41

return title;
}
public String getAuthor() {
return author;
}
private String title;
private String author;
}

SortBooks sorts the books based on the comparator


import java.util.*;
class SortBooks {
public static void main(String[] args) {
ArrayList<Book> bookList = new ArrayList<Book> ();
bookList.add(new Book("Huckleberry Finn", "Mark Twain"));
bookList.add(new Book("Tom Sawyer", "Mark Twain"));
bookList.add(new Book("Catch 22", "Joseph Heller"));
bookList.add(new Book("The Great Gatsby",
"F. Scott Fitzgerald"));
bookList.add(new Book("The Sun Also Rises",
42

"Ernest Hemingway"));
System.out.println("Unsorted Books");
for (int i = 0; i < bookList.size(); i++) {
bookList.get(i).printBook();
}
System.out.println("\nSorted By Title ");
TitleCompare titleCompare = new TitleCompare();
Collections.sort(bookList, titleCompare);
for (int i = 0; i < bookList.size(); i++) {
bookList.get(i).printBook();
}
System.out.println("\nSorted By Author");

AuthorCompare authorCompare = new AuthorCompare();


Collections.sort(bookList, authorCompare);
for (int i = 0; i < bookList.size(); i++) {
bookList.get(i).printBook();
}
}
}

$ java SortBooks
Unsorted Books
Huckleberry Finn
By Mark Twain
Tom Sawyer
By Mark Twain
Catch 22
By Joseph Heller
The Great Gatsby
By F. Scott Fitzgerald
The Sun Also Rises
By Ernest Hemingway
43

Sorted By Title
Catch 22
By Joseph Heller
Huckleberry Finn
By Mark Twain
The Great Gatsby
By F. Scott Fitzgerald
The Sun Also Rises
By Ernest Hemingway
Tom Sawyer
By Mark Twain

44

Sorted By Author
The Sun Also Rises
By Ernest Hemingway
The Great Gatsby
By F. Scott Fitzgerald
Catch 22
By Joseph Heller
Huckleberry Finn
By Mark Twain
Tom Sawyer
By Mark Twain

45

Back to Syntax Strangeness


static <T extends Comparable<? super T>>
void sort(List<T> list)
What does the <?

super T> mean?

46

Remember
public void addPublishers(ArrayList<Book> aList)
only takes ArrayList<Book> types and none of its subclasses. That is it is not polymorphic because of the
type-checking safety feature of generics.
You could add elements that arent of the same type.
Compiler wont allow this.

47

Wildcards to the rescue


Wildcards are going to allow you to make
public void addPublishers(ArrayList<Book> aList) polymorphic.
? is the wildcard symbol.
When you use the wildcard in your method arguments,
the compiler knows to prevent you from doing anything
harmful to the type referenced in the argument.
You cant add things to list but polymorphism works
and the type is guarantied.
48

Because of the wildcard, these two statments are now


equivalent
public <T extends Book> void addPublishers(ArrayList<T>
aList)
==
public void addPublishers(ArrayList<?

extends Book> aList)

49

The super T parts mean that the type must be of type


T or one Ts superclasses (i.e its parents).
So now you can read this
static <T extends Comparable<? super T>>
void sort(List<T> list)
<T extends Comparable> The type reference implements
the interface Comparable.
<? super T> Comparable acts on objects of type T or
its superclasses. Comparable can only read these types;
it cant add to the list.
50

(List<T>) List acts on object of type T


For the Book class this becomes
static <Book extends Comparable<Book>>
void sort(List<Book> list)

Inner Classes
To use Comparators you can also create what are called
inner classes.
Inner classes are nested classes, declared inside another
classes braces.
class Foo {
....
class Bar {
void DoSmething() {.... }
}
}
Class Bar is an inner class of Foo
51

Inner classes can use all the variables and methods of


the outer class, even those declared private.
Also, inner classes can have their own variables and
methods
class Foo {
private int z;
class Bar {
void DoSomething() {
//this is Foos z
z = 280;
}
}
52

To call inner classes from the outer class, create an


inner class object and refer to the inner class just as
you do other classes.

class Foo {
private in z;
Bar bar = new Bar();
void doStuff() {
bar.doSomething();
}
53

class Bar {
void DoSomething() {
z = 280;
}
}

Inner classes live inside of the outer class that created


it. Cannot access any class object, only the object that
instantiated it.

Why inner classes?


Can group (helper) classes together.
Encapsulation who need to see your inner class
Can implement different version of an interface inside
the same class.

54

class SortBooks {
public static void main(String[] args) {
ArrayList<Book> bookList = new ArrayList<Book> ();
bookList.add(new Book("Tom Sawyer", "Mark Twain"));
bookList.add(new
bookList.add(new
bookList.add(new
bookList.add(new
bookList.add(new

Book("Huckleberry Finn", "Mark Twain"));


Book("Connecticut Yankee", "Mark Twain"));
Book("Catch 22", "Joseph Heller"));
Book("The Great Gatsby", "F. Scott Fitzger
Book("The Sun Also Rises", "Ernest Hemingw

System.out.println("Unsorted Books");
for (int i = 0; i < bookList.size(); i++) {
55

bookList.get(i).printBook();
}
System.out.println("\nSorted By Author");
AuthorCompare authorCompare = new AuthorCompare();
Collections.sort(bookList, authorCompare);
for (int i = 0; i < bookList.size(); i++) {
bookList.get(i).printBook();
}

System.out.println("\nSorted By Title");
TitleCompare titleCompare = new TitleCompare();
Collections.sort(bookList, titleCompare);

for (int i = 0; i < bookList.size(); i++) {


bookList.get(i).printBook();
}
}
static class AuthorCompare implements Comparator<Book> {
public int compare(Book a, Book b) {
return a.getAuthor().compareTo(b.getAuthor());
}
}
static class TitleCompare implements Comparator<Book> {
public int compare(Book a, Book b) {
return a.getTitle().compareTo(b.getTitle());

}
}
}

Potrebbero piacerti anche