Skip to main content

Type-safe way for obtaining Method, Field & co. instances

27 replies [Last post]
Joined: 2004-10-11

In addition to ordinary reasonable Class.getMethod("myMethod"), it would be welcome if we could obtain Method & co. instances in a type-safe way (not via String literal)

This does not breaks reflection concepts, just takes them further and extends the possibilities in a type-safe way.

- refactoring, IDE support
- one-sided reflection: you obtain Method instance in a typesafe way and pass it to some generic code which processes it as usual.

Example of where it would be useful:

<br />
class Utility {<br />
   public void callMeBack(Object instance, Method method) {...}<br />
<p>public void doSomething(String thing) {}</p>
<p>void example() {<br />
   // obtain reference to method in a typesafe way<br />
   Method m = ThisClass.class.doSomething(String.class);<br />
   Utility u = ...;<br />
   u.callMeBack(this, m);<br />
}<br />

added on 20040123

Another example where it may be useful is JDOQL.
JDO queries refer to fields of concrete classes. Currently references are hardcoded in strings which is no safe at all and compiler cannot help. And if syntax was simple enough (hard task, I know) JDOQL and many other similar things might really benefit from this.

Message was edited by: patrikbeno

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Joined: 2006-07-05


Essentially the same suggestion.

Joined: 2005-11-28

I don't think annotations complete this need, for the reason stated above, annotation have an ambiguity in that they exist for multiple purposes.

What we need are keywords, which are strict and have one well-defined purpose, not a meta "marker" or a signal to be replaced by boilerplate.

You misunderstood my proposal. It's actually very similar to yours.

The complete revamped version would look like:

/* This is one form */
Method m = DAO.class.myMethodName(String.class,String.class).method;

/* The other overloaded form. */
Method m = DAO.class.myMethodName(String.class).method;

/* In practice would look like... */
Method m = UserDAO.class.getUserById(Integer.class).method;

I'm using the parameter types as the way to disambiguate overloaded forms of the same method name, and this is consistent with how reflection currently lets you disambiguate methods.

The .method keyword is a good addition I think in that it allows you to jump right to the method way in a way that is consistent with .class. Shouldn't there be a .field too? :)

Joined: 2005-12-22

Re-Thinking all about, I like Beno's proposal better than ours. (I know, who cares what I like more? Let me explain).

You and I, by different paths, came to the [b]method[/b] keyword. That means adding other keyword [b]field[/b] for fields.
I like the [b]:[/b] proposal beacause it simplifies those two keywords in one operator, whithout introducing ambiguity (you know that is a field or a method).

I think that the [b]:[/b] operator is not a solution to linking the programming levels normal and meta. But is a better aproximation than keywords.

Joined: 2005-06-22

> i would rather prefer operator, something like this:
> Field f = A.class:something;
> Method m = A.class:someAction(String.class);
> [/code]

I agree that an operator ist probably better than a keyword. I wouldn't mind using [b]&[/b] as a prefix operator (yes, of course am I a former C programmer...)
So that would change your code sample to:
Field f = &A.something;
Method m = &A.someAction(String);

You'll notive that I have also left out the [b].class[/b] syntax, since that looks like a runtime expression, not really befitting a declarative statement.
What do you think?

Joined: 2004-10-11

[i]although i suggested an operator, i'd be careful using operators for an ad-hoc purpose like in perl or bash, even for sake of verbosity minimization.
that way syntax becomes uncomprehensible and unreadable very quickly...[/i]

what i like about ':' syntax is that it works in the same way and direction as dot, it only switches context (you cannot say this about your proposal, btw)

dot says "i'm calling ya!" [i];[/i]
colon says "i want your meta info!" [i];[/i]

now turn on your imagination:
you could also navigate type tree metadata:

1) navigating static type tree, data can be all null
2) type safe: referencing types indirectly. i.e. if i want to use type of field 'address' defined in class Person, i don't wanna reference it directly (Address.class), because somebody may refactor class Person and change the type of 'address' field and breaks my code silently... with indirect references to static type tree model, this is type safe...

now consider verbosity:

Field f = person:address:city;
Method m = person:address:city:showInfo();
Class c = person:address:city.getType();

same stuff the old way:

Field f = Person.class.getField("address").getType().getField("city");
Method m = Person.class.getField("address").getType().getField("city").getType().getMethod("showInfo");
Class c = Person.class.getField("address").getType().getField("city").getType();

Joined: 2003-07-06


I really like what you are proposing.

Using your syntax, would this be correct?

class DoSomething {
public doIt(Runnable:run() runner) {
// not sure what would go here

Joined: 2004-10-11

sorry, I don't think so :-|

it is an invalid declaration: you are using dynamically evaluated expression (Runnable:run()) in a static context (compile time)

Runnable:run() is runtime expression which would return Method instance (same thing you get via Runnable.class.getMethod("run")).

you cannot use it in declarations...

further, what would you do in the body of the doIt() method with plain Method instance which points to ? you don't even provide object on which you could invoke() such method (not mentioning fact that it simply does not make sense)

you probably want to do completely different thing (delegate).

when I think about it...

void doIt(Runnable runner) {;

/* delegates have simplified definition
their full-blown and more powerful nature is anonymous class
following syntax conflicts with anonymous constructors but I quite like it :-) */

doIt(new Runnable() {{

or, another option, which looks more like your idea but conflicts with my original proposal

/* this declaration says that you can pass a code block parameter which will be wrapped by */
void doIt(@Delegate Runnable:run() runner) {;

/* this would create Runnable instance with run() body filled with the {} block from parameter */

doIt({ System.out.println("Hello!") });

but all this is just syntactical excercise ;-)

- i like delegates :-)
- i know anonymous classes are more powerful and stronger concept
- still, proper delegate support (even built as syntactic sugar around anonymous classes) could decrease verbosity a lot

Joined: 2005-11-28

btw, Eclipse can refactor the .class notation. I hope you're not refactoring with vi ;)

Joined: 2004-10-11

ok, I do refactor a lot and I use IDEA for that purpose.

but I am kinda missing how this relates to my previous post or this proposal at all...
would you mind clarifying that? thnx

Joined: 2004-10-11

personally, i hate introducing new keywords of any kind. (more, now that we have annotations, we don't need any new keywords; more #2, we should eliminate most of the keywords and replace them with annotations)

but that's another story...

there's problem with referencing methods since there can be more methods with the same name and different signatures...

your proposal mixes invocation with the static reference: [i]object.doSomething("lala").method[/i]
this is bad...

i would rather prefer operator, something like this:

class A {
String something;
void someAction(String s);

Field f = A.class:something;
Method m = A.class:someAction(String.class);

might also work on objects:

A a;
Field f = a:something;
Method m = a:someAction(String.class);

what operator to use is an open question.
which do you like most?
should we use existing one or add new?

Joined: 2005-12-22

I'm thinking aloud:
Arent't operators another form of reserved words?
I mean, I agree with you in what you critize me: more keywords are not a good idea. But aren't operators in the same level of bad idea?

Another option you propose is to use annotations. Though I'm not against using annotations (like other people), what I don't like too much is that they can become another language inside java to describe things that can be perfectly described with Java. (That means more ambiguity, which we don't want)

Annotations are a way to connect a programming level with its meta-level (I mean, you write a method and you write an annotation about the method [i]itself[/i]).
So, it seems logical to use annotations when you want to go from one level to its meta-level.
"I don't want to execute the method, I want the method [i]itself[/i]".

However the syntax for using annotations are rather complicated for using it as comfortably as the operator you proposed. (Imagine asking for the annotation associated to the method for asking the method, or something like that)

I believe we need to think a way to connect these two levels as simple as possible.
I don't know how, apart from the alternatives already proposed. Any ideas?

Joined: 2004-07-16

Rather than Cls.class.doSomething, it should be just Cls.doSomething. At least, that works for methods. I'm less sure about fields. Maybe "Cls.&field" or something?

Also, I'd like it if there were some delegate-like support, since that runs way faster than reflection, is more convenient, and is more type safe.

For instance, I could say:

interface Blah {
String doSomething();

Blah blah = this.toString;

And that "this.toString" automatically creates an inner class that implements the Blah interface which calls this.toString.

But even just nicer, compiler-checked access to Method instances as originally requested above would still be very nice.

Joined: 2005-12-22

The problem with expressing something like [i]Cls.doSomething[/i] is that you don't know if that is a call to a static method or a way of getting the method object.
The same thing happens when using [i]Cls.class.doSomething[/i].
I am calling to doSomething in a Class object? or asking for the method object?

To workaround this problem, [and I think what Patrik Beno has proposed is a great idea (we just have find a way)], we could make [i]field[/i] and [i]method[/i] special keywords. I know that is not a good idea to add more keywords to the language, but it would help to build expressions like this:

[i]Method someMethod = Cls.doSomething(String).[b]method[/b];[/i]
I'm asking for the method object.

[i]Field someFieldObject = Cls.someField.[b]field[/b];[/i]
I'm asking for the field object.

Do you think this breaks other things? (Of course, field and method should be reserved words, which I don't like and could have bad consecuences for backward compatibility).
But since we have have the [i]class[/i] keyword, [i]method[/i] and [i]field[/i] don't sound so bad to me.

Message was edited by: kfgodel

Joined: 2005-12-22

Thinking a little more about the [b]method[/b] keyword.
What do you think of something like this:

Gets the method object

[i]Cls object = ...
Gets the method call to the specified instance. If we have something like a MethodCall class, the last sentence could return that.

[i]Cls object = ...
MethodCall methodCall = object.doSomething("lala").[b]method;[/b]
methodCall.invoke()[/i] or

We could retain the method call itself as an object, and use it for other objects without carrying the parameters with the method object.

What dou you think? It's a weird stuff?
(Beno, I would like to know your thoughts about it!)

Joined: 2005-11-28

I think it's incredible that I posted pretty much the exact same conclusion of this thread somewhere else. Has this been submitted via a JSR? I really don't understand why it's not part of reflection already.

In a Java culture where people are already producing byte-code rewriting engines, I would think the JCP would approve an enchancement to type-safety in the core itself.

Joined: 2004-03-18

That still uses reflection. Rapt design so far (unpublished yet) is more like this;

class MyClass {
/** Runnables.doSomething(MyClass x) is a Runnable
that calls this method. */
@As(Runnable.class) void doSomething() {
/* bla de bla */
void whoCaresWhatName() {
new Thread(Runnables.doSomething(this)).start();
What gets generated from the annotation is
/** In same package as @As annotation target,
class name is plural of annotation element value's
simple name */
final class Runnables {
static Runnable doSomething(final MyClass owner) {
return new Runnable() {
public void run() {
/* Runnables annotated elswhere in this package */
Still working on it, and yes I have mechanisms for known problems in more complex cases.

Basically it just hides the anonymous classes from the source code.

Joined: 2004-10-11

delegates, rapt, etc...

guys, this was just a single example in my proposal. but the proposal itself is about [b]optional type safety for the reflection mechanism[/b].
it is [b]not[/b] about delegates or whatever. it just makes them possible.
it is [b]not[/b] about removing or replacing reflection. it is about improving it.

Joined: 2004-10-11

and I think we [b]need compiler support[/b] for this, that's why I am proposing it here. (otherwise we could live with annotations and code generation and I would not mention it in this forum).

Joined: 2004-10-07

Great idea. I like it. Very simple & handy.

Joined: 2003-06-22

Very good idea, just extend the current syntax. You get compile time checking, and hopefully this eliminates the NoSuchMethodException and SecurityException and the need to deal with them, since its checked at compile time.

I would like to see a javac optimization also where if all you're doing is calling "Foo.class.getName()" it could simply replace it with the full classname, instead of generating the entire class$ method. Every reference to ".class" generates a chunk of bytecode.

Joined: 2003-06-20

In C# this is called delegate. In C and C++ this a pointer to a method.
In Java language the Interfaces tried to be a poor substitute, (defined on a class level).
Sun recognized at least some of the dificulties of using Interfaces, so they introduced anonymous inner classes.
However we need to take this a step further. How many times we see declaration of Interfaces with one method, then implementing classes with a lot of interfaces with one method, because we can not refer to a method definition.
Allowing a reference to a function definition in the language will allow us to express in a lot less lines a lot more (See closures).

Joined: 2003-06-15

> +1
> In C# this is called delegate. In C and C++ this a
> pointer to a method.
> In Java language the Interfaces tried to be a poor
> substitute
-1, Interfaces have turned out to be a very powerful and useful tool. I'd hate to think about what introducing pointers in the language would do though I would agree that closures would be a definite benefit as it is a much more elegant and cleaner solution.

Joined: 2004-10-11

This is just extension for reflection. Nothing more.
We can either (a) let reflection as is and you will have to get Method/Field instance using string literal or we can (b) improve it a little bit and let you obtain the mentioned Method/Field instance in a type-safe way.

remember that you're still using reflection for some reason and you cannot use interfaces or whatever.

Now which one is better? Cls.class.getMethod("doSomething") or st. like Cls.class.doSomething?

Joined: 2005-02-23

+1 from me

Something like:

Method meth = Foo.class.method("myMeth");

The parametric sig on Method is of the form:

By analogy, something like:

Field fld = Foo.class.field("aField");

Here, Field is the form.

Since static methods don't require an object, we could refer to them with something like:

Method<;Foo;> staticFoo = SomeClass.class.method(getFooSingleton)

I think this opens the door to a load of type-safe, reflection-based code. It would certainly make writing certain types of libraries much easier. Generics gave us parameterisation over types. This would be a big step towards parameterisation over code.

Joined: 2003-06-20

You can actually do this with annotation tags and apt.

The apt processor generates a meta class, so if your class is something like this

@Meta public class Foo {
public int a;
public double b;

Apt can generate a meta class like this

public class Foo_Meta {
public Field a = getField("a");
public Field b = getField("b");
private static Field getField(String) { ... }

Joined: 2004-10-11

Yes, but this is workaround, not solution :-)

Joined: 2004-10-11

Yes, Reflection must be made safer and simpler.