Смущен компилятором обработки наследования и вызова метода - PullRequest
0 голосов
/ 07 октября 2018

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

Давайте сначала взглянем на следующий код:

Класс A:

public class A {

    public void testMethodA(String a) {
        System.out.println(a);
    }

}

Класс B:

public class B extends A {


}

Main

public class Main {

    public static void main(String[] args) {
        B b = new B();
        b.testMethodA("test");
    }

}

Сейчасдавайте взглянем на то, как я понимаю вещи (пожалуйста, исправьте меня, если я ошибаюсь):

  1. Во время наследования при создании объекта подкласса вы создаете один объект, который получает все поля и методыиз всех суперклассов.Таким образом, поля и методы подклассов не переносятся из суперклассов в подклассы во время компиляции (Источник: Создается ли экземпляр суперкласса, когда мы создаем экземпляр объекта? )
  2. Во время компиляциикомпилятор проверяет, определен ли вызываемый метод, который поддерживает тип аргумента, в объявленном ссылочном типе.Таким образом, в примере: A a = new A(); a.testMethod("test") во время компиляции будет проверяться, определен ли testMethod () в классе A , который может получить String в качестве аргумента,(Источник: Как Java-компилятор выбирает правильные методы и переменные в наследовании )
  3. Когда происходит время выполнения, testMethod () вызывается из фактического объекта, который хранитсяв переменной a , которая не всегда является объектом типа A из-за полиморфизма.

Теперь актуальная проблема:

На основена логике и коде, которые я описал выше, я ожидал Не удается разрешить ошибку метода во время компиляции.Причина в том, что во время компиляции компилятор проверяет класс B , если существует testMethodA (String) .Однако этот метод унаследован от класса A , и, насколько я понимаю, унаследованные методы передаются не подклассам, а скорее объектам подклассов во время выполнения.Поэтому, если testMethodA (String) не существует в классе B во время компиляции, как компилятор все еще может успешно скомпилировать код?Конечно, он не проверяет объект для метода, потому что он еще не создан.

На этот вопрос нет ответа в «возможном ответе», так как эта тема является темой, которую я сам пометил как источник знанийпри описании этой проблемы.

1 Ответ

0 голосов
/ 07 октября 2018

Я думаю, ваше основное недоразумение - в пункте 2.

Во время компиляции компилятор проверяет, определен ли вызываемый метод, который поддерживает тип аргумента, в объявленном ссылочном типе.

Это лучше читать:

Во время компиляции компилятор проверяет, определен ли вызываемый метод, который поддерживает тип аргумента, в объявленном ссылочном типе или одном из его супертипов.или реализованные интерфейсы по всему дереву .

Компилятор знает, что любой экземпляр B (являющийся подклассом A) будет иметь метод testMethodA(), либо тот, который унаследован отсуперкласс A, или переопределенный из подкласса, так что этот метод можно безопасно вызывать.

Вы используете формулировку «pass» для описания наследования полей и методов от суперкласса к подклассу.Эта формулировка звучит мне смущающе, поскольку подразумевает некоторый процесс дублирования, который имеет место лишь частично.Для полей экземпляра это более или менее нормально, так как каждый экземпляр подкласса получит отдельные копии полей суперкласса плюс поля подкласса.Но методы не копируются в экземпляры, они остаются «в» классах, в которых они были определены (экземпляр не занимает больше памяти, если вы добавляете методы).Внутренне Java Runtime поддерживает какую-то таблицу поиска, чтобы найти подходящую версию метода для класса данного экземпляра.

Поэтому я думаю, что формулировка «передать метод объекту подкласса» не соответствует реальному процессу..

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...