Почему автобокс Java не распространяется на вызовы методов для автобоксированных типов? - PullRequest
50 голосов
/ 07 августа 2008

Я хочу преобразовать примитив в строку, и я попытался:

myInt.toString();

Это происходит с ошибкой:

int cannot be dereferenced

Теперь я понимаю, что примитивы не являются ссылочными типами (т. Е. Не объектами) и поэтому не могут иметь методы. Тем не менее, Java 5 ввел автобокс и распаковку (а-ля C # ... что мне никогда не нравилось в C #, но это не относится к делу). Таким образом, в случае автобокса я бы ожидал, что вышеприведенное преобразует myInt в Integer, а затем вызовет toString () для этого.

Кроме того, я считаю, что C # разрешает такой вызов, если я не помню неправильно. Является ли это просто прискорбным недостатком спецификации Java для автоматической коробки / распаковки, или для этого есть веская причина?

Ответы [ 8 ]

45 голосов
/ 07 августа 2008

Автобокс / распаковка Java не позволяет вам разыменовать примитив, поэтому ваш компилятор предотвращает это. Ваш компилятор все еще знает myInt как примитив. Есть статья по этому вопросу на jcp.org .

Автобокс в основном полезен при назначении или передаче параметров - позволяет передавать примитив как объект (или наоборот) или назначать примитив объекту (или наоборот).

Так что, к сожалению, вам придется сделать это так: (слава Патрику, я переключился на ваш путь)

Integer.toString(myInt);
27 голосов
/ 07 августа 2008

То же самое, что сказал Джастин, но вы должны сделать это вместо этого:

Integer.toString(myInt);

Сохраняет выделение или два и более удобочитаем.

15 голосов
/ 10 августа 2008

Еще один способ сделать это - использовать:

String.valueOf(myInt);

Этот метод перегружен для каждого типа примитива и Object. Таким образом, вам даже не нужно думать о типе, который вы используете. Реализации метода вызовут соответствующий метод данного типа для вас, например, Integer.toString(myInt).

См. http://java.sun.com/javase/6/docs/api/java/lang/String.html.

9 голосов
/ 07 августа 2008

кажется недостатком спецификация для меня

Есть и другие недостатки, и это тонкая тема. Проверьте это из:

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

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

   public static void main(String[] args){
      int i = 5;
      hello(i);
   }
}

Здесь будет напечатано «long» (я сам не проверял), потому что компилятор выбирает расширение вместо автобокса. Будьте осторожны при использовании автобокса или не используйте его вообще!

5 голосов
/ 24 сентября 2008

Действительный синтаксис, ближайший к вашему примеру:

((Integer) myInt).toString();

Когда компилятор завершает работу, это эквивалентно

Integer.valueOf(myInt).toString();

Однако это не так хорошо, как при обычном использовании, String.valueOf(myInt), потому что, за исключением особых случаев, он создает новый экземпляр Integer, а затем немедленно выбрасывает его, что приводит к большему количеству ненужного мусора. (Небольшой диапазон целых чисел кэшируется, и доступ осуществляется через доступ к массиву.) Возможно, разработчики языка хотели отказаться от такого использования по соображениям производительности.

Изменить: Я был бы признателен, если бы downvoter (ы) прокомментировал, почему это не полезно.

1 голос
/ 31 января 2014

Было бы полезно, если бы Java определила определенные статические методы для работы с примитивными типами и встроила в компилятор некоторый синтаксический сахар, чтобы

5.asInteger

будет эквивалентно

some.magic.stuff.Integer.asInteger(5);

Я не думаю, что такая функция может привести к несовместимости с любым кодом, который компилируется в соответствии с текущими правилами, и во многих случаях она поможет уменьшить синтаксический беспорядок. Если бы Java использовалась для автоматического примитива примитивов, которые были разыменованы, люди могли бы предположить, что он отображал синтаксис разыменования в вызовы статических методов (что и происходит в .NET), и, таким образом, операции, написанные в этой форме, были не более дорогостоящими, чем это было бы эквивалентные статические вызовы методов. Добавление новой языковой функции, которая бы побуждала людей писать плохой код (например, автобокс разыменованных примитивов), не кажется хорошей идеей, хотя использование методов разыменования может быть полезным.

1 голос
/ 23 января 2010

Как уже отмечалось, автоматическая блокировка позволяет упростить некоторый код, но вы не можете притворяться, что примитивы являются сложными типами.

Также интересно: "autoboxing - это хак на уровне компилятора" в Java. Автобокс - это в основном странный ключ, добавленный в Java Проверьте этот пост для более подробной информации о том, как это странно.

1 голос
/ 11 сентября 2008

В C # целые числа не являются ни ссылочными типами, ни их необходимо заключать в квадрат для вызова ToString () . Они считаются объектами в Framework (как ValueType, поэтому они имеют семантику значений). В CLR методы для примитивов вызываются путем «косвенной» загрузки их в стек (ldind).

...