Перегрузка с дополнительными факторами

Author: Tatyana Milkina
  1. Расширение примитивных типов
  2. Расширение и boxing
  3. Упаковка и расширение
  4. Расширение и упаковка
  5. Расширение и аргументы переменной длины
  6. Упаковка и аргументы переменной длины
  7. Правила перегрузки методов при использовании расширения, упаковки и аргументов переменной длины

Перегрузка методов усложняется при одновременном использовании следующих факторов:

  • расширение
  • автоупаковка/распаковка
  • аргументы переменной длины

1. Расширение примитивных типов

При расширении примитивных типов используется наименьший возможный вариант из всех методов.

public class EasyOver {
    static void go(int x) {
        System.out.print("int ");
    }

    static void go(long x) {
        System.out.print("long ");
    }

    static void go(double x) {
        System.out.print("double ");
    }

    public static void main(String[] args) {
        byte b = 5;
        short s = 5;
        long l = 5;
        float f = 5.0f;
        go(b);
        go(s);
        go(l);
        go(f);
    }
}

2. Расширение и boxing

Между расширением примитивных типов и boxing всегда выигрывает расширение. Исторически это более старый вид преобразования.

public class AddBoxing {
    public static void go(Integer x) {
        System.out.println("Integer");
    }

    public static void go(long x) {
        System.out.println("long");
    }

    public static void main(String[] args) {
        int i = 5;
        go(i); // какой go() вызовется?
    }
}

3. Упаковка и расширение

Можно упаковать, а потом расширить. Значение типа int может стать Object, через преобразование Integer.

public class BoxAndWiden {
    public static void go(Object o) {
        Byte b2 = (Byte) o;
        System.out.println(b2);
    }

    public static void main(String[] args) {
        byte b = 5;
        go(b); // можно ли преобразовать byte в Object?
    }
}

4. Расширение и упаковка

Нельзя расширить и упаковать. Значение типа byte не может стать Long. Нельзя расширить от одного класса обертки к другой. (IS-A не работает.)

public class WidenAndBox {
    static void go(Long x) {
        System.out.println("Long");
    }

    public static void main(String[] args) {
        byte b = 5;
        // go(b); // нужно расширить до long и упаковать, что невозможно
    }
}

5. Расширение и аргументы переменной длины

Между расширением примитивных типов и var-args всегда проигрывает var-args:

public class AddVarargs {
    public static void go(int x, int y) {
        System.out.println("int,int");
    }

    public static void go(byte... x) {
        System.out.println("byte... ");
    }

    public static void main(String[] args) {
        byte b = 5;
        go(b, b); // какой go() вызовется?
    }
}

6. Упаковка и аргументы переменной длины

Упаковка и var-args совместимы с перегрузкой методов. Var-args всегда проигрывает:

public class BoxOrVararg {
    public static void go(Byte x, Byte y) {
        System.out.println("Byte, Byte");
    }

    public static void go(byte... x) {
        System.out.println("byte... ");
    }

    public static void main(String[] args) {
        byte b = 5;
        go(b, b); // какой go() вызовется?
    }
}

7. Правила перегрузки методов при использовании расширения, упаковки и аргументов переменной длины

Подытожим все правила:

  1. При расширении примитивных типов используется наименьший возможный вариант из всех методов.
  2. Между расширением примитивных типов и упаковкой всегда выигрывает расширение. Исторически это более старый вид преобразования.
  3. Можно упаковать, а потом расширить. (Значение типа int может стать Object, через преобразование Integer.)
  4. Нельзя расширить и упаковать. Значение типа byte не может стать Long. Нельзя расширить от одного класса обертки к другой. (IS-A не работает.)
  5. Можно комбинировать var-args с расширением или упаковкой. var-args всегда проигрывает.
Читайте также:
Комментарии