5
public class Solution {
    private String name;

    Solution(String name) {
        this.name = name;
    }

    private String getName() {
        return name;
    }

    private void sout() 
    {
        new Solution("sout")
        {
            void printName() 
            {
                System.out.println(getName());
            }
        }.printName();
    }

    public static void main(String[] args) {
        new Solution("main").sout();
    }
}

The method of an anonymous class behaves unexpectedly. How to make method sout to print "sout", now it prints "main"?

kurumkan
  • 2,635
  • 3
  • 31
  • 55
  • 1
    You should always provide more info than "behaves unexpectedly". Study the help center to get an idea what you should putting in your question. – GhostCat Mar 19 '16 at 21:48
  • 2
    I suspect this has to do with the fact `getName` is private, and the anonymous class cannot access its superclass's private methods, but it can access its enclosing class's private methods... and it's complicated by the fact that those two are the same class. – user253751 Mar 19 '16 at 21:50
  • Where did you find this code? It's really weird. You're also doing this: http://stackoverflow.com/questions/32959680/invoking-a-method-of-an-anonymous-class – Paul Boddington Mar 19 '16 at 21:54
  • @immibis you are right. The problem is `private`. @Artur Arsalanov why are you making a getter method private, what is the point? – rdonuk Mar 19 '16 at 21:59
  • yes it seems that the problem in private. Thank you. Solved. – kurumkan Mar 19 '16 at 22:09

2 Answers2

3

The problem is that String getName() is private.

What this means is that it is inaccessible to methods of derived classes.

However, the anonymous derived class is not only derived, but it is also an inner class. As such, the class has access to private members of the outer class. That is why main gets printed, not sout.

All you need to do to make this work is to make the method non-private: default access, protected, or public would work fine.

Demo.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • @ArturArsalanov if you use `this.getName()` while keeping `getName()` private, the code would not compile ([demo](http://ideone.com/pvtUpE)). – Sergey Kalinichenko Mar 19 '16 at 22:04
  • but if not private can run with this.getName(); but if just getName without this -still prints "main" – kurumkan Mar 19 '16 at 22:11
  • @ArturArsalanov Please see the demo at the bottom of the answer. Its only difference from the code that you posted is removed `private` in front of `getName`. This is sufficient, because when both an outer context and a derived context supply a method, the inherited method "wins". – Sergey Kalinichenko Mar 19 '16 at 22:17
1

You would use

System.out.println(super.getName());

You have an anonymous inner class Solution inside a Solution, so getName() implicitly refers to the outer instance because the method is private.

You could also make getName protected instead of private.

The explanation is a bit ornery. getName is visible to the anonymous class because of scope, but since it's private, the anonymous class can't normally refer to getName on itself because it's actually a subclass.

The really strange case of this is when you have a static nested subclass:

class Example {
    private void sayHello() {
        System.out.println();
    }

    static class Subclass extends Example {
        Subclass() {
            // This is a compiler error
            // because it tries to call sayHello()
            // on an enclosing instance which doesn't
            // exist (as if Subclass is an inner class).
            sayHello();
        }
    }
}

I walked through the specification in my answer to a question asking about the static case, which also explains why "main" gets printed here: https://stackoverflow.com/a/28971617/2891664.

Community
  • 1
  • 1
Radiodef
  • 37,180
  • 14
  • 90
  • 125