Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / June 2007

Tip: Looking for answers? Try searching our database.

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

Thread view: 
kaja_love160@yahoo.com - 28 Jun 2007 18:35 GMT
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
Andreas Leitgeb - 28 Jun 2007 20:40 GMT
> hello
> 1) Syntax for creating anonymous class:
[quoted text clipped - 5 lines]
> 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
[quoted text clipped - 4 lines]
>             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 :-)
Twisted - 28 Jun 2007 23:00 GMT
On Jun 28, 3:40 pm, Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at>
wrote:
> kaja_love...@yahoo.com <kaja_love...@yahoo.com> wrote:
> > hello
[quoted text clipped - 40 lines]
> 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
   }
}
Andreas Leitgeb - 29 Jun 2007 14:30 GMT
> 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.
Twisted - 29 Jun 2007 21:49 GMT
On Jun 29, 9:30 am, Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at>
wrote:
> > You can work around it too, by using final arrays or final objects
> > with mutable fields. In fact, you can get closure-like behavior:
[quoted text clipped - 14 lines]
> 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. :))
Patricia Shanahan - 28 Jun 2007 23:08 GMT
...
>> 2)
>> If we declare class C inside  method A(), then any local variable
[quoted text clipped - 13 lines]
> 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
Andreas Leitgeb - 29 Jun 2007 14:17 GMT
>> The same restriction holds currently, if "i" were a field of the
>> class that contains "A", ...
> 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.
Stefan Ram - 28 Jun 2007 23:15 GMT
>>final. Why?
>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/
Twisted - 29 Jun 2007 00:49 GMT
> >>final. Why?
> >The reasons are perhaps more technical than anything else.
[quoted text clipped - 7 lines]
>
> 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? :)
Andreas Leitgeb - 29 Jun 2007 13:21 GMT
>>>final. Why?
>>The reasons are perhaps more technical than anything else.
> http://madbean.com/2003/mb2003-49/

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".
Twisted - 29 Jun 2007 21:56 GMT
On Jun 29, 8:21 am, Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at>
wrote:
> 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).
Tom Hawtin - 30 Jun 2007 15:38 GMT
> 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
Mark Space - 28 Jun 2007 22:19 GMT
> Example:
>
[quoted text clipped - 5 lines]
> 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.
Tom Hawtin - 28 Jun 2007 22:42 GMT
> 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[b];
            array[b] = aOrig;
        }
    }.sort(0, array.length);
}

Tom Hawtin
Mark Space - 28 Jun 2007 23:20 GMT
> 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

Tom you've hurted my brain again.
Patricia Shanahan - 28 Jun 2007 22:55 GMT
>> Example:
>>
[quoted text clipped - 9 lines]
> 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
Mark Space - 28 Jun 2007 23:10 GMT
> 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.
Roedy Green - 29 Jun 2007 00:56 GMT
> 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.
--
Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com
Mike Schilling - 29 Jun 2007 04:21 GMT
> hello
>
[quoted text clipped - 11 lines]
> 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
[quoted text clipped - 8 lines]
>            }
> }

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".


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.