Расширяющие и упаковывающие Java примитивы - PullRequest
8 голосов
/ 10 августа 2011

Расширение и упаковка Java-примитивов.

Я знаю, что невозможно расширить класс-оболочку от одного к другому, поскольку они не принадлежат одному и тому же дереву наследования.Почему, однако, невозможно расширить примитив на другой тип примитива и автоматически добавить расширенный примитив?

Учитывая, что аргумент байта может быть передан методу, который ожидает int, почему байт в следующем примере не может быть расширен до int и затем помещен в Integer?* В приведенном выше примере goInt(b) принимается компилятором, а goInteger(b) отклоняется.

Ответы [ 5 ]

6 голосов
/ 10 августа 2011

Короткий ответ

Язык Java поддерживает только некоторый уровень небрежности.

Более длинный ответ

Я считаю, что автобокс был добавлен для поддержки небрежности разработчика.В частности, в таких ситуациях: «Мне нужно Integer как параметр для метода, который я хочу вызвать, но у меня есть int. Почему-то новое Integer (int) никогда не появляется в моей голове. Вместо этого я просто отправлю intи компилятор java сделает для меня новый вызов Integer (). Спасибо группе поддержки по невнимательности java! "

Люди, разрабатывающие автобокс, были готовы поддержать 1 уровень небрежности (int => Integer и обратно), ноне хотели поддерживать автоматическое приведение меньших примитивных типов к большим примитивным типам в сочетании с автоматическим созданием и извлечением из классов-оболочек примитивных типов.Я подозреваю, что матрица решений для этого будет несколько больше, чем матрица решений для текущей схемы автобокса.

4 голосов
/ 10 августа 2011

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

Но вот некоторые обходные пути для ошибки компиляции:

goInteger((int) b);

// these are equivalent
goInteger(((Byte) b).intValue());
goInteger(Byte.valueOf(b).intValue());
1 голос
/ 11 мая 2012

В Java допускается Бокс + Расширение , но не Расширение + Бокс .. Для принятия goInteger требуется первое расширение примитивного типа данных (byte -> int), что нормально, а затем требуется бокс (int -> Integer).Пожалуйста, найдите 5 золотых правил Расширения, Бокса и Варарг:

  1. Примитивное Расширение> Бокс> Вараргс.
  2. Расширение и Бокс (WB) не разрешены.
  3. Бокс и расширение (BW) разрешены.
  4. При перегрузке Widening + vararg и Boxing + vararg могут использоваться только взаимоисключающим образом, т.е. не вместе.не разрешено

Надеюсь, это поможет вам.С уважением, Судипта Деб.

1 голос
/ 11 августа 2011

Если мы допустим слишком много магических преобразований, это будет очень запутанным.

Существующие правила преобразования уже больше, чем люди хотят понять.Даже языковая спецификация ошиблась!Посмотрите на этот забавный пример Приведение Java: неправильный компилятор или спецификация языка, или я ошибаюсь?

0 голосов
/ 08 февраля 2018

Я думаю, что заказ довольно интересный. Я разглядел следующую игровую площадку, чтобы увидеть все возможные комбинации. Это мои функции:

static void doSomeThing(short i) {
    System.out.println("short");
}

static void doSomeThing(short... i) {
    System.out.println("short...");
}

static void doSomeThing(Short i) {
    System.out.println("SHORT");
}

static void doSomeThing(Short... i) {
    System.out.println("SHORT...");
}

static void doSomeThing(long i) {
    System.out.println("long");
}

static void doSomeThing(long... i) {
    System.out.println("long...");
}

static void doSomeThing(Long i) {
    System.out.println("LONG");
}

static void doSomeThing(Long... i) {
    System.out.println("LONG...");
}

static void doSomeThing(int i) {
    System.out.println("int");
}

static void doSomeThing(int... i) {
    System.out.println("int...");
}

static void doSomeThing(Integer i) {
    System.out.println("INTEGER");
}

static void doSomeThing(Integer... i) {
    System.out.println("INTEGER...");
}

static void doSomeThing(Object i) {
    System.out.println("Object");
}

static void doSomeThing(Object... i) {
    System.out.println("Object...");
}

Правила:

 1.Searches for exactly the same type (int -> int)
 2.Widening (int -> long)
 3.Boxing (int-> Integer, it is NEVER possible to implicit box AND wide (int -> Long NOT possible without cast))
 !!Multiple boxing go BEFORE var args!!
 int -> Object will be chosen before int -> int...
 4.Var args (int -> int...)
 5.Widening + var args (int -> long...)
 6.Boxing + var args (int -> Integer...)
 7.Boxing + widening + var args (int -> Object...)

public class Main{

    public static void main(String...args) {
        //primitive int
        int i = 0;
        doSomeThing(i); //int
        //commented out doSomeThing(int i){}
        doSomeThing(i); //long. It is not possible to narrow, so short, short... Short and Short... will NEVER be called when the input is larger than a short.
        //commented out doSomeThing(long i){}
        doSomeThing(i); //INTEGER
        //commented out doSomething(Integer i){}
        doSomeThing(i); //Object. Notice that there can be multiple boxing before moving to var args
                            //Error occured: compiler if confused: can either execute int..., long..., Object... or Integer...
        //Object... and Integer... are commented out, because in the real world int... will be called first
        doSomeThing(i); //int...
        //commented out int...
        doSomeThing(i); //long...
        //commented out long... and uncommented Integer...
        doSomeThing(i); //Integer...
        //commented out Integer... and uncommented Object...
        doSomeThing(i); //Object...

                //Integer
        //Integer
        Integer i = new Integer(0);
        doSomeThing(i); //INTEGER
        //commented out doSomeThing(Integer i)
        doSomeThing(i); //Object
        //commented out doSomeThing(Object i)
        doSomeThing(i); //int
        //commented out doSomeThing(int i)
        doSomeThing(i); //long so NOT int... it goes widening again
        //commented out doSomeThing(long i)
                        //Error occured: compliler refused: not both have int..., long..., Integer... and Object...
        //int... and long... are commented out
        doSomeThing(i); //INTEGER...
        //commented out doSomeThing(Integer... i)
        doSomeThing(i); //Object...
        //commented out doSomeThing(Object... i)
        //uncommented doSomeThing(int... and long...)
        doSomeThing(i); //int...
        //uncommented doSomeThing(int... i)
        doSomeThing(i); //long...
    }
...