[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
RE: accumulator generator (Java)
Another (less elegant) way in Java would be to have each invocation of foo(n)
return a Method that takes an argument 'i' and accumulates this value with n.
We need to reload the returned Method's class (named Inc) at each invocation.
To emulate closure-like behavior for every invocation of 'foo' a new definition
of class Inc is reloaded, an instance is created, so the Method returned will
delegate to that instance. The following horrid code demonstrates...
import java.io.*;
import java.lang.reflect.*;
public class Accumulator {
public static void main(String[] args) throws Exception {
Method[] ms = new Method[3];
for (int i = 0; i < ms.length; i++) {
ms[i] = foo(i);
}
for (int i = 0; i < ms.length; i++) {
for (int j = 0; j < 3; j++) {
System.out.println(i + "," + j + ": " +
ms[i].invoke(null, new Object[]{new Integer(j)}));
}
}
}
static class Inc {
public int n;
public static Inc instance;
public Inc(int n) { this.n = n; }
private int inc(int i) { return n += i; }
public static int foo(int i) { return instance.inc(i); }
}
static Method foo(int n) throws Exception {
// Load the new class
Class incClass = new ClassLoader(null) {
final static byte[] bytes = {
-54,-2,-70,-66,0,3,0,45,0,31,7,0,2,1,0,15,65,99,99,117,
109,117,108,97,116,111,114,36,73,110,99,7,0,4,1,0,16,106,97,118,
97,47,108,97,110,103,47,79,98,106,101,99,116,1,0,8,105,110,115,116,
97,110,99,101,1,0,17,76,65,99,99,117,109,117,108,97,116,111,114,36,
73,110,99,59,1,0,1,110,1,0,1,73,1,0,3,105,110,99,1,0,
4,40,73,41,73,1,0,4,67,111,100,101,1,0,15,76,105,110,101,78,
117,109,98,101,114,84,97,98,108,101,12,0,7,0,8,9,0,1,0,13,
1,0,3,102,111,111,12,0,5,0,6,9,0,1,0,16,12,0,9,0,
10,10,0,1,0,18,1,0,6,60,105,110,105,116,62,1,0,4,40,73,
41,86,12,0,20,0,23,1,0,3,40,41,86,10,0,3,0,22,1,0,
10,83,111,117,114,99,101,70,105,108,101,1,0,16,65,99,99,117,109,117,
108,97,116,111,114,46,106,97,118,97,1,0,12,73,110,110,101,114,67,108,
97,115,115,101,115,7,0,29,1,0,11,65,99,99,117,109,117,108,97,116,
111,114,1,0,3,73,110,99,0,32,0,1,0,3,0,0,0,2,0,9,
0,5,0,6,0,0,0,1,0,7,0,8,0,0,0,3,0,18,0,9,
0,10,0,1,0,11,0,0,0,36,0,3,0,2,0,0,0,12,42,89,
-76,0,14,27,96,90,-75,0,14,-84,0,0,0,1,0,12,0,0,0,6,
0,1,0,0,0,28,0,9,0,15,0,10,0,1,0,11,0,0,0,32,
0,2,0,1,0,0,0,8,-78,0,17,26,-73,0,19,-84,0,0,0,1,
0,12,0,0,0,6,0,1,0,0,0,29,0,1,0,20,0,21,0,1,
0,11,0,0,0,42,0,2,0,2,0,0,0,10,42,-73,0,24,42,27,
-75,0,14,-79,0,0,0,1,0,12,0,0,0,14,0,3,0,0,0,27,
0,4,0,27,0,9,0,27,0,2,0,25,0,0,0,2,0,26,0,27,
0,0,0,10,0,1,0,1,0,28,0,30,0,8,
};
protected Class findClass(String name) throws ClassNotFoundException {
return super.defineClass(name, bytes, 0, bytes.length);
}
}.loadClass("Accumulator$Inc");
// Set Inc's n value
Constructor ctor = incClass.getConstructor(new Class[]{int.class});
ctor.setAccessible(true);
Object instance = ctor.newInstance(new Object[]{new Integer(n)});
Field f = incClass.getField("instance");
f.setAccessible(true);
f.set(null, instance);
// Get the new method
Method method = incClass.getMethod("foo", new Class[]{int.class});
method.setAccessible(true);
return method;
}
}
... and outputs
0,0: 0
0,1: 1
0,2: 3
1,0: 1
1,1: 2
1,2: 4
2,0: 2
2,1: 3
2,2: 5
showing that each method returned from 'foo' is, in fact, unique.
Jeff
---
Jeffrey Palm --> http://www.cs.colorado.edu/~jdp