Passing a Method Name to a Method

G

Gene Wirchenko

Dear Jav'ers:

Maybe I will find this after searching more, but so far, no good.

I want to pass a parameter of a method name to another method.

N.B.: I do not want to pass the method name as a string. I want
to pass it as a pointer / reference / whatever term is used for this
in Java.

I am doing this to test different ways of parsing. I want to be
able to do this (timing details not shown):

for (i=1; i<=nRepetitions; i++)
Parse(ThisWay);

for (i=1; i<=nRepetitions; i++)
Parse(ThatWay);

static void Parse
(
????? What goes here? MethodToUse
)
{
...
????? How exactly is this done? MethodToUse(actual parms)
...
}

static returntype ThisWay(formal parms)
{...}

static returntype ThatWay(formal parms)
{...}

The signatures and return types of ThisWay() and ThatWay() would
be identical.

Sincerely,

Gene Wirchenko
 
F

Fuschia, President-Elect of the Bright Purplish-Gr

Dear Jav'ers:

Maybe I will find this after searching more, but so far, no good.

I want to pass a parameter of a method name to another method.

N.B.: I do not want to pass the method name as a string. I want
to pass it as a pointer / reference / whatever term is used for this
in Java.

Unfortunately, you can't do this easily or efficiently (you'd need to
use the Reflection API's Method objects) in Java; what you really want
is a functional language like Clojure or Scala.

If you really must use Java, define an interface that ThisWay and
ThatWay can be instances of and which specify a parse method, and pass
an instance to the parser class's method. (The so-called "strategy
pattern".)
 
S

Stefan Ram

Gene Wirchenko said:
I want to pass a parameter of a method name to another method.

In Java, there is no such thing as »a parameter of a method name«.
There are »parameter declarations«, which are a part of a
»method declaration«. (Vulgo: »parameters« of »methods«
[not »method names«]).
N.B.: I do not want to pass the method name as a string.

A method /name/ /is/ a string.
I want to pass it as a pointer / reference / whatever term is
used for this in Java.

The closest you can get is

http://download.java.net/jdk7/docs/api/java/lang/reflect/Method.html

, although you may not like it.

Or use a »method object«, that is an object implementing
an interface with a single method, such as, for example,

http://download.java.net/jdk7/docs/api/java/lang/Runnable.html

or

http://download.java.net/jdk7/docs/api/java/util/concurrent/Callable.html

(it is called »function object« or »functor« in the C++ world.)

Such an object represents a methods as a run-time value.

Java 8 will have lambda expressions.
 
M

markspace

Dear Jav'ers:

Maybe I will find this after searching more, but so far, no good.

I want to pass a parameter of a method name to another method.


As others have said, you can't do this literally. However you have a
few options using interfaces, classes, dependency injection, and good
ol' software engineering.

First, the interface/class method:

public class Parser {
final private Language parser;
public Parser( Language parser ) {
this.parser = parser;
}
public parse( Reader in ) {
parser.parse( in );
}
}

Here, you use a Parser which uses dependency injection to determine
which language you are going to parse. You use it like this:

Parser p = new Parser( new JavaParser() );
p.parse( System.in ); // parse stdin

Where JavaParser is:

public class JavaParser implements Language { ...

and

public interface Language {
parse( Reader in );
}

You could of course pass in the language at the same time, but that's a
little less OOD.

public class Parser {
public static parse( Language parser, Reader in ) {
parser.parse( in );
}
}

Note that the "don't do it in Java" guy, Fuschia, is off his rocker.
This is very efficient in Java as the JVM will recognize the JavaParser
class is effectively final and optimize the call to use non-virtual calls.

You can also do similar things with Runnable or Callable, which just
avoids declaring a type. Since declaring a type isn't that big of a
deal, this is usually poor solution unless you are in fact spawning
threads and using the concurrency API directly.

public class Parser {
final private Runnable parser;
public Parser( Runnable parser ) {
this.parser = parser;
}
public parse() {
parser.run();
}
}

You might call this with an anonymous class rather than declaring a yet
another type, however again that might not really be worth it. I'm
drawing a blank here how to pass in arguments to the run method, so I'll
cheat:

Parser p = new Parser( new Runnable() {
private final Reader in = System.in;
public void run() {
new JavaLanguage.doIt( in );
}
} );
p.parse(); // parse stdin

Note that when you see this for "real", say in the Java API, you'll
typically use a factory method, not instantiate an injectable object.
(For example, both the ScriptEngineManager and
javax.xml.parsers.DocumentBuilder use factory methods.) So don't ignore
the Factory Pattern in your own designs as well.

Parser p = Parser.getParser( "Java" );
p.parse( System.in ); // parse stdin

No code compiled or tested. ;)
 
E

Eric Sosman

Dear Jav'ers:

Maybe I will find this after searching more, but so far, no good.

I want to pass a parameter of a method name to another method.

N.B.: I do not want to pass the method name as a string. I want
to pass it as a pointer / reference / whatever term is used for this
in Java.

(It's "reference." The only data items a Java program can
manipulate are primitives and references.)

Pass a reference to an object that implements an agreed-upon
interface. See, for example, the two-argument version of
java.util.Arrays.sort().

Y'know, Gene, you've been asking a spate of pretty elementary
questions. Maybe some time with a textbook or other documentation
would be helpful, or possibly relocation to c.l.j.help, which is
more beginner-oriented.
 
J

Joshua Cranmer

I want to pass a parameter of a method name to another method.

No you don't. You essentially want to go with the interface approach, as
the prior responders to myself have said.

Java does not have a concept of a function pointer or method handle. It
is possible to emulate this to some degree with reflection, but if you
are contemplating calling Method.invoke, you are almost always doing
something wrong.
static returntype ThisWay(formal parms)
{...}

static returntype ThatWay(formal parms)
{...}

Why are you having static methods (on the same class, I presume) for two
different ways of parsing instead of using separate parser classes?
 
F

Fuschia, President-Elect of the Bright Purplish-Gr

public interface Language {
parse( Reader in );
}

You could of course pass in the language at the same time, but that's a
little less OOD.

public class Parser {
public static parse( Language parser, Reader in ) {
parser.parse( in );
}
}

Note that the "don't do it in Java" guy, Fuschia, is off his rocker.
Wrong.

This is very efficient in Java as the JVM will recognize the JavaParser
class is effectively final and optimize the call to use non-virtual calls.

I never claimed otherwise. In fact that approach is exactly what I
recommended he use if he insisted on not going to a JVM language that
better supports functional programming.

It was using the Reflection API and Method objects that I said would not
be efficient.
 
A

Arved Sandstrom

No you don't. You essentially want to go with the interface approach, as
the prior responders to myself have said.

Java does not have a concept of a function pointer or method handle. It
is possible to emulate this to some degree with reflection, but if you
are contemplating calling Method.invoke, you are almost always doing
something wrong.


Why are you having static methods (on the same class, I presume) for two
different ways of parsing instead of using separate parser classes?
At this stage of the game, considering the original problem statement, I
haven't seen any compelling arguments for not doing

for (i=1; i<=nRepetitions; i++)
ParseThisWay(args);

and

for (i=1; i<=nRepetitions; i++)
ParseThatWay(args);

(Note the editing from the original.) I mean, there's a strong
distinction between testing different methods of parsing (which the OP
mentioned he was doing) and coding your application to permit selection
of arbitrary parsing method.

We may be thinking at cross-purposes here. It could be that Gene,
incidental to the problem of testing parsing techniques, might really
just be curious as to whether it's possible to do something like he
asked about, i.e. function pointer-looking things. Practically everyone
else seems to have posited a Parsing U"ber-Problem which demands an
interface/pattern-based adaptive dynamic solution for production use,
and for my part I'm suggesting that if the actual issue is simply
adhoc/experimentally testing a couple of different chunks of code why
not just hardcode a couple of different methods (the engineering Good
Enough approach).

AHS
 
G

Gene Wirchenko

On Wed, 22 Jun 2011 22:09:05 -0400, Eric Sosman

[snip]
Y'know, Gene, you've been asking a spate of pretty elementary
questions. Maybe some time with a textbook or other documentation
would be helpful, or possibly relocation to c.l.j.help, which is
more beginner-oriented.

Yes, I know. I have been reading the on-line documentation, but
it is often hard to find out how to do something. I usually already
know the concept, but if it is called something different in Java, it
can be hard to find the documentation.

What is the difference between the two newsgroups other than that
c.l.j.help seems fairly moribund?

Sincerely,

Gene Wirchenko
 
A

Arved Sandstrom

This is procedural programming, while the approach with the
same method name in different classes is object-oriented
programming, because it would use polymorphism.

Under specific and fixed requirements, it is possible that
both solutions are equally well. However, requirements often
change in time.

In the general case, object-oriented programing is better,
because it allows to add another parse method by adding
another (third) parse class /without changing/ most of the
other code and thus fulfills the open-closed principle,
while procedural programming usually would required code
changes in more places when adding a third way to parse.
You're absolutely correct in almost all respects. I'd go further and
assert that in an adhoc, experimental situation then the procedural-type
solution (which is nothing to hold your nose for; a great deal of Java
code _is_ inevitably procedural, and later-generation hybrid- or
multi-paradigm languages acknowledge this reality) might even be better
because the hard-wiring looks adhoc and experimental and
throwaway...precisely because it _is_.

Setting things up the "OO way" in this situation, while aesthetically
appealing, also means that you've made a deliberate design decision to
allow for more straightforward swapping of parse logic. This _should_ be
a deliberate design choice. I'm sure you've read the odd article that
decries elaboration of implementation on a "what if?" and "just in case"
basis - I'm mostly in that camp.

This may seem like a trivial example - no harm done, and all that - but
over-engineering starts exactly with thought processes like this. And
the second you start designing and coding stuff to be more adaptable and
general-purpose, the more danger there is that the code is going to be
kept, and go into production. Not so desirable if the requirement didn't
exist. I know requirements often change, but my philosophy on that is,
provided that your project costing structure accurately assigns change
request costs to the people changing the requirements, make the cost of
requirements changes public, highly visible, and somewhat painful.

To return to my original point, with the added context of your reply
above, my argument remains this: we don't know what case this is.

AHS
 
J

Joshua Cranmer

Setting things up the "OO way" in this situation, while aesthetically
appealing, also means that you've made a deliberate design decision to
allow for more straightforward swapping of parse logic.

Given that most of the parsers I deal with are lengthy recursive-descent
parsers, I assumed that there would have been a distinct parser object
that handled the lexing and parsing itself and furthermore that two
parsers would want to be in two separate classes. Also, since the
question was asked with the purpose of timing, I presumed that it was
fairly large and complicated parsers that were being tested for the
purpose of determining the more efficient one. As a logical consequence
of these assumptions, I would have assumed that the natural way to
implement this code is as objects, hence my surprise to not find it
implemented in such a manner.

Of course, all of this relies on my assumptions being correct.
 
R

Roedy Green

????? How exactly is this done? MethodToUse(actual parms)
...
You are presuming that Java works internally like assembler or C
where all methods exist as machine code and have an address,
determined pretty much at link time.

In Java it is much more complicated than that. Before a class is ever
used, the method reference only exists as a string. The first time it
is invoked, the class is loaded, the method offset looked up and the
caller is patched to this offset. Later code gets converted to
machine code via hotspot, and you have machine address links rather
than offsets in byte code.

That's the bad news. The good news is you can pass methods and classes
about as strings, and dynamically invoke methods with constructed
parameter lists. This is ugly and cumbersome and slow, but very
flexible. See http://mindprod.com/jgloss/reflection.html
You can do a lot with simply dynamic loading of variant classes that
support an interface. See http://mindprod.com/jgloss/classforname.html
http://mindprod.com/jgloss/delegate.html
--
Roedy Green Canadian Mind Products
http://mindprod.com
One of the great annoyances in programming derives from the irregularity
of English spelling especially when you have international teams.
I want to find a method or variable, but I don't know precisely
how its is spelled or worded. English is only approximately phonetic.
Letters are randomly doubled. The dictionary often lists variant spellings.
British, Canadian and American spellings differ.I would like to see an
experiment where variable names were spelled in a simplified English, where
there were no double letters.I also think you could add a number of rules
about composing variable names so that a variable name for something would
be highly predictable. You would also need automated enforcement of the
rules as well as possible.
 
F

Fuschia, President-Elect of the Bright Purplish-Gr

This is procedural programming ...
In the general case, object-oriented programing is better,
because it allows to add another parse method by adding
another (third) parse class /without changing/ most of the
other code and thus fulfills the open-closed principle,
while procedural programming usually would required code
changes in more places when adding a third way to parse.

I'll just mention here that functional programming, in this case at
least, also gives the advantages given by object oriented programming;
specifically, you can add another parse method by adding another (third)
parse *function* without changing most of the other code. And generally
while writing a lot less boilerplate code than Java requires, with one
interface, plus one class skeleton around each parse function, plus
relevant imports and type declarations here and there.
 
F

Fuschia, President-Elect of the Bright Purplish-Gr

What is the difference between the two newsgroups other than that
c.l.j.help seems fairly moribund?

This group's not much less moribund.

It almost makes you wish for the good old days when there were thousands
of posts a month here and half of them were Twisted and people flaming
Twisted. :)
 
B

blmblm

[ snip ]
You can also do similar things with Runnable or Callable, which just
avoids declaring a type. Since declaring a type isn't that big of a
deal, this is usually poor solution unless you are in fact spawning
threads and using the concurrency API directly.

public class Parser {
final private Runnable parser;
public Parser( Runnable parser ) {
this.parser = parser;
}
public parse() {
parser.run();
}
}

You might call this with an anonymous class rather than declaring a yet
another type, however again that might not really be worth it. I'm
drawing a blank here how to pass in arguments to the run method,

I don't think you can, can you? (Someone will probably be along
shortly to correct me if I'm wrong. Sort of a :). )
so I'll
cheat:

Parser p = new Parser( new Runnable() {
private final Reader in = System.in;
public void run() {
new JavaLanguage.doIt( in );
}
} );
p.parse(); // parse stdin

I think this is about the best you can do if you insist on (ab)using [*]
an interface whose methods don't have the parameters you want.

[*] Not that I've ever done anything like that. (Ha.)

[ snip ]
 
B

blmblm

(It's "reference." The only data items a Java program can
manipulate are primitives and references.)

Pass a reference to an object that implements an agreed-upon
interface. See, for example, the two-argument version of
java.util.Arrays.sort().

Sound advice IMO -- if you're familiar with the C library function
qsort, with its function-pointer parameter, comparing it with the
two-argument version of Arrays.sort may be helpful, since IMO they
provide roughly equivalent functionality, and a compare-and-contrast
with something familiar might be easier to grok than suggestions that
might be a little over the head of a novice (no offense to Gene).
In the long term learning good object-oriented design is probably
a good thing, but in the short term ....

[ snip ]
 
M

markspace

I think this is about the best you can do if you insist on (ab)using [*]
an interface whose methods don't have the parameters you want.


I think it's a hack, but it's available if you need to use it. I'm not
recommending it, just pointing it out. Very occasionally, I could see
working with some legacy code where this might be the most economical
solution.
 
M

markspace

On 6/23/2011 10:42 AM, Fuschia, President-Elect of the Bright
I'll just mention here that functional programming, in this case at
least, also gives the advantages given by object oriented programming;
specifically, you can add another parse method by adding another (third)
parse *function* without changing most of the other code. And generally


I'll just mention here that this is fairly specious. A proper OO
solution, like the ones I gave, you can add another parser just by
adding the appropriate class. The boiler plate is about two lines.

while writing a lot less boilerplate code than Java requires, with one
interface, plus one class skeleton around each parse function, plus
relevant imports and type declarations here and there.


The interface is already done, skeleton, imports, etc are already done.
Just add a class with a method. What you gain in Java is type safety,
something not available in the "functional" languages I'm familiar with.
 
A

Arved Sandstrom

On 6/23/2011 10:42 AM, Fuschia, President-Elect of the Bright


I'll just mention here that this is fairly specious. A proper OO
solution, like the ones I gave, you can add another parser just by
adding the appropriate class. The boiler plate is about two lines.

Leaving aside the actual parsing code, none of the possible solutions
involve changing much code. The question is only where the code needs to
be changed.
The interface is already done, skeleton, imports, etc are already done.
Just add a class with a method. What you gain in Java is type safety,
something not available in the "functional" languages I'm familiar with.

Good thing you used the double quotes...because the functional languages
I'm familiar with do have type safety.

AHS
 
F

Fuschia, President-Elect of the Bright Purplish-Gr

On 6/23/2011 10:42 AM, Fuschia, President-Elect of the Bright

I'll just mention here that this is fairly specious.
Wrong.

A proper OO solution, like the ones I gave, you can add another parser
just by adding the appropriate class. The boiler plate is about two lines.

1. package foo;
2.
3. import bar.baz.ParseStrategy;
4.
5. public final class MyParseStrategy implements ParseStrategy {
6. public final Thingy parse (String input) {
7. // The actual implementation goes here
8. }
9. }

I count 8 lines of non-implementation code, not 2, and 162 characters,
plus eight "extra" characters per line of implementation code to indent
it properly. Versus this Clojure code:

(defn my-parse [input]
(the actual implementation goes here))

ONE line of non-implementation code and 26 characters, plus two indent
spaces per line of implementation code.

1/8 as many lines. 1/6 as many characters. 1/4 as many indent spaces per
line of implementation code. And probably a shorter & sweeter
implementation as well.
The interface is already done, skeleton, imports, etc are already done.
Just add a class with a method. What you gain in Java is type safety,
something not available in the "functional" languages I'm familiar with.

Scala also gets you type safety, at a cost of a bit more boilerplate
than the Clojure example.
 

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,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top