Внешний против Супер класса - PullRequest
14 голосов
/ 03 мая 2011

Имеет ли super более высокий приоритет, чем внешний класс?

Предположим, у нас есть три класса:

  1. ClassA
  2. ClassB
  3. Анонимный класс вClassB, который расширяет ClassA

ClassA.java:

public class ClassA {
    protected String var = "A Var";

    public void foo() {
        System.out.println("A foo()");
    }
}

ClassB.java:

public class ClassB {
    private String var = "B Var";

    public void test() {

        new ClassA() {
            public void test() {
                foo();
                System.out.println(var);
            }
        }.test();
    }

    public void foo() {
        System.out.println("B foo()");
    }
}

Когда я вызываю new ClassB().test(), я получаю следующеевывод (что вполне ожидаемо):

A foo()
A Var

Вопрос: определено ли где-то, что внутренний класс (методы и члены) сначала берет из суперкласса, а затем из внешнего класса, или это JVM зависит от реализации компилятора?Я просмотрел JLS (§15.12.3), но не смог найти для этого никакой ссылки, может быть, там указано, но я неправильно понял некоторые термины?

Ответы [ 2 ]

5 голосов
/ 03 мая 2011

См. 6.3.1 Теневые декларации :

Объявление d метода с именем n затеняет объявления любых других методов с именем n , которые находятся в пределах объема в точке, где d встречается в области действия d .

Который может интерпретироваться как "объявление foo (унаследованное от ClassA) затеняет объявление любых других методов с именем foo, которые находятся в пределах объема (ClassB) в точке, где происходит foo, во всем объеме foo. "

Также актуально - раздел 15.12.1 :

15.12.1 Время компиляции Шаг 1: Определить класс или интерфейс для поиска

Первый шаг в обработке вызова метода во время компиляции - выяснить имя вызываемого метода и какой класс или интерфейс проверить для определения методов с таким именем. В зависимости от формы, которая предшествует левой круглой скобке, необходимо рассмотреть несколько случаев:

  • Если форма MethodName , то есть три случая:
    • Если это простое имя, то есть просто Идентификатор , то именем метода является Идентификатор. Если Идентификатор появляется в области видимости (§6.3) видимого объявления метода с этим именем, то должно быть вложение декларации типа, членом которого является этот метод. Пусть T будет самым внутренним объявлением типа. Класс или интерфейс для поиска - T .
    • Если это полное имя формы TypeName.Identifier, то [...]
    • Во всех остальных случаях квалифицированное имя имеет форму FieldName.Identifier; тогда [...]
1 голос
/ 03 мая 2011

Я думаю, вы всегда получите "A var".

Это потому, что ваша реализация метода test() определена для анонимного подкласса A. Я не думаю, что вы можете получить доступ к переменной экземпляра B.var в вашем методе test(), если вы явно не ссылаетесь на внешний класс, используя ClassB.this.var.

...