1 1.runtime type identification (rtti) 2.reflection 3.components - beans 4.events 5.properties

44
1 1. Runtime Type Identification (RTTI) 2. Reflection 3. Components - Beans 4. Events 5. Properties

Upload: scot-warner

Post on 20-Jan-2016

223 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

1

1. Runtime Type Identification (RTTI)2. Reflection3. Components - Beans4. Events5. Properties

Page 2: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

2

Object typesEach Object reference has two types :

- static type - known at compile time- compiler enforces static code soundness checks- does not change

- dynamic type (only known at run time – can change)

A a;

for(int i=0;i<5;i++) {

a=(i%2==0) ? new B() : new C();

a.f();

}

Enforced at compile-time

Problem :- specific operation desired depending on run time type- standard solution : use polymorphism- if not possible … -> RTTI needed !

Page 3: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

3

Why RTTI ?

• Special, type dependent operations needed• Only supertype available

public void dynamic(A a) {

a.f(); // always possible

// call g() if B-object

// call h() if C-object

}

Special operator :instanceof <TYPE literal>• Limitation : only NAMED types allowed (no expressions !)• Implicitly used when downcasting• Discovers dynamic type at runtime

public void dynamic(A a) {

a.f(); // always possible

if(a instanceof B) ((B)a).g();

if(a instanceof C) ((C)a).h();

}

NOT allowed :

String s=“B”;

… instanceof s

Page 4: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

4

Example :Count B

class A {}

class B extends A{}

class C extends A{}

class CountingB {

private ArrayList l=new ArrayList();

public void fillList(int n) {

for(int i=0;i<n;i++) {

int r=(int)(Math.random()*3);

if(r==0) l.add(new A());

else if(r==1) l.add(new B()); else l.add(new C());

}

}

public int countB() {

int r=0;

for(int i=0;i<l.size();i++) if((l.get(i)) instanceof B) r++;

return r;

}

public static void main(String[] args) {

CountingB b=new CountingB(); b.fillList(10);

System.out.println("Number of B-objects : "+b.countB());

}

}

Static type : Object

Dynamic type : A, B or C

Page 5: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

5

RTTI mechanicsThe class Class

• runtime info for each class/interface contained in special object (created by JVM)• “special object” of type Class (meta-class)• runtime-type in the Class-object• Class-object stored in “.class”-file • JVM loads object stored in class-file as needed (when first used)

How to get reference to Class-object ?

Class literal : <class_name>.class e.g. A.class

Static Class-method :Class.forName(“class_name”) e.g. Class.forName(“A”)

Object-method : <object_reference>.getClass() e.g. a.getClass()

Runtime type checking

static (named typed only) :

<object_reference> instanceof A

dynamic :

<class_reference>.isInstance(<object_reference>);

Page 6: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

6

Example :Count A, B and C

class A {}

class B extends A{}

class C extends A{}

class Counting {

private ArrayList l=new ArrayList();

public void fillList(int n) {/* as before */ }

public int count(Class c) {

int r=0;

for(int i=0;i<l.size();i++) if(c.isInstance(l.get(i))) r++;

return r;

}

public static void main(String[] args) {

Class[] c={A.class,B.class,C.class};

Counting b=new Counting();

b.fillList(10);

for(int i=0;i<c.length;i++)

System.out.println("Number of objects of type "+c[i]+" : "+b.count(c[i]));

}

}

Number of objects of type class A : 10

Number of objects of type class B : 3

Number of objects of type class C : 4

Page 7: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

7

Checking types

instanceofisInstance

true if type-relation between object and class exists

==equals

(on class objects) true if IDENTICAL Class-objects(no type-relation checking)

interface I {}

class A{}

class B extends A{}

class C extends B implements I {}

//…

A a=new A();

B b=new B();

C c=new C();

instanceof A B C Ia true false false falseb true true false falsec true true true true

.getClass()== A.class B.class C.class I.classa true false false falseb false true false falsec false false true false

Page 8: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

8

More Class methods

• public String getName()• public Package getPackage()• public boolean isInterface()• public boolean isPrimitive()• public boolean isArray()• public Class getSuperClass()• public Class[] getInterfaces()• public boolean isAssignableFrom(Class c)• public int getModifiers()

Page 9: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

9

Using RTTI

• Mostly to cope with 3rd party code (components !)• Design with much RTTI syntax probably flawed ! (redesign)• Sometimes unavoidable

Idiom to check for object equality (for Collections-framework)

class A {// …

public boolean equals(Object o) {if(o instanceof A) {

// safe downcast to class A// check for logical equality and return boolean

} else return false;}

// …}

Page 10: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

10

RTTI vs Reflection

“classical” RTTI

reflection

• Type info known at compile and runtime• discovers type from a known set of types• does type-dependent actions (actions known at compile time)

• Type info only known at runtime• discovers type + type info (e.g. constructors)• does type-dependent actions (actions NOT necessarily known at compile time)• meta-level programming

Motivation for reflection

• write programs to handle unknown types• JVM itself• Rapid Application Development environments• JUnit

• Java serialization mechanism• RMI : discover capabilities of remote objects

Page 11: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

11

Class introspection

public Members only (+superclasses)

use xxxDeclaredXxx to retrieve

all declared Members(no superclass info !)

Page 12: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

12

Type infoimport java.lang.reflect.*;

class TypeInfo {

public static void printInfo(Class cl) {

System.out.println("All public members of "+cl);

Constructor[] c=cl.getConstructors();

Field[] f=cl.getFields();

Method[] m=cl.getMethods();

for(int i=0;i<f.length;i++) System.out.println(f[i]);

for(int i=0;i<c.length;i++) System.out.println(c[i]);

for(int i=0;i<m.length;i++) System.out.println(m[i]);

System.out.println("-----------------------------------------------------------------------------");

}

public static void printDeclaredInfo(Class cl) {

System.out.println("All declared members of "+cl);

// same as above, but with <Declared> in method calls

}

public static void main(String[] args) {

Class cA=null;

try { cA=Class.forName(args[0]);

} catch(ClassNotFoundException e) {

System.err.println("Class not found !");

}

printInfo(cA); printDeclaredInfo(cA);

}

}

Does not contain any info about type to print info on

Page 13: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

13

Type infoAll public members of class A

public int A.a

public A()

public java.lang.String A.toString()

public void A.f()

public void A.fInit(int,int)

public void A.fInit()

public native int java.lang.Object.hashCode()

public final native java.lang.Class java.lang.Object.getClass()

public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException

public final void java.lang.Object.wait() throws java.lang.InterruptedException

public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException

public boolean java.lang.Object.equals(java.lang.Object)

public final native void java.lang.Object.notify()

public final native void java.lang.Object.notifyAll()

-----------------------------------------------------------------------------

All declared members of class A

public int A.a

private int A.b

private A(int,int)

public A()

public java.lang.String A.toString()

public void A.f()

public void A.fInit(int,int)

public void A.fInit()

----------------------------------------------------------------------------

class A{

public int a;

private int b;

public A() {System.out.println("A()"); }

private A(int aa,int bb) {a=aa;b=bb;}

public String toString() {return "A["+a+",+"+b+"]";}

public void f() {System.out.println("f()");}

public void fInit() {a=0;b=0;}

public void fInit(int aa,int bb) {a=aa;b=bb;}

}

java TypeInfo A

Page 14: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

14

Making objectsclass MakeObject {

public static void main(String[] args) {

Class cA=null;

Object[] par={new Integer(5),new Integer(10)};

Class[] param={int.class,int.class};

try {cA=Class.forName(args[0]);

} catch(ClassNotFoundException e) {

System.err.println("Class not found !");

}

Object o1=null,o2=null;

try{

o1=cA.newInstance(); System.out.println(o1);

Constructor c=cA.getDeclaredConstructor(param);

o2=c.newInstance(par); System.out.println(o2);

} catch(Exception e) {System.err.println(e);}

}

}

class A{

public int a;

private int b;

public A() {System.out.println("A()"); }

public A(int aa,int bb) {System.out.println("A(int,int)");a=aa;b=bb;}

public String toString() {return "A["+a+", "+b+"]";}

public void f() {System.out.println("f()");}

public void fInit() {a=0;b=0;}

public void fInit(int aa,int bb) {a=aa;b=bb;}

}

java MakeObject A

A()

A[0,0]

A(int,int)

A[5,10]

Page 15: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

15

Manipulating Fieldsclass ManiField {

public static void main(String[] args) {

Class cA=null;

Object[] par={new Integer(5),new Integer(10)};

Class[] param={int.class,int.class};

try {cA=Class.forName(args[0]);

} catch(ClassNotFoundException e) {

System.err.println("Class not found !");

}

Object o=null;

try{

o=cA.newInstance();

System.out.println(o);

} catch(Exception e) {System.err.println(e);}

Field[] f=cA.getDeclaredFields();

try {

for(int i=0;i<f.length;i++)

if(f[i].getType()==int.class) f[i].setInt(o,100);

} catch(IllegalAccessException e) {

System.err.println(e);

}

System.out.println(o);

}

}

java ManiField A

A()

A[0,0]

java.lang.IllegalAccessException: Class ManiField can not access a member of class A with modifiers "private"

A[100,0]

Page 16: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

16

Invoking Methodsclass ManiField {

public static void main(String[] args) {

Class cA=null;

try {cA=Class.forName(args[0]);

} catch(ClassNotFoundException e) {

System.err.println("Class not found !");

}

Object o=null;

try{

o=cA.newInstance();

System.out.println(o);

} catch(Exception e) {System.err.println(e);}

Method m=null;

try{m=cA.getDeclaredMethod("fInit",param);

} catch(NoSuchMethodException e) {System.err.println(e);}

System.out.println(m);

try{m.invoke(o,par);

} catch(IllegalAccessException e) {System.err.println(e);

} catch(InvocationTargetException e) {System.err.println(e);}

System.out.println(o);

}

}

java Invoke A

A()

A[0,0]

public void A.fInit(int,int)

A[5,10]

Page 17: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

17

A meta-program

Write a method that for a given Class :-constructs an object using the no-arg constructor-invokes arbitrary order all methods on this object

- containing “f” in their name- having an empty parameter list

Page 18: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

18

Introduction

a (often used) definition

purpose • Build applications rapidlycheaplyreliably

reusing (standard) pieces of code• component = building block (cf. Lego-system)

“A software component is a unit of composition with contractually specified interfaces and explicit context dependencies only. A software component can be deployed independently and is subject to composition by third parties.” (Szyperski and Pfister, 1997)

Page 19: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

19

Introduction

examples

characteristics

• application consists of composition of components• component is larger than single class (“unit of deployment)• component conforms to specifications

- interfaces offered- naming conventions

• often : only compiled/binary version available for building applications• delivered by 3rd parties

• shared libraries • Windows DynicamicLinkLibrary (*.DLL)• Unix Dynamic Libraries (*.so)

• OO component technologies• Corba Component Model (CCM)• Java components

• visual programming : JavaBeans• server side component framework : EnterpriseJavaBeans (EJB)

• MS-components (COM, DCOM, OLE, ActiveX)

Page 20: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

20

Visual Programming

• visual programming : draw program (cf. electronic circuit design)- pieces of codes needed from tool palette

- configure code

- wire pieces (interactions)• earlier technologies : Visual Basic, Delphi, LabView• visual programming key to “Rapid Application Development” (RAD)

Application Builder Tool

Component Repository

• component selection• component configuration (properties)• specification of behavior

“Programmer”

Application Code

Page 21: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

21

The beans model

In Java : component is ordinary class following conventions

Exported state : properties

Behavior

Property name : xxxWrite method : setXxx()Read method : getXxx()

alternative for booleans : isXxx()

“ordinary” methods public

event system (for component wiring)

Event name : XxxEvent (extends EventObject)Listener type : XxxListenerRegister listener : addXxxListener(XxxListener)Deregister listener : removeXxxListener(XxxListener)

Page 22: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

22

Inspecting Beans

Application Builder Tool

Bean

intr

osp

ecti

on

BeanInfo

introspectio

n

EventSetDescriptor[] getEventSetDescriptors()

PropertyDescriptor[] getPropertyDescriptors()

MethodDescriptor[] getMethodDescriptors()

Image getIcon(int)

BeanInfo b=null;

try {

b=Introspector.getBeanInfo(aBean);

} catch(IntrospectionException e) {}

• for bean Xxx, XxxBeanInfo is searched• if not available : reflection is used to extract info

Page 23: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

23

Making/using a BeanMaking a Bean

Bean Usage

• create Bean source code (A.java file) in dedicated package (a) (possibly > 1 bean per package)

• provide Bean public properties (according to pattern)• provide Bean public methods• provide Bean event code (source/sink of events)

• compile the Beans codejavac a/A.java

• package the Beans in single jar-archivejar cfm a.jar manifest.tmp a/*.class

• import the Bean in a standard IDE (e.g. NetBeans) or dedicated RAD-environment (e.g. Sun’s Bean Development Kit – BDK)• drop Beans on application form• configure Bean properties• connect Beans through events• generate code/compile/run application

Page 24: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

24

A simple Beanpackage circle;

import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

import java.io.*;

public class Circle extends JPanel implements Serializable, ActionListener {

private ActionListener l;

private int rad=0; private Color col=Color.RED;

public void setRadius(int newRad) {rad=newRad;}

public int getRadius() {return rad;}

public void setColor(Color c) {col=c;}

public Color getColor() {return col;}

public void paintComponent(Graphics g) {

super.paintComponent(g);

g.setColor(col); g.fillOval(0,0,rad,rad);

}

public void actionPerformed(ActionEvent e) {

col = (col==Color.RED) ? Color.GREEN : Color.RED;

repaint(0,0,rad,rad);

notifyListeners();

}

public void addActionListener(ActionListener ll) {l=ll;}

public void removeActionListener(ActionListener ll) {if(l==ll) l=null;}

public void notifyListeners() {if(l!=null) l.actionPerformed(new ActionEvent(this,0,""));}

}

• properties : color, radius• public methods :

• setRadius / getRadius• setColor / getColor• paintComponent• actionPerformed• addActionListener/removeActionListener• notifyListeners

• event handling• sink for ActionEvent• source of ActionEvent

Page 25: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

25

Retrieving Bean informationpublic class Info {

public static void main(String[] args) {

BeanInfo b=null;

Class info=null,stop=null;

try {info=Class.forName(args[0]);stop=Class.forName(args[1]);} catch(Exception e) { }

try { b=Introspector.getBeanInfo(info,stop);

} catch(IntrospectionException e) {}

PropertyDescriptor[] p=b.getPropertyDescriptors();

MethodDescriptor[] m=b.getMethodDescriptors();

EventSetDescriptor[] e=b.getEventSetDescriptors();

System.out.println("Properties :"); for(int i=0;i<p.length;i++) {

System.out.println("Property name : "+p[i].getName());

System.out.println("\tType : "+p[i].getPropertyType());

System.out.println("\tReadMethod : "+p[i].getReadMethod());

System.out.println("\tWriteMethod : "+p[i].getWriteMethod());

}

System.out.println("Methods :"); for(int i=0;i<m.length;i++) { System.out.println("Method : "+m[i].getMethod()); }

System.out.println("Events :"); for(int i=0;i<e.length;i++) {

System.out.println("Event listener type "+e[i].getListenerType());

Method[] lm=e[i].getListenerMethods();

for(int j=0;j<lm.length;j++) System.out.println("\tListener method : "+lm[j]);

System.out.println("\tAdd listener method : "+e[i].getAddListenerMethod());

System.out.println("\tRemove listener method :"+e[i].getRemoveListenerMethod());

}

}

}

Page 26: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

26

Retrieving Bean informationjava Info circle.Circle javax.swing.JPanel

Properties :

Property name : color

Type : class java.awt.Color

ReadMethod : public java.awt.Color circle.Circle.getColor()

WriteMethod : public void circle.Circle.setColor(java.awt.Color)

Property name : radius

Type : int

ReadMethod : public int circle.Circle.getRadius()

WriteMethod : public void circle.Circle.setRadius(int)

Methods :

Method : public void circle.Circle.actionPerformed(java.awt.event.ActionEvent)

Method : public void circle.Circle.addActionListener(java.awt.event.ActionListener)

Method : public java.awt.Color circle.Circle.getColor()

Method : public int circle.Circle.getRadius()

Method : public void circle.Circle.notifyListeners()

Method : public void circle.Circle.paintComponent(java.awt.Graphics)

Method : public void circle.Circle.removeActionListener(java.awt.event.ActionListener)

Method : public void circle.Circle.setColor(java.awt.Color)

Method : public void circle.Circle.setRadius(int)

Events :

Event listener type interface java.awt.event.ActionListener

Listener method : public abstract void java.awt.event.ActionListener.actionPerformed(java.awt.event.ActionEvent)

Add listener method : public void circle.Circle.addActionListener(java.awt.event.ActionListener)

Remove listener method :public void circle.Circle.removeActionListener(java.awt.event.ActionListener)

Page 27: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

27

Jarring the Beans

jar utility • group java files in one archive• originally meant to reduce complexity of Applet download• contains meta-information (manifest file)• MUST be added to CLASSPATH variable !

mostly used options c create new archive

t create table of contents

x extract from archive

f specify archive file name

m specify base manifest file

e.g. jar tf circle.jarjar cfm circle.jar manifest.tmp circle/*.class

Beans manifest file Manifest-Version: 1.0

Name: circle/Circle.class

Java-Bean: True

Empty line

Manifest file In directory containing circle

Invoke jar from this directory

Page 28: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

28

Events and Listeners

Event Source object

Event Listenerobject

RegisterDeregister

Event notification

Event

Page 29: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

29

Events and ListenersOwn event type and listener interface

public interface ColorListener extends java.util.EventListener {

public void colorChanged(ColorEvent e);

}

ColorListener.java

public class ColorEvent extends java.util.EventObject {

private Color c;

public ColorEvent(Object o,Color cc) {super(o);c=cc;}

public Color getColor() {return c;}

}

ColorEvent.java

Page 30: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

30

Events and Listenerspublic class Circle extends JPanel implements Serializable, ActionListener {

private ColorListener l;

private int rad=0;

private Color col=Color.RED;

public void setRadius(int newRad) {rad=newRad;}

public int getRadius() {return rad;}

public void setColor(Color c) {col=c;}

public Color getColor() {return col;}

public void paintComponent(Graphics g) {/* as before */}

public void actionPerformed(ActionEvent e) {/* as before */}

public void addColorListener(ColorListener ll) {l=ll;}

public void removeColorListener(ColorListener ll) {if(l==ll) l=null;}

public void notifyListeners() {

if(l!=null) l.colorChanged(new ColorEvent(this,col));

}

}

Circle.java

java Info circle.Circle javax.swing.JPanel…

Events :

Event listener type interface circle.ColorListener

Listener method : public abstract void circle.ColorListener.colorChanged(circle.ColorEvent)

Add listener method : public void circle.Circle.addColorListener(circle.ColorListener)

Remove listener method :public void circle.Circle.removeColorListener(circle.ColorListener)

Page 31: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

31

Unicast Eventsunicast events : one listener only !throw TooManyListenersException if attempt to register > 1 listener !

public void add<ListenerType> (<ListenerType> l) throws java.util.TooManyListenersException;

public void remove<ListenerType>(<ListenerType> l);

public class TheBean {

MyEventListener l=null;

// …

public void addMyEventListener(MyEventListener ll) throws java.util.TooManyListenersException {

if(l==null) l=ll;

else throw new java.util.TooManyListenersException();

}

public void removeMyEventListener(MyEventListener ll) {

if(l==ll) l=null;

}

}

Page 32: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

32

Unicast Events

public class Circle extends JPanel implements Serializable, ActionListener {

private ColorListener l;

private int rad=0;

private Color col=Color.RED;

public void setRadius(int newRad) {rad=newRad;}

public int getRadius() {return rad;}

public void setColor(Color c) {col=c;}

public Color getColor() {return col;}

public void paintComponent(Graphics g) {/* as before */}

public void actionPerformed(ActionEvent e) {/* as before */}

public void addColorListener(ColorListener ll) throws java.util.TooManyListenersException {

if(l==null) l=ll;

else throw new java.util.TooManyListenersException();

}

public void removeColorListener(ColorListener ll) {if(l==ll) l=null;}

public void notifyListeners() {

if(l!=null) l.colorChanged(new ColorEvent(this,col));

}

}

Page 33: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

33

Multicast Eventsmulticast events : possibly many listeners !

public void add<ListenerType> (<ListenerType> l);

public void remove<ListenerType>(<ListenerType> l);

Issues with multithreading

• listeners get notified on caller’s thread• event handler possibly/often done in separate thread• problems :

• call back to event source object from different thread• list of listeners can get modified during event notification

Programming guidelines

• DO NOT invoke listener method from synchronized block (deadlock danger !)• make copy of list of listeners BEFORE notification• by default, make all public bean methods SYNCHRONIZED

Page 34: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

34

Multicast Eventspublic class TheBean {

private ArrayList listeners = new ArrayList();

// …

public synchronized void f() {

// …

}

public void addMyEventListener(MyEventListener ll) {

if(!(listeners.contains(ll)) listeners.add(ll);

}

public void removeMyEventListener(MyEventListener ll) {

if(listeners.contains(ll)) listeners.remove(ll);

}

public void notifyListeners() {

MyEvent evt=new MyEvent(this);

ArrayList l;

synchronized(this) {

l=(ArrayList) listeners.clone();

}

for(int i=0,s=l.size();i<s;i++) {

MyEventListener c=(MyEventListener)(l.get(i));

c.listenToMyEvent(evt);

}

}

}

Page 35: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

35

Multicast Eventspublic class Circle extends JPanel implements Serializable, ActionListener {

private ArrayList listeners=new ArrayList();

private int rad=0;

private Color col=Color.RED;

public synchronized void setRadius(int newRad) {rad=newRad;}

public synchronized int getRadius() {return rad;}

public synchronized void setColor(Color c) {col=c;}

public synchronized Color getColor() {return col;}

public synchronized void paintComponent(Graphics g) {/* as before */}

public synchronized void actionPerformed(ActionEvent e) {/* as before */}

public void addColorListener(ColorListener ll) { if(!(listeners.contains(ll))) listeners.add(ll);}

public void removeColorListener(ColorListener ll) { if(listeners.contains(ll)) listeners.remove(ll);}

public void notifyListeners() {

ColorEvent evt=new ColorEvent(this,col);

ArrayList l;

synchronized(this) {

l=(ArrayList) listeners.clone();

}

for(int i=0,s=l.size();i<s;i++) {

ColorListener c=(ColorListener)(l.get(i));

c.colorChanged(evt);

}

}

}

Page 36: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

36

Properties and Indexed Properties

public void set<PropertyName> (<PropertyType> value);

public <PropertyType> get<PropertyName>();

public boolean is<PropertyName>();

public class TheBean {

private MyType obj;

private int anInt;

private boolean bool;

public synchronized void setObject(MyType m) {obj=m;}

public synchronized MyType getObject() {return obj;}

public synchronized void setInt(int a) {anInt=a;}

public synchronized int getInt() {return anInt;}

public synchronized void setB(boolean b) {bool=b;}

public synchronized boolean isB() {return bool;}

// …

}PropertyName :• object• int• b

Page 37: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

37

Properties and Indexed Properties

public void set<PropertyName> (<PropertyType>[ ] value);

public <PropertyType>[ ] get<PropertyName>();

public void set<PropertyName> (int index, <PropertyType> value);

public <PropertyType> get<PropertyName>(int index);

public class TheBean {

private int[] a;

private ArrayList l;

public synchronized void setA(int index,int val) {a[index]=val;}

public synchronized int getA(int index) {return a[index];}

public synchronized void setMyString(int index,String v) {l.set(index,o);}

public synchronized String getMyString(int index) {return (String)(l.get(index));}

// …

}

PropertyName :• a• myString

Page 38: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

38

Notifying ChangesBound Properties

Provide a mechanism to notify changes of property values

• Event type : PropertyChangeEvent• Listener interface : PropertyChangeListener• Listener method :

public void propertyChange(PropertyChangeEvent e)

Page 39: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

39

Notifying ChangesBound Properties

Non-specific property binding

Specific property binding

public void addPropertyChangeListener (PropertyChangeListener l);

public void removePropertyChangeListener (PropertyChangeListener l);

public void add<PropertyName>Listener (PropertyChangeListener l);

public void remove<PropertyName>Listener (PropertyChangeListener l);

public class TheBean {

private ArrayList changeA=new ArrayList();

private ArrayList change=new ArrayList();

public int a=0,b=0;

public void addPropertyChangeListener (PropertyChangeListener l) {change.add(l);}

public void addAListener(PropertyChangeListener l) {changeA.add(l);}

// …

}

Fire ChangeEvents AFTER values are updated !

Page 40: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

40

Support for Property Changes

• inherit from PropertyChangeSupport• use instance of PropertyChangeSupport

Page 41: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

41

Vetoing ChangesConstrained Properties

Provide a mechanism to prevent changes in other Beans

Non-specific property binding

Specific property binding

public void addVetoalbeChangeListener (VetoableChangeListener l);

public void removeVetoableChangeListener (VetoableChangeListener l);

public void add<PropertyName>Listener (VetoableChangeListener l);

public void remove<PropertyName>Listener (VetoableChangeListener l);

Getting/setting

public void set<PropertyName> (<PropertyType> value)

throws PropertyVetoException;

public <PropertyType> get(<PropertyName>);

Page 42: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

42

Reaching agreement

setProperty(newValue)• bean does own validity checking : if not valid throw PropertyVetoException• notify all VetoableChangeListeners of attempt to change to new value• if PropertyVetoException is thrown :

• notify all registered VetoableChangeListeners with old value• event source is allowed to IGNORE second round PropertyVetoExceptions

• if no PropertyVetoException is thrown :• update the value• notify all registered PropertyChangeListeners with new value

• Event type : PropertyChangeEvent• Listener interface : VetoableChangeListener• Listener method :

public void vetoableChange(PropertyChangeEvent e) throws PropertyVetoException

Page 43: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

43

Reaching agreementpublic class TheBean {

private int a=0;

private ArrayList change=new ArrayList(),veto=new ArrayList();

public void addPropertyChangeListener(PropertyChangeListener l) {change.add(l);}

public void addVetoableChangeListener(VetoableChangeListener l) {veto.add(l);}

public void setA(int n) throws PropertyVetoException {

if(!(isValidValue(n)) throw new PropertyVetoException(this);

try {

fireVetoableChangeListeners(n);

} catch(PropertyVetoException e) {

try {

fireVetoableChangeListeners(a);

} catch(PropertyVetoException ee) {} // ignore

throw e; // rethrow

}

a=n; // update

firePropertyChangeListeners(n);

}

}

Page 44: 1 1.Runtime Type Identification (RTTI) 2.Reflection 3.Components - Beans 4.Events 5.Properties

44

Support for Vetoable Changes

• inherit from VetoableChangeSupport• use instance of VetoableChangeSupport• fireVetoableChange

• throws PropertyVetoException• notifies in 2 rounds :

• 1st round : new value• if exceptions : 2nd round : old value• rethrows exception if raised