Reflection

Klasa Class

import java.lang.reflect.*; public class class_existence_check { public static void main(String argv[]) { String class_name = argv[0]; Class c; try { c = Class.forName(class_name); } catch(Throwable e) { System.out.println(class_name + " not found"); return; } System.out.println(class_name + " exists"); } }

$ java class_existence_check java.lang.Widget java.lang.Widget not found $ java class_existence_check java.lang.String java.lang.String exists $ java class_existence_check String String not found

Hierarchia

import java.lang.reflect.*; public class class_hierarchy { static void print_hierarchy(Class c, String indent) { System.out.println(indent + c); Class superclass = c.getSuperclass(); Class[] ifaces = c.getInterfaces(); for (int i = 0; i < ifaces.length; i++) print_hierarchy(ifaces[i], indent + "| "); if(superclass != null) print_hierarchy(superclass, indent + "> "); } public static void main(String argv[]) { String class_name = argv[0]; Class c; try { c = Class.forName(class_name); } catch(Throwable e) { System.out.println(class_name + " not found"); return; } print_hierarchy(c, ""); } }

$ java class_hierarchy java.lang.String class java.lang.String | interface java.io.Serializable | interface java.lang.Comparable | interface java.lang.CharSequence > class java.lang.Object

$ java class_hierarchy java.awt.PopupMenu class java.awt.PopupMenu > class java.awt.Menu > | interface java.awt.MenuContainer > | interface javax.accessibility.Accessible > > class java.awt.MenuItem > > | interface javax.accessibility.Accessible > > > class java.awt.MenuComponent > > > | interface java.io.Serializable > > > > class java.lang.Object

Metody

import java.lang.reflect.*; public class class_list_methods { public static void main(String argv[]) { String class_name = argv[0]; Class c; try { c = Class.forName(class_name); } catch(Throwable e) { System.out.println(class_name + " not found"); return; } System.out.println("Methods of " + class_name + ":"); Method m[] = c.getDeclaredMethods(); for (int i = 0; i < m.length; i++) System.out.println(m[i].toString()); } }

$ java class_list_methods java.lang.String Methods of java.lang.String: public int java.lang.String.hashCode() public int java.lang.String.compareTo(java.lang.Object) public int java.lang.String.compareTo(java.lang.String) public boolean java.lang.String.equals(java.lang.Object) public java.lang.String java.lang.String.toString() public char java.lang.String.charAt(int) private static void java.lang.String.checkBounds(byte[],int,int) public int java.lang.String.compareToIgnoreCase(java.lang.String) public java.lang.String java.lang.String.concat(java.lang.String) public boolean java.lang.String.contentEquals(java.lang.StringBuffer) public static java.lang.String java.lang.String.copyValueOf(char[]) public static java.lang.String java.lang.String.copyValueOf(char[],int,int) public boolean java.lang.String.endsWith(java.lang.String) public boolean java.lang.String.equalsIgnoreCase(java.lang.String) public byte[] java.lang.String.getBytes() public void java.lang.String.getBytes(int,int,byte[],int) public byte[] java.lang.String.getBytes(java.lang.String) throws java.io.UnsupportedEncodingException public void java.lang.String.getChars(int,int,char[],int) public int java.lang.String.indexOf(int) public int java.lang.String.indexOf(int,int) static int java.lang.String.indexOf(char[],int,int,char[],int,int,int) public int java.lang.String.indexOf(java.lang.String) public int java.lang.String.indexOf(java.lang.String,int) public native java.lang.String java.lang.String.intern() public int java.lang.String.lastIndexOf(int) public int java.lang.String.lastIndexOf(int,int) static int java.lang.String.lastIndexOf(char[],int,int,char[],int,int,int) public int java.lang.String.lastIndexOf(java.lang.String) public int java.lang.String.lastIndexOf(java.lang.String,int) public int java.lang.String.length() public boolean java.lang.String.matches(java.lang.String) public boolean java.lang.String.regionMatches(int,java.lang.String,int,int) public boolean java.lang.String.regionMatches(boolean,int,java.lang.String,int,int) public java.lang.String java.lang.String.replace(char,char) public java.lang.String java.lang.String.replaceAll(java.lang.String,java.lang.String) public java.lang.String java.lang.String.replaceFirst(java.lang.String,java.lang.String) public java.lang.String[] java.lang.String.split(java.lang.String) public java.lang.String[] java.lang.String.split(java.lang.String,int) public boolean java.lang.String.startsWith(java.lang.String) public boolean java.lang.String.startsWith(java.lang.String,int) public java.lang.CharSequence java.lang.String.subSequence(int,int) public java.lang.String java.lang.String.substring(int) public java.lang.String java.lang.String.substring(int,int) public char[] java.lang.String.toCharArray() public java.lang.String java.lang.String.toLowerCase() public java.lang.String java.lang.String.toLowerCase(java.util.Locale) public java.lang.String java.lang.String.toUpperCase() public java.lang.String java.lang.String.toUpperCase(java.util.Locale) public java.lang.String java.lang.String.trim() public static java.lang.String java.lang.String.valueOf(char) public static java.lang.String java.lang.String.valueOf(double) public static java.lang.String java.lang.String.valueOf(float) public static java.lang.String java.lang.String.valueOf(int) public static java.lang.String java.lang.String.valueOf(long) public static java.lang.String java.lang.String.valueOf(boolean) public static java.lang.String java.lang.String.valueOf(char[]) public static java.lang.String java.lang.String.valueOf(char[],int,int) public static java.lang.String java.lang.String.valueOf(java.lang.Object)

$ java class_list_methods java.awt.Button Methods of java.awt.Button: static java.lang.Class java.awt.Button.class$(java.lang.String) private void java.awt.Button.writeObject(java.io.ObjectOutputStream) throws java.io.IOException private void java.awt.Button.readObject(java.io.ObjectInputStream) throws java.lang.ClassNotFoundException,java.io.IOException,java.awt.HeadlessException private static native void java.awt.Button.initIDs() public synchronized void java.awt.Button.addActionListener(java.awt.event.ActionListener) public void java.awt.Button.addNotify() java.lang.String java.awt.Button.constructComponentName() boolean java.awt.Button.eventEnabled(java.awt.AWTEvent) public javax.accessibility.AccessibleContext java.awt.Button.getAccessibleContext() public java.lang.String java.awt.Button.getActionCommand() public synchronized java.awt.event.ActionListener[] java.awt.Button.getActionListeners() public java.lang.String java.awt.Button.getLabel() public java.util.EventListener[] java.awt.Button.getListeners(java.lang.Class) protected java.lang.String java.awt.Button.paramString() protected void java.awt.Button.processActionEvent(java.awt.event.ActionEvent) protected void java.awt.Button.processEvent(java.awt.AWTEvent) public synchronized void java.awt.Button.removeActionListener(java.awt.event.ActionListener) public void java.awt.Button.setActionCommand(java.lang.String) public void java.awt.Button.setLabel(java.lang.String)

Rails

package www_blog_pl; public class Uid { public int id; public String name; public Uid(String id) { String sql = "SELECT id,name FROM users WHERE id=" + id; // Temporary solution this.id = Integer.parseInt(id); if(this.id == 1) { name = "jasiu"; } else if(this.id == 2) { name = "kasia"; } else { this.id = 0; name = "unknown"; } } };

Wersja wyidealizowana

package www_blog_pl; public class www { public static String main(Uid viewer) { return "

Welcome to the blog server, " + viewer.name; } public static String index() { return main(new Uid("0")); } public static String person(Uid target) { return "<p>This is " + target.name + "'s blog"; } public static String view_comment(Uid target, int thread_nr, int comment_nr) { String comment = "This is " + comment_nr + "th comment in " + target.name + "'s blog"; return comment; } public static String post_comment(Uid viewer, Uid target, int thread_nr) { return "<p>Please write the comment below<br><form><input type='submit'>"; } public static String post_comment_2(Uid viewer, Uid target, int thread_nr, String comment) { String sql = "INSERT INTO comments VALUES (" + target.id + "," + thread_nr + ",'" + comment + "')"; // add new comment to the data base return "<p>Thank you, " + viewer.name + ", for your input\n"; } };

Wersja rzeczywista

package www_blog_pl; public class www { public static String[] main_paramnames() { String[] x={"viewer"}; return x; }; public static String main(Uid viewer) { return "<p>Welcome to the blog server, " + viewer.name; } public static String[] index_paramnames() { String[] x={}; return x; }; public static String index() { return main(new Uid("0")); } public static String[] person_paramnames() { String[] x={"target"}; return x; }; public static String person(Uid target) { return "<p>This is " + target.name + "'s blog"; } public static String[] view_comment_paramnames() { String[] x={"target", "thread_nr", "comment_nr"}; return x; }; public static String view_comment(Uid target, int thread_nr, int comment_nr) { String comment = "This is " + comment_nr + "th comment in " + target.name + "'s blog"; return comment; } public static String[] post_comment_paramnames() { String[] x={"viewer", "target", "thread_nr"}; return x; }; public static String post_comment(Uid viewer, Uid target, int thread_nr) { return "<p>Please write the comment below<br><form><input type='submit'>"; } public static String[] post_comment_2_paramnames() { String[] x={"viewer", "target", "thread_nr", "comment"}; return x; }; public static String post_comment_2(Uid viewer, Uid target, int thread_nr, String comment) { String sql = "INSERT INTO comments VALUES (" + target.id + "," + thread_nr + ",'" + comment + "')"; // add new comment to the data base return "<p>Thank you, " + viewer.name + ", for your input\n"; } };

Rail engine

import java.lang.reflect.*; import java.util.*; public class rails { static void call(Class c, Method m, Hashtable args) throws java.lang.Exception { Class param_types[] = m.getParameterTypes(); // Shouldn't be necessary Class gpn_a[] = {}; Object gpn_aa[] = {}; Method gpn = c.getMethod(m.getName() + "_paramnames", gpn_a); String param_names[] = (String[])gpn.invoke(null, gpn_aa); if(param_names.length != param_types.length) throw new Exception("Bad param info"); Object a[] = new Object[param_types.length]; for(int i=0; i<param_types.length; i++) { String arg = (String)args.get(param_names[i]); Class typ = param_types[i]; Object o; // Conversions if(typ == java.lang.String.class) o = arg; else if(typ == int.class) o = new Integer(arg); else { Class str_a[] = {java.lang.String.class}; Constructor cstr = typ.getConstructor(str_a); Object str_aa[] = {arg}; o = cstr.newInstance(str_aa); } a[i] = o; } // null obj, static methods only String s = (String)m.invoke(null, a); System.out.println(s); } public static void main(String argv[]) { String class_name = argv[0]; Class c; try { c = Class.forName(class_name); } catch(Throwable e) { System.out.println("<p>Error, wrong request"); return; } Hashtable args = new Hashtable(); // Hashtable<String,String> args.put("action", "index"); // default action for(int i=1; i<argv.length; i++) { String arg = argv[i]; int j = arg.indexOf('='); String key; String value; if(j != -1) { key = arg.substring(0, j); value = arg.substring(j+1, arg.length()); } else { key = arg; value = "true"; } args.put(key, value); } String action = (String)args.get("action"); Method m[] = c.getDeclaredMethods(); for (int i = 0; i < m.length; i++) { if(m[i].getName().equals(action)) { try { call(c, m[i], args); } catch (Throwable e) { System.out.println("<p>Error, wrong request"); e.printStackTrace(); } return; } } System.out.println("<p>Error, unknown action " + action); } }

java.beans

public class Hello_bean implements java.io.Serializable { protected String world; public Hello_bean() { world = "world"; } public void hello() { System.out.println("Hello, " + world); } public void setWorld(String newWorld) { world = newWorld; } public String getWorld() { return world; } }

Event model

import java.beans.*; public class Account implements java.io.Serializable { VetoableChangeSupport ctrls = new VetoableChangeSupport(this); public synchronized void addVetoableChangeListener(VetoableChangeListener l) { ctrls.addVetoableChangeListener(l); } public synchronized void removeVetoableChangeListener(VetoableChangeListener l) { ctrls.removeVetoableChangeListener(l); } float balance = 100.0f; public float getBalance() { return balance; } public void setBalance(float newBalance) { try { ctrls.fireVetoableChange("balance", new Float(balance), new Float(newBalance)); balance = newBalance; } catch (PropertyVetoException e) { System.out.println("The change has been vetoed: " + e.getMessage()); } } }

class AccountUser implements Runnable { Account account; AccountUser(Account account) { this.account = account; Thread thr = new Thread(this); thr.start(); } public void run() { try { while (true) { // Spend 80% of time, save 20% of time if(Math.random() > 0.8) account.setBalance(account.getBalance() + 100.0f*(float)Math.random()); else account.setBalance(account.getBalance() - 100.0f*(float)Math.random()); Thread.sleep(500); } } catch (Exception e) { e.printStackTrace(); } } }

import java.beans.*; class AccountController implements VetoableChangeListener { public void vetoableChange(PropertyChangeEvent evt) throws PropertyVetoException { float new_balance = ((Float)evt.getNewValue()).floatValue(); if (new_balance < 0.0f) { throw(new PropertyVetoException("balance must be non-negative and " + new_balance + " is not", evt)); } else { System.out.println(evt.getPropertyName() + " changed to " + new_balance); } } }

class Bank { public static void main(String args[]) { Account account = new Account(); AccountUser account_user = new AccountUser(account); AccountController account_controller = new AccountController(); account.addVetoableChangeListener(account_controller); } }

$ java Bank balance changed to 62.42096 balance changed to 33.49341 balance changed to 33.49341 The change has been vetoed: balance must be non-negative and -41.56317 is not balance changed to 33.49341 The change has been vetoed: balance must be non-negative and -54.31034 is not balance changed to 117.22432 balance changed to 30.141861 balance changed to 11.38781 balance changed to 56.782356 balance changed to 56.782356 The change has been vetoed: balance must be non-negative and -23.382767 is not balance changed to 29.687029 balance changed to 29.687029 The change has been vetoed: balance must be non-negative and -41.377907 is not