Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invoking a method of an anonymous class

Tags:

java

class

I learned the other day that you can do this

new Object() {
    void hello() {
        System.out.println("Hello World!");
    }
}.hello();

This seems really weird to me. Surely the static type of the object created is Object, so there isn't a method hello()? Isn't it almost completely pointless (it isn't possible to invoke hello twice for example).

I have 2 questions about this.

  1. Can somebody point me to the part of the specification that addresses this?
  2. Am I right in thinking that the only way you can invoke hello is immediately like this. What about reflection?

Thanks

like image 815
Paul Boddington Avatar asked Oct 05 '15 23:10

Paul Boddington


People also ask

How do you implement an anonymous class?

Example 1: Anonymous Class Extending a Class In the above example, we have created a class Polygon . It has a single method display() . We then created an anonymous class that extends the class Polygon and overrides the display() method. When we run the program, an object p1 of the anonymous class is created.

Can an anonymous class be instantiated?

Anonymous classes enable you to make your code more concise. They enable you to declare and instantiate a class at the same time. They are like local classes except that they do not have a name. Use them if you need to use a local class only once.

Can an anonymous class have multiple methods?

You can't. The only way to be able to call multiple methods is to assign the anonymous class instance to some variable.


2 Answers

Can somebody point me to the part of the specification that addresses this?

This will mostly be defined in the section concerning Method invocation expressions:

The first step in processing a method invocation at compile time is to figure out the name of the method to be invoked and which class or interface to search for definitions of methods of that name.

For the class or interface to search, there are six cases to consider, depending on the form that precedes the left parenthesis of the MethodInvocation:

  • [...]
  • If the form is Primary . [TypeArguments] Identifier, then let T be the type of the Primary expression. The class or interface to search is T if T is a class or interface type, or the upper bound of T if T is a type variable.

Here, the Primary expression is the class instance creation expression. So the type to search is the anonymous type.

Am I right in thinking that the only way you can invoke hello is immediately like this. What about reflection?

As long as an expression evaluates to the anonymous type T, whether through direct access like you have, or through generics, you have access (regular access rules apply) to the members that T declares. This isn't limited to methods. You can access fields or types, though it's not as useful for types. For example,

Object var = new Object() {
    class Nested {
    }
}.new Nested();

Since there's no way to refer to the nested type without the enclosing type, you can't declare a variable of that nested type. The usefulness declines very quickly. (Presumably, that's also why you can't have a static nested type within this anonymous class.)

Reflection also exposes this method. The generated anonymous class contains this method, so you can retrieve it and invoke it. The process is the same. The fact that the instance is from an anonymous class doesn't matter. The same strategy as presented in How do I invoke a Java method when given the method name as a string? applies.

For example,

Object ref = new Object() {
    public void method() {
        System.out.println("hidden");
    }
};
Class<?> anonymousClass = ref.getClass();
Method method = anonymousClass.getMethod("method");
method.invoke(ref, new Object[0]);

Don't ever write code like this.

like image 52
Sotirios Delimanolis Avatar answered Oct 08 '22 12:10

Sotirios Delimanolis


As posted, there isn't a way to get the anonymous methods from the Object instance. And, it makes Anonymous classes look pointless. But, you could (and I usually would) use it to implement an interface. Something like,

static interface Hello {
    void hello();
}
public static void main(String[] args) {
    Hello o = new Hello() {
        public void hello() {
            System.out.println("Hello World!");
        }
    };
    o.hello();
}

Or, more commonly, for call-backs with JFC/Swing and ActionListener.

like image 12
Elliott Frisch Avatar answered Oct 08 '22 11:10

Elliott Frisch