3

Is it possible to do something like this (I use initializer blocks to shorten the example)

new A() {{
  new B() {{
    method(outer.this);
  }}
}}

Where I supply the this of the outer object as a parameter to the method call within the second anonymous class? I cannot use A.this, this gives a compile error.

Note: the given code does not compile, it should only illustrate what I'm trying to achieve.

Edit: example that lies closer to the actual use case:

public class Outer {

  public SomeBean createBean() {
    return new SomeBean() {

      private final Object reference = new SomeClass() {

        @Override
        public void notify() {
          Outer.callback(/*what goes here???*/);
        }
      };

      //Methods...
    };
  }

  public static void callback(final SomeBean bean) {
    // do stuff with bean
  }
}

And the compile error I get is just that I'm not providing the correct argument to callback, as I don't know how to reference the SomeBean subclass...

4
  • 1
    does it work when you put the code inside a method? Inside the initializers you are trying to reference an object which isn't created yet. Commented Jan 2, 2012 at 16:15
  • The answer depends on your actual usecase. Commented Jan 2, 2012 at 16:20
  • 1
    I don't recommend unsafe publication of this. Also, can you please show us the compiler error? Commented Jan 2, 2012 at 16:20
  • I elaborated the problem a bit more in the original question. Commented Jan 3, 2012 at 18:30

3 Answers 3

2

If you really must, I guess this should work.

new A() {
    {
        new B() {{
            method();
        }};
    }
    private void method() {
        method(this);
    }
}

(Historical note: With -target 1.3 or earlier, this should NPE.)

If you don't need the exact type of the A inner class.

new A() {
    {
        new B() {{
            method(a);
        }};
    }
    private A a() {
        return this;
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

The first suggestion is along the lines of what I've currently done, it works, but I was wondering whether it is possible to directly call the needed method instead of providing a "proxy-method", I'll keep this solution if the direct call isn't possible though.
I'll accept this one as it is the solution I also came up with myself and I don't think there really is a better way.
1

@TomHawtin 's answer is good, mine is quite similar. I would do this:

new A() {
    private final A anon = this;
    /*init*/ {
        new B() {
            /*init*/ {
                method(anon);
            }
        }
    }
}

This will probably give you slightly better performance than calling a method to get your A instance. The main benefit is IMO this is easier to read/maintain.

Edit: @Tomas 's answer is also very similar, but required that you keep a reference to your new A object in the outer-outer class, where it might not be needed.

In light of op's edit:

public SomeBean createBean() {
    SomeBean myBean = new SomeBean() {
        private final Object reference = new SomeClass() {
            @Override
            public void notify() {
                Outer.callback(/*what goes here???*/);
            }
        };
        //Methods...
    };
    return myBean;
}

FYI obj.notify() is a final method in Object, you can't override it. JavaDoc here

3 Comments

I'm not sure what you mean by your comment. / The field solution is slightly more concise, although it does add an extra field, probably giving slightly worse performance. I think the private field will cause a synthetic accessor method to be generated.
I can't claim any intimate knowledge of the compiler, I was under the impression that field-access was slightly faster than trivial method invokation. I'll edit my answer.
notify was just an example name, I didn't think of the method in Object while typing it.
0

Consider refactoring your code, as the code you are proposing doesn't seem too logical, and for sure not easy to handle or mantain. You could do a pretty similar structure (subclassing two different types and using one from another) with something like this:

//declaring a variable as final enables accessing it from the B subtype if declared at the same scope (method)
final A myA=new A() {
   //personalized content for type A
};
//then, declare the B subtype, using the final myA var as you need, at the constructor 
B myB=new B() {{
   method(myA);
}};

This, in case you need to overwrtie both classes, as you exposed. Maybe a little rethink could save you from these anonymous classes (or at least, from some of them).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.