1
public class Test {
    public static void main(String[] args) {
        DemoAbstractClass abstractClass = new DemoAbstractClass() {
            private String val;

            @Override
            public void runner() {
                val = "test";
                System.out.println(val);
                this.run();
            }

            public String getVal() {
                return val;
            }
        };

        abstractClass.runner();

        /**
         * I want to access getVal method here
         */
    }
}

abstract class DemoAbstractClass {
    public void run() {
        System.out.println("running");
    }

    public abstract void runner();
}

Here, I'm declaring an abstract class DemoAbstractClass. I can obviously create a new class that extends this class and add this method to it. But, I would prefer not doing that in my scenario. Is there any other way to access getVal method in above code??

Kush
  • 148
  • 11
  • 1
    In addition to the answers below, also see http://stackoverflow.com/questions/319765/accessing-inner-anonymous-class-members – cklab Jun 14 '12 at 15:45

5 Answers5

6

You can't. You need to make a proper (non-anomous) class out of it. Make it an inner private class if you want to limit its scope.

Alternatively, you could use a StringBuffer and share a referense to it between the methods. Not extremely clean however.

Related question:

Community
  • 1
  • 1
aioobe
  • 413,195
  • 112
  • 811
  • 826
  • "private inner class" seems to be the final answer for the problem.Using StringBuilder will be a bad game with language designers. ;) – Kush Jun 14 '12 at 16:28
  • Another doubt.. What would be better, a private inner class or a local class (as given in an answer of link suggested by you). – Kush Jun 14 '12 at 16:33
  • 1
    A local would have an even narrower scope, so if possible, go for that. – aioobe Jun 14 '12 at 17:21
1

Short of using reflection, you cannot as you have no access to the concrete type of the object to be able to bind the methodcall to

If you don want to do something like this in a sane manner, declare a named class and use that as the type of abstractClass

Attila
  • 28,265
  • 3
  • 46
  • 55
1

Unfortunately, if you cannot name the type, you cannot access the methods at the language level.

What you can do, though, is use the reflection API to get a Method object and invoke it on this object.

This, however, is pretty slow. A private class or private interface would be much faster.

Sam
  • 2,939
  • 19
  • 17
  • Agreed!! Reflection will be a burden here. private class/interface (or a local class) is the perfect solution here. – Kush Jun 14 '12 at 16:44
1

I can obviously create a new class that extends this class and add this method to it.

You've already done this; the end result was an anonymous inner class: new DemoAbstractClass() { ... }; If you just moved that declaration into its own class -- you can even make it a private class -- you can access getVal.

Per your example above:

public class Test {
    public static void main(String[] args) {
        DemoClass abstractClass = new DemoClass();

        abstractClass.runner();

        /**
         * I want to access getVal method here
         */
        abstractClass.getVal(); // can do this here now
    }

    private class DemoClass extends DemoAbstractClass {

            private String val;

            @Override
            public void runner() {
                val = "test";
                System.out.println(val);
                this.run();
            }

            public String getVal() {
                return val;
            }
        }
    }
}
Roddy of the Frozen Peas
  • 14,380
  • 9
  • 49
  • 99
1

Another option is to make a StringBuilder a member of the main method and use the closure nature of anonymous inner methods:

public static void main(String[] args) {
    final StringBuilder value = new StringBuilder();
    DemoAbstractClass abstractClass = new DemoAbstractClass() {
        @Override
        public void runner() {
            value.append( "test" );
            System.out.println(val);
            this.run();
        }
    };

    abstractClass.runner();

    // use val here...
    String val = value.toString();
}
Lucas
  • 14,227
  • 9
  • 74
  • 124
  • I liked this answer but it is more of an "alternative arrangement". What if your anonymous object contains a member other than String? – Kush Jun 14 '12 at 16:41
  • I never use member/instance variables in anonymous classes. I always use variables defined outside of the class definition and rely on the closure to access them. It will work for any type of variable as long as it is mutable. It must be mutable because the reference must be final. In other words, you can only edit the value of the referred to variable, not the reference itself, which is why i used StringBuilder and not String. – Lucas Jun 14 '12 at 17:47
  • i also opted a similar approach, using a final list to hold my object data, but I was asked to look up for a better approach.. – Kush Jun 14 '12 at 20:21