Почему мой метод, аргументированный примитивным типом, не переопределяет метод суперкласса, аргументированный по типу обертки? - PullRequest
0 голосов
/ 07 сентября 2018
public class WrapperClasses{
    void overloadedMethod(Number N){
        System.out.println("Number Class Type");
    }

    void overloadedMethod(Double D){
        System.out.println("Double Wrapper Class Type");
    }

    void overloadedMethod(Long L){
        System.out.println("Long Wrapper Class Type");
    }

    public static void main(String[] args){
        int i = 21;
        WrapperClasses wr = new WrapperClasses();

        //wr.overloadedMethod(i);
    }
}

class mine extends WrapperClasses{
    void overloadedMethod(int N){
        System.out.println("Integer Class Type");
    }
    public static void main(String[] args){
        int i = 21;
        WrapperClasses wr = new mine();

        wr.overloadedMethod(i);
    }
}

Это печатает Number Class Type.

Я понимаю правила перегрузки метода класса-оболочки:

  1. Если вы передаете примитивный тип данных в качестве аргумента методу вызов, компилятор сначала проверяет определение метода, который принимает тот же тип данных, что и в качестве аргумента.
  2. Если такого метода не существует, он проверяет метод определение, которое принимает примитивный тип данных большего размера, чем переданный тип данных. То есть, он пытается выполнить автоматическое расширение переданный тип данных.
  3. Если преобразование с автоматическим расширением невозможно, выполняется проверка определение метода, которое принимает соответствующий тип класса-оболочки как аргумент. То есть он пытается выполнить автоматическое преобразование в бокс.
  4. Если такого метода не существует, то он проверяет метод, который принимает в качестве аргумента тип суперкласса (число или тип объекта).
  5. Если такого метода также не существует, то компилятор выдает ошибка времени компиляции.

Согласно правилу 1 должно быть напечатано Integer Class Type. Что мне здесь не хватает?

Ответы [ 3 ]

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

На уровне спецификации языка это происходит потому, что методы с параметрами, которые отличаются как примитивные и упакованные примитивные типы, не рассматриваются как эквивалентный переопределению . (Причудливый способ сказать: «Они просто не делают этого, потому что так сказано в спецификации языка»).

Но по логике они также не должны, по крайней мере, в случае параметра int в подклассе, "переопределяющего" упакованный параметр в суперклассе.

Согласно принципу подстановки Лискова, методы в подклассах должны принимать не менее всех параметров, принятых методом в суперклассе.

Если метод суперкласса принимает обернутый класс, он может принять null. Если бы методу подкласса было разрешено только принимать int, он не мог бы принимать ноль, поэтому он не мог бы быть заменяемым.

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

Полиморфизм выполняется JVM во время выполнения.Чтобы это работало, оба метода должны иметь одну и ту же сигнатуру во время выполнения.

В случае ковариантных возвращаемых типов компилятор генерирует методы моста, чтобы это произошло, однако для языка Java Spec не требуетсятакой метод моста для оболочек против примитивов.

Существует ряд причин, по которым это может быть, однако наиболее вероятной является обратная совместимость.Java 1.0 этого не делала, и хотя автобокс был добавлен более десяти лет спустя, это не позволило взломать старый код.т.е. обертка и примитивы перегружены, а не перегружены, поэтому они не могут сейчас.

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

Разрешение перегрузки метода определяется во время компиляции на основе типа времени компиляции переменной, содержащей ссылку на экземпляр, для которого вы вызываете метод.

void overloadedMethod(int N) определено только в подклассе mine. Поэтому при вызове метода для ссылки, тип которой является базовым классом WrapperClasses, только методы базового класса могут рассматриваться для разрешения перегрузки.

Аргумент int, который вы передаете методу, не соответствует ни одному из 3 методов базового класса, но после того, как он упакован в Integer, он соответствует методу void overloadedMethod(Number N).

Если вы измените свой код на

    int i = 21;
    mine wr = new mine();

    wr.overloadedMethod(i);

будет выполнено void overloadedMethod(int N).

...