Compilation error on non-static element reference

Asked

Viewed 75 times

4

public abstract class Teste {
    public static final Teste IMPLEMENTACAO_1 = new Teste() {
        @Override
        public void executar() {
            teste1();
        }
    };

    public static final Teste IMPLEMENTACAO_2 = new Teste() {
        @Override
        public void executar() {
            teste2();
        }
    };

    public static final Teste IMPLEMENTACAO_3 = new Teste() {
        @Override
        public void executar() {
            // Non-static method 'teste3()' cannot be referenced from a static context
            teste3();
        }
    };

    public abstract void executar();

    public void teste1() {}

    protected void teste2() {}

    private void teste3() {}
}

The above class, in IMPLEMENTACAO_3, is released a compilation error saying:

non-static element cannot be referenced by a static element

However, the three implementations use essentially the same code, differing only by the access modifier of the functions that are called.

Why only the private function generates this error? What does the access modifier influence this? In my opinion the three functions should give problem.

  • 2

    The error displayed is confusing because "this" is implied. If you modify all test calls to contain "this." , the actual error appears: "The method teste3() from the type Test is not Visible", which is much less confusing.

  • So, for me it was not very clear why is giving the error that gives. I should give that the method is not visible.

  • From what I understand, it’s not visible at all. Because an "invisible class" is created somewhere, and because it is outside the Test class, it cannot access the private method.

  • @Piovezan Hunch: this seems to be a corner case strange, I don’t know. Anyway, if the method is private static void teste3(), then the code compiles (that’s because to be static the visibility rules in the subclasses are no longer valid), so in the above code the compiler should consider that you tried to call a method that should be static but is not, since it is in a static context.

  • On the other hand, if you try to create a subclass (instead of a static field), then you get the error of "cannot find Symbol" as expected: https://repl.it/repls/AlertCoralMethods#Test.java - then my guess is that the compiler first tries to check the static context, and then check the visibility rules. Unless, of course, you explicitly called for this.teste3(), as already said above, because there it makes clear that does not want to call the static method, and there gives the error that the method is not visible.

  • @hkotsubo Ah, now I understand what it means to "contain this. on calls from teste()". I had not understood, I thought it was to add in the parameter. And thanks for the explanation :)

  • @Piovezan If you want, you can look in the source code of the compiler to be sure: http://openjdk.java.net/groups/compiler/ :-) (no, I didn’t look)

  • 1

    @hkotsubo Thanks for the tip, but I won’t look no. Good to know it exists, but I’d rather not commit these corner cases. If it is for the daughter class to see, it should not be private. It is better not to abuse of inheritance, as you well know.

Show 3 more comments

1 answer

4


At the moment the class is instantiating Teste in the static field need to create the implementation of the abstract method and this is what it does correctly, after all abstract classes cannot be instantiated directly. So what happens when you create this instance?

There is a class heritage Teste for a temporary (anonymous) class to allow the extension of the class and method implementation that was not implemented. It’s kind of weird, but that’s how it works, in practice it’s not instantiating well Teste and yes a class derived from it, although in the code this is not visible.

It’s also weird because it’s instantiated within the class itself, but static members are like that, they’re there almost by chance, it could be in other places, they don’t belong to the object, they don’t see the members of the object directly. Think of him as somewhere else because it’s the same.

If you want to know more read Static reference giving error while accessing and What is the use of a static or final variable in java?.

So the moment you call teste1() everything works because you have access to a public method from anywhere in the application, as long as an object of this type is instantiated it can be called, so it is with all public members.

It’s okay to call teste2() which is protected. This method cannot be called from anywhere, it can only be called from a class that is derived from the base class, i.e., it has to be derived from Teste. And in fact this is what happens as I explained in the second paragraph, you have there an invisible class derived from Teste.

Already teste3() cannot be called because it is private, i.e., it can only be called within an object of the class Teste. You can’t even call a derivative of it that is the case you created there. And gives the error.

You may be thinking, "but you’re inside Teste". It’s inside the class, not the object, static members are not part of the object, by chance it’s all together, but it’s like something separate, so it doesn’t work.

Read What is the difference between a class and an object?. Also What is the difference between class instance variables, automatic (local) and static duration?.

If you believe it should work you should justify why it should. If you can’t justify it then you can’t. Nothing should work without justification.

The example is good and helps in learning many people, pity that the site has no longer attracted more people who want to know it, but the question is a boost.

  • I didn’t know about this part of creating an "invisible class," although I figured there’d be something secret underneath the covers... Thanks a lot for the explanation, it helped a lot. If it’s not too much to ask, could you give me a tip on how to make this class work properly? I need the function to be private, and from what I see, the only way to do that is to make it static. Is that correct, or is there some other way?

  • 3

    In this one there is no way because it is artificial, in a real could have a different solution that can only be thought of with the real case. Being private or static are different things.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.