access to anonymous inner class instance from another package

R

Robert Dodier

Hello, I have a program that looks something like this:

public class A
{
public static void main (String [] aa) throws Exception
{
Object foo = new Object () { public double times (double x,
double y) { return x*y; } };
java.lang.reflect.Method f = foo.getClass().getMethod
("times", new Class [] {Double.TYPE, Double.TYPE});
bar.baz.Quux q = new bar.baz.Quux ();
q.mumble (foo, f)
}
}

where bar.baz.Quux.mumble eventually calls f.invoke(foo, <stuff>) and
<stuff> are some arguments.

My program compiles OK but when I run it I get an
IllegalAccessException
something like "Class bar.baz.Quux cannot access a member of class A
$1".

I'm not sure I understand the reason for that. bar.baz.Quux.mumble
isn't
attempting any member access in foo's class, neither explicitly via
foo.<whatever> nor implicitly via Class.getMethod or Class.getField.
If f.invoke(foo, <stuff>) fails, how can any call from another package
succeed? It seems that would rule out all the call backs in, say,
Swing
code which are implemented by anonymous inner classes.

Aside from just understanding the problem, I am hoping to find a way
to make the code work.

Thanks for any light you can shed on this.

Robert Dodier
 
L

Lew

Robert said:
Hello, I have a program that looks something like this:

public class A
{
    public static void main (String [] aa) throws Exception
    {
        Object foo = new Object () { public double times (double x,
double y) { return x*y; } };
        java.lang.reflect.Method f = foo.getClass().getMethod
("times", new Class [] {Double.TYPE, Double.TYPE});

Use of reflection here is unwarranted and a nasty antipattern.
        bar.baz.Quux q = new bar.baz.Quux ();
        q.mumble (foo, f)
    }
}

where bar.baz.Quux.mumble eventually calls f.invoke(foo, <stuff>) and
<stuff> are some arguments.

My program compiles OK but when I run it I get an
IllegalAccessException
something like "Class bar.baz.Quux cannot access a member of class A
$1".

"Something like"? Why not give us the *exact* message, hm?

I will bet, absent that vital piece of missing information, that the
member it cannot access is 'times()', which is part of a non-public
inner class not in package bar.baz, and not intrinsic to 'Object',
which is the only known interface to the anonymous class.
I'm not sure I understand the reason for that. bar.baz.Quux.mumble
isn't
attempting any member access in foo's class, neither explicitly via
foo.<whatever> nor implicitly via Class.getMethod or Class.getField.

Wrong. It is attempting to access 'times()'.
If f.invoke(foo, <stuff>) fails, how can any call from another package
succeed? It seems that would rule out all the call backs in, say,
Swing
code which are implemented by anonymous inner classes.

Nonsense. Callbacks are accessed via named interface methods
polymorphically.
Aside from just understanding the problem, I am hoping to find a way
to make the code work.

Instead of an anonymous implementation of 'Object', make the inner
class an implementation of a type known to contain an accessible
method 'times()'.
 
R

Robert Dodier

Use of reflection here is unwarranted and a nasty antipattern.

I remember you. Your responses are always obnoxious,
disdainful, and useless.

Robert Dodier
 
M

Mark Space

Robert said:
My program compiles OK but when I run it I get an
IllegalAccessException
something like "Class bar.baz.Quux cannot access a member of class A
$1".

If you remove the reflection, you have this:

public class BadIdea
{
public static void main( String[] aa ) throws Exception
{
Object foo = new Object() {
public double times( double x, double y ) {
return x * y;
}
};

double d = foo.times( 1.0, 2.0 );
}
}

This gives:

C:\Users\Brenden\Dev\misc\fubar\src\fubar\BadIdea.java:21: cannot find
symbol
symbol : method times(double,double)
location: class java.lang.Object
double d = foo.times( 1.0, 2.0 );


As Lew already explained, you don't have permission to access "times()"
on this object. It's just a bad construct all the way around. Object
is not at all the right type here.

To "fix" this, make a public interface:

public interface MyTimes {
double times( double x, double y );
}

And use that instead of "Object"

public class BadIdea
{
public static void main( String[] aa ) throws Exception
{
MyTimes foo = new MyTimes() {
public double times( double x, double y ) {
return x * y;
}
};

double d = foo.times( 1.0, 2.0 ); // works now
}
}
 
R

Robert Dodier

To "fix" this, make a public interface:

public interface MyTimes {
double times( double x, double y );

}

Is there a way to do this without inventing a named class or
interface?
I was hoping to avoid the clutter.
And use that instead of "Object"

public class BadIdea

What's bad about this? Why the scare quotes on "fix" ?

Thanks for your help.

Robert Dodier
 
L

Lew

I remember you. Your responses are always obnoxious,
disdainful, and useless.

You're entitled to your opinion, of course, but the remark was
technical, accurate, non-personal and designed to give you information
that would help.
 
J

Joshua Cranmer

Robert said:
Is there a way to do this without inventing a named class or
interface?
> I was hoping to avoid the clutter.

Why avoid an interface? One of the chief benefits of interfaces is that
it gives you a convenient place to documentation. It also gives you the
benefit of static typing.
 
M

Mark Space

Robert said:
Is there a way to do this without inventing a named class or
interface?
I was hoping to avoid the clutter.


Not that I know of. Java requires a public type for all objects
exported by your package. That means a public class or a public
interface. Trying to use an anonymous class or a local class instead
won't work, as you are finding out.

"Fix" = not a fix, it's the right way of doing things. Your original
code wasn't "fixable" for what you wanted to do.
 
L

Lew

Mark Space said:
Not that I know of.  Java requires a public type for all objects
exported by your package.  That means a public class or a public
interface.  Trying to use an anonymous class or a local class instead
won't work, as you are finding out.

"Fix" = not a fix, it's the right way of doing things.  Your original
code wasn't "fixable" for what you wanted to do.

Then, once you've implemented a public type as suggested by Mark
Space, Joshua Cranmer, and me originally, you can use polymorphism
instead of the reflection antipattern. This will result in cleaner,
more maintainable and type-safe code.
 
A

Arne Vajhøj

Robert said:
I remember you. Your responses are always obnoxious,
disdainful, and useless.

Use of reflection in this case *is* unwarranted and an antipattern
(I consider all antipatterns to be nasty so I will omit that).

Listen (technically: read) and learn.

Arne
 
D

Daniel Pitts

Robert said:
Is there a way to do this without inventing a named class or
interface?
I was hoping to avoid the clutter.
Reflection is clutter, interfaces are not.

Reflection is best used if you *can't* know at compile time what the
call should be. If this truly is the case, look up the
Method.setAccessible(boolean) method.

Interfaces give you several benefits over reflection:
1. Speed. Reflection is very slow compared to normal polymorphic calls.
2. Type safety. An interface usually guarantees that the method
signature is what you expect, both the client and the service know for
sure they've done the right thing.
3. Documentation. An interface is a convenient place to put JavaDocs
about what is expected of the callback.
4. Clarity. It is *much* easier to read "a.times(x,y);" over
a.getClass().getMethod("times", new Class[] {Double.TYPE,
Double.TYPE}).invoke(a, new Object[] {Double.valueOf(x),
Double.valueOf(y)});
5. Common idioms. There are more people who understand interfaces
and polymorphic dispatch than those who understand reflection.
 
M

Mike Schilling

Robert said:
I remember you. Your responses are always obnoxious,
disdainful, and useless.

Would you prefer it if I said, politely, that reflection is almost always a
bad idea? You haven't given enough context to know for a fact whether it's
required here, but I'm almost sure that it's not.
 
R

Robert Dodier

Would you prefer it if I said, politely, that reflection is almost always a
bad idea?
Yes.

You haven't given enough context to know for a fact whether it's
required here, but I'm almost sure that it's not.

Well, this is Usenet, so feel free to jump to conclusions ...
everyone else does.

Robert Dodier
 
R

Robert Dodier

Reflection is clutter, interfaces are not.

I'm not so sure. What I'm really looking for, which Java doesn't
quite provide, is an anonymous method, analogous to an
anonymous class. Anonymous classes avoid clutter, why not
anonymous methods as well.

Anyway I figured out a way to resolve the problem (via a method
in a named class). Thanks for your help.

Robert Dodier
 
L

Lew

Robert said:
I'm not so sure. What I'm really looking for, which Java doesn't
quite provide, is an anonymous method, analogous to an
anonymous class. Anonymous classes avoid clutter, why not
anonymous methods as well.

For now, a named method in an anonymous implementing class of a named
interface is the closest Java comes.
 
J

Joshua Cranmer

Robert said:
Anonymous classes avoid clutter, why not
anonymous methods as well.

Because of the implementation of the JVM and the strong static typing
nature of Java makes first-class methods tricky to implement. I have
heard that what the BGGA proposal does "under the hood" is very ugly (it
makes the anonymous class implementation look clean by comparison), and
it's not terribly clean in the style of Java. Do you really want to be
working with { double, double => double } types (I haven't even gotten
into the issues with generics!)?

The developers of Java decided that interface-based programming was much
cleaner than function pointer-based programming, and from a
maintainability perspective, I think most people would agree with them.
 
J

Joshua Cranmer

Peter said:
"Most" from what sample set?

Real-world Java programmers in industry.
> The one thing I find most awkward about
Java is its lack of a proper function pointer type and closures. One of
the things I love most about C# is those features. I dare say that
looking at a broader set of people, you'd find that many, if not most,
would agree that one of the things holding Java back the most is its
refusal to include any functional-style paradigms.

How can Java be "held back" if it is the most widely-used programming
language out there?
The mere fact that Java is _filled_ with all these single-method
interfaces and anonymous classes, which are essentially exactly what
function pointers and closures offer but in a more verbose way, shows
that Java hasn't done a single thing to stay away from the idioms that
use these kinds of features. It's just made it really annoying to
implement them.

Is it really filled with single-method interfaces and anonymous classes?
I decided to run a simple script to estimate a count of the numbers of
single-method interfaces in Java. Using OpenJDK, I count approximately
1029 public top-level interfaces in the JDK, about 271 of which have a
single method. If I include all top-level interfaces and annotations, I
get 1397 of which 307 have annotations.

This count is probably an overestimate, as I don't take into account
addition of methods via inheritance, and I expect that (public) nested
interfaces would have more than a few methods. A brief glance of some of
these interfaces don't seem to call out to me features that would be
better as closures, such as a few factory patterns, or the
java.security.interfaces interfaces.

In short, it doesn't seem to be as filled as you claim it to be.
 
L

Lew

Peter said:
The mere fact that Java is _filled_ with all these single-method
interfaces and anonymous classes, which are essentially exactly what
function pointers and closures offer but in a more verbose way, shows

It seems the only objection people have is that the Java idioms are "verbose".

Awww.
that Java hasn't done a single thing to stay away from the idioms that
use these kinds of features. It's just made it really annoying to
implement them.

Not everyone is annoyed by a little extra typing. Especially those who have
to read the resulting code some time later.
 
W

Wojtek

Peter Duniho wrote :
Because of the implementation of the JVM and the strong static typing
nature of Java makes first-class methods tricky to implement.

The first point (implementation of JVM) might be valid. The second (strong
static typing) certainly is not. Other strongly typed languages have
closures, without any real tricky aspects at all.
[...]
The developers of Java decided that interface-based programming was much
cleaner than function pointer-based programming, and from a maintainability
perspective, I think most people would agree with them.

"Most" from what sample set? The one thing I find most awkward about Java is
its lack of a proper function pointer type and closures. One of the things I
love most about C# is those features. I dare say that looking at a broader
set of people, you'd find that many, if not most, would agree that one of the
things holding Java back the most is its refusal to include any
functional-style paradigms.

Hmmm, function pointers...

interface Foo
{
public void doSomething();
}

class One implements Foo
{
One()
{
}

public void doSomething()
{
// stuff to be done
}
}

class Two implements Foo
{
Two()
{
}

public void doSomething()
{
// stuff to be done
}
}

enum FooHolder
{
ONE(new One()),
TWO(new Two());

private Foo foo;

FooHolder(Foo fooIn)
{
foo = fooIn;
}

public Foo getFoo()
{
return foo;
}
}


....

FooHolder.ONE.getFoo().doSomething();


or

work(Foo.TWO);

public void work(FooHolder foo)
{
foo.getFoo().doSomething();
}

Off the top of my head, but the syntax is basically sound.
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top