Anonymous class - I don't know how to...

K

kaja_love160

hello

1) Syntax for creating anonymous class:

new < superclass> ( <params> ) { <class definition> };


Example:

Object o = new Object() { public int anon = 20; };


The above statement creates an object of anonymous class and returns
a reference to it. But in order to use members declared in anonymous
class ( o.anon ), variable o would have to be of same type as
anonymous class. How do we make 'o' of same type, considering that
anonymous class has no name?




2)
If we declare class C inside method A(), then any local variable
( declared inside A() ) that will also be used inside class C, must be
declared final. Why? I assume there must be some valid reason for
that?


public void A ( final int i ) {

class C {
int u = i ;
}
}


thank you for your help
 
A

Andreas Leitgeb

hello
1) Syntax for creating anonymous class:
new < superclass> ( <params> ) { <class definition> };
Example:
Object o = new Object() { public int anon = 20; };

The above statement creates an object of anonymous class and returns
a reference to it. But in order to use members declared in anonymous
class ( o.anon ), ...

.... you'd not only define the variable, but also overwrite
a (non-final, of course) method from the base-class, which then
accesses the variable.

e.g.
Object o = new Object() {
public int anon = 20;
// doesn't make much sense except for the sake of an example:
public String toString() { anon++; return Integer.toString(anon); }
}
o.toString(); // -> 21
o.toString(); // -> 22

Alternatively, you can also use the reflection-API to
see and access the variable "anon" of the object referenced by "o".
2)
If we declare class C inside method A(), then any local variable
( declared inside A() ) that will also be used inside class C, must be
declared final. Why? I assume there must be some valid reason for
that?
public void A ( final int i ) {
class C { int u = i ; }
}

The reasons are perhaps more technical than anything else.
At class-file level, C is in a separate class-file than the
class containing A, and it would be quite complicated to implement
a connection between C's "i", and the local variable "i" in A.
The same restriction holds currently, if "i" were a field of the
class that contains "A", and my feeling is, that this case is
slightly more likely to change in future than the case of a local
variable.

In a nutshell, I consider it a current limitation of implementation
that was then taken into java language spec for practical reasons.
I wouldn't bet that this requirement will be there into all eternity.
At some point in future, some brilliant programmer might find a way
to actually implement a live connection between these vars, despite
the current fundamental difference between local variables and class
variables, and the requirement for "final" might then be dropped.

PS: I'm sure, some will followup with their personal decision, that
they indeed would bet on this limitation never ever changing, and
I wouldn't bet against them, either. I'm not really the betting
type :)
 
M

Mark Space

Example:

Object o = new Object() { public int anon = 20; };


The above statement creates an object of anonymous class and returns
a reference to it. But in order to use members declared in anonymous
class ( o.anon ), variable o would have to be of same type as
anonymous class. How do we make 'o' of same type, considering that
anonymous class has no name?

To re-enforce what Andreas said, this is a design issue, not a language
issue. You must design your super-class so that you can access
variables or other information from the anonymous class.

If you absolutely cannot, then here's the reflection example:

package anontest;
import java.lang.reflect.Field;

public class Main
{
public static void main(String[] args) throws IllegalAccessException
{
Object o = new Object() { public int anon = 20; };
printAnon( o );

}
static void printAnon( Object o ) throws IllegalAccessException
{
Class c = o.getClass();
Field fields[] = c.getDeclaredFields();
for( Field f : fields )
{
System.out.println( f.getName() + " = " + f.get( o ) );
}
}
}

Better to NOT use Object and just design an appropriate super-class however.
 
T

Tom Hawtin

Mark said:
To re-enforce what Andreas said, this is a design issue, not a language
issue. You must design your super-class so that you can access
variables or other information from the anonymous class.

If you absolutely cannot, then here's the reflection example:

And if you don't want to use reflection, but do want to do so really
quite odd:

http://jroller.com/page/tackline?entry=method_local_methods_for_recursion

public static void sort(final long[] array) {
if (array.length <= 1) return;
new Object() {
private void sort(int off, int len) {
... partition ...

// Recursively sort non-partition-elements
if ((s = b-a) > 1)
sort(off, s);
if ((s = d-c) > 1)
sort(n-s, s);
}
private void swap(int a, int b) {
long aOrig = array[a];
array[a] = array;
array = aOrig;
}
}.sort(0, array.length);
}

Tom Hawtin
 
P

Patricia Shanahan

Mark said:
To re-enforce what Andreas said, this is a design issue, not a language
issue. You must design your super-class so that you can access
variables or other information from the anonymous class.

More usually, it is not even a matter of designing a super-class. The
commonest use of anonymous inner class objects is to provide a very
simple, one-off, implementation of some interface, such as Comparator.

Patricia
 
T

Twisted

... you'd not only define the variable, but also overwrite
a (non-final, of course) method from the base-class, which then
accesses the variable.

e.g.
Object o = new Object() {
public int anon = 20;
// doesn't make much sense except for the sake of an example:
public String toString() { anon++; return Integer.toString(anon); }
}
o.toString(); // -> 21
o.toString(); // -> 22

Alternatively, you can also use the reflection-API to
see and access the variable "anon" of the object referenced by "o".


The reasons are perhaps more technical than anything else.
At class-file level, C is in a separate class-file than the
class containing A, and it would be quite complicated to implement
a connection between C's "i", and the local variable "i" in A.
The same restriction holds currently, if "i" were a field of the
class that contains "A", and my feeling is, that this case is
slightly more likely to change in future than the case of a local
variable.

You can work around it too, by using final arrays or final objects
with mutable fields. In fact, you can get closure-like behavior:

public int lexicalContext () {
final int[] someLocal = new int[1];
someLocal[0] = 17;
final int[] result = new int[1];
...
Foo closure = new Foo () {
public double evaluate (int g) {
// do stuff with g and someLocal[0]
someLocal[0]++;
// do more stuff
if (foobar) return 1.0; // returns to evaluator
if (somethingElse) {
result[0] = 42;
throw new MyClosuresRuntimeException();
// returns from lexicalContext(!); see below
}
...
return g*someLocal[0]*Math.PI/11;
}
}
...
try {
int fiddlesticks = mumble.evaluator(closure);
// may invoke closure, which may return from here
// or back into mumble.evaluator
...
// do something with fiddlesticks
...
return fiddlesticks%3
} catch (MyClosuresRuntimeException e) {
return result[0]; // and yes I can also pull
// a rabbit out of a hat in case you were wondering
}
}
 
P

Patricia Shanahan

Andreas said:
The reasons are perhaps more technical than anything else.
At class-file level, C is in a separate class-file than the
class containing A, and it would be quite complicated to implement
a connection between C's "i", and the local variable "i" in A.
The same restriction holds currently, if "i" were a field of the
class that contains "A", and my feeling is, that this case is
slightly more likely to change in future than the case of a local
variable.

I don't understand the remark about "a field of the class...".

This program:

public class AnonTest {

private String name = "InitialName";

public void setName(String newName){
name = newName;
}

public Object o = new Object(){
public String toString(){
return name;
}
};

public static void main(String[] args) {
AnonTest a = new AnonTest();
System.out.println(a.o);
a.setName("xxx");
System.out.println(a.o);
}
}

compiles and runs. Could you modify it to show the nature of the
restriction?

Patricia
 
M

Mark Space

Patricia said:
More usually, it is not even a matter of designing a super-class. The
commonest use of anonymous inner class objects is to provide a very
simple, one-off, implementation of some interface, such as Comparator.

I almost gave an example of a "properly designed" super-class using
Runnable as the super-class, but in both cases I think Comparator and
Runnable are super-classes that have already been designed for the
programmer. This was sorta my point.

If one is going to start with Object, then one has to do a bit more work
to get the proper super-class. The question is: does an already
designed class exist, or does the programmer have to invent one?

I don't like the idea of overriding toString(); this changes the implied
purpose of the method. It's fine for the quick example Andreas gave,
but in the real world it would invite ridicule. In general, I'd think
most classes would not have an appropriate method to override unless one
was designed in, such as the compareTo() method Comparator provides.
 
S

Stefan Ram

Andreas Leitgeb said:
The reasons are perhaps more technical than anything else.

»Guy Steele wrote:

Actually, the prototype implementation *did* allow
non-final variables to be referenced from within inner
classes. There was an outcry from *users*, complaining
that they did not want this!«

http://madbean.com/2003/mb2003-49/
 
T

Twisted

»Guy Steele wrote:

Actually, the prototype implementation *did* allow
non-final variables to be referenced from within inner
classes. There was an outcry from *users*, complaining
that they did not want this!«

http://madbean.com/2003/mb2003-49/

And they got it anyway. See elsewhere in this thread -- Java
effectively *does* have closures, via the one-element-array trick and
exception abuse.

(Storing the closure and executing it after the enclosing function
exited of course results in a runtime exception bubbling up elsewhere
in the code and probably blowing everything up, but that's only proper
-- closures that return from their enclosing function are not meant to
be stored and executed after that function returns, and doing this
anyway is a bug and *should* therefore blow up the application with a
runtime exception stack trace as its final testament, just as invoking
a method on null does. The major issue is that really the exception
should be unique to each instance of the enclosing function being
executed. This can in effect be done, if you make a RuntimeException
in the enclosure:

public int enclosure () {
final RuntimeException throwme = new RuntimeException();
final int result[] = new int[0];
...
Runnable closure = new Runnable () {
public void run () {
...
if (someCondition) {
result[0] = something;
throw throwme;
}
...
}
}
...
try {
doSomethingWith(closure);
} catch (RuntimeException e) {
if (e == throwme) return result[0];
throw e;
}
}

The specific exception constructed for this invocation of enclosure is
compared for identity with the caught exception. If it's not the exact
same object the exception is simply rethrown, so the enclosure method
does not improperly eat any exception that should be handled elsewhere
or abort the program. Including even a closure returning from lexical
scope after its embedding function had already returned. Including
even the closure in "enclosure" doing so, and then trying to return,
and this managing to happen inside the try block during a later call
to "enclosure".

Of course, you'll probably not believe me if I tell you that Java also
has optional method parameters with defaults and keyword syntax.
Right? I knew it! You don't believe me.

public void function (Map args) {
Integer numFoos = (Integer)(args.get("numFoos"));
if (numFoos == null) numFoos = (Integer)(defaults.get("numFoos"));
int nFoos = numFoos.intValue();
Runnable doOnFail = (Runnable)(args.get("doOnFail"));
if (doOnFail == null) doOnFail = (Runnable)
(defaults.get("doOnFail"));
Integer maxFoos = (Integer)(args.get("maxFoos"));...
...
if (nFoos > mxFoos) doOnFail.run();
...
}

Map futz = new HashMap ();
futz.put("numFoos", Integer.valueOf(3));
function(futz);

Still don't believe me? :)
 
R

Roedy Green

How do we make 'o' of same type, considering that
anonymous class has no name?

The whole point of an anonymous class is you only need to create them
at one point in all your code. Otherwise use an inner class.

If you want to be silly you can use tricks described at
http://mindprod.com/jgloss/classforname.html
to get a Class object then use reflection to instantiate more of them.
 
M

Mike Schilling

hello

1) Syntax for creating anonymous class:

new < superclass> ( <params> ) { <class definition> };


Example:

Object o = new Object() { public int anon = 20; };


The above statement creates an object of anonymous class and returns
a reference to it. But in order to use members declared in anonymous
class ( o.anon ), variable o would have to be of same type as
anonymous class. How do we make 'o' of same type, considering that
anonymous class has no name?

You use some other sort of inner class; that's not what anonynmous classes
are for.
2)
If we declare class C inside method A(), then any local variable
( declared inside A() ) that will also be used inside class C, must be
declared final. Why? I assume there must be some valid reason for
that?


public void A ( final int i ) {

class C {
int u = i ;
}
}

Presumably to help answer to the question "When the anonymous (or local)
class instance accesses a local variable, does it see the current value or
the value as it was when the instance was created?" If the variable is
final, the answer is "Both".
 
A

Andreas Leitgeb

Stefan Ram said:

Actually, I interpret this comment by Guy Steele to
affirm my position, except for one small detail:

It wasn't (as I implied) that no way was found to do this
connection, but the way he (Guy Steele) had implemented had
some disadvantages that the users didn't want to accept,
back then.

Even Guy Steele seems to believe in a chance to eventually
"... restoring full-blown support for closures in the future."
even for his implementation, where I only speculated about
*some future* implementation.

PS: full blown support for closures means direct support,
not just with help of explicit "containers/wrappers".
 
A

Andreas Leitgeb

Patricia Shanahan said:
I don't understand the remark about "a field of the class...".
Patricia

You're right. It was a bug in my thinking...

If "i" were a field of the class that contains "A", ...
then it of course *doesn't* need to be final.

Sorry for confusion caused by that statement.
 
A

Andreas Leitgeb

Twisted said:
You can work around it too, by using final arrays or final objects
with mutable fields. In fact, you can get closure-like behavior:

It's good that you mentioned the use of arrays for sharing
non-final data with a closure. I plainly forgot to mention this
workaround, myself.

However, I didn't understand the necessity of involving exceptions.
whenever the closure has done its job, you just access the array
element in the outer object, no matter if any exceptions were
thrown from the closure or whether it returned normally.

Even more, if you pass the closure to somewhere, where it is
supposed to be "used" more than once, then your exception-throwing
closure will break that after its first use.

Surely there are cases, where you want to throw exceptions
from the closure, but that isn't at all related to sharing data.
 
T

Twisted

It's good that you mentioned the use of arrays for sharing
non-final data with a closure. I plainly forgot to mention this
workaround, myself.

However, I didn't understand the necessity of involving exceptions.
whenever the closure has done its job, you just access the array
element in the outer object, no matter if any exceptions were
thrown from the closure or whether it returned normally.

Even more, if you pass the closure to somewhere, where it is
supposed to be "used" more than once, then your exception-throwing
closure will break that after its first use.

Surely there are cases, where you want to throw exceptions
from the closure, but that isn't at all related to sharing data.

The exception is to do the other thing closures are supposed to be
able to do -- return from the enclosing function. In Smalltalk you can
just [^value] inside a block, and the return doesn't simply exit the
block, it exits the function with the block literal inside it and
returns the value specified. To emulate this in Java you would throw a
runtime exception from a method of an anonymous inner class, and catch
it in the method that passes it to another call.

Yes, if it gets stored and used later, after the original method has
exited, the exception will bomb the JVM. So? That's a bug -- in
Smalltalk, it is likewise a bug if you store a [^value] somewhere and
eventually execute it after the original context has already returned.
Bugs like these are supposed to result in a stack trace from some
uncaught exception in Java, as with NullPointerException and the
like. :)

In practise, I don't see much use for return-from-context capability
in Java, versus its handiness in something like Smalltalk. The
interesting thing is that it is actually there, if obscure and
demanding some syntactic salt. (It's also not as robust, in that bad
code that catches and discards arbitrary RuntimeExceptions in the call
chain can break it. Then again, Smalltalk closures are non-reentrant!
Threading in Java is so much less painful. :))
 
T

Twisted

PS: full blown support for closures means direct support,
not just with help of explicit "containers/wrappers".

All that they need to do is write in some syntactic sugar for the
stuff I demonstrated in this thread. For the passing-in-mutable-locals
thing, silently autoboxing them in one-element arrays -- not unlike
the autoboxing of primitives put into container classes or otherwise
used with generics in 1.5. A return-from-context capability could use
an anonymous exception throw and catch under the hood, not allow the
exception to be absorbed by intervening code (even if it has "catch
(Exception e) {...}"; of course "finally" clauses would still execute
as for any exception propagating up the call chain), and provide a
simple syntax for returning from the enclosing method, say
methodname.return foo or to disambiguate Classname.methodname.return
foo (in case you've decided to get baroque and nest anonymous inner
classes, and from a deep down one return from any of the multiple
enclosing contexts).

In practise, I expect the requirement for "final" on the local
variables may be quietly dropped and nothing will be done to support
returning from enclosing contexts, though it could be done, as it just
isn't very useful in typical Java programming (to the point that I've
never used it aside from as proof-of-concept).
 
T

Tom Hawtin

Twisted said:
In practise, I expect the requirement for "final" on the local
variables may be quietly dropped and nothing will be done to support
returning from enclosing contexts, though it could be done, as it just
isn't very useful in typical Java programming (to the point that I've
never used it aside from as proof-of-concept).

If closures could support abstraction like the for loop, early exits
should be common. Think how you would normally implement a 'find first'.

OTOH, if closures are supposed to abstract control flow away, then the
early exits should be moved to the 'algorithm method' and not in the
closure.

Tom Hawtin
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,573
Members
45,046
Latest member
Gavizuho

Latest Threads

Top