Почему автоупаковка Java не распространяется на вызовы методов автоматически упаковываемых типов?

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

myInt.toString();

Это не удается с ошибкой:

int cannot be dereferenced

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

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


person Mike Stone    schedule 07.08.2008    source источник


Ответы (8)


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

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

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

Integer.toString(myInt);
person Justin Standard    schedule 07.08.2008

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

Integer.toString(myInt);

Это экономит выделение или два и более читабельно.

person Patrick    schedule 07.08.2008

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

String.valueOf(myInt);

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

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

person SaM    schedule 10.08.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» (сам не проверял), потому что компилятор предпочитает расширение автоупаковке. Будьте осторожны при использовании автобокса или не используйте его вообще!

person dlinsin    schedule 07.08.2008

Допустимый синтаксис, наиболее близкий к вашему примеру,

((Integer) myInt).toString();

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

Integer.valueOf(myInt).toString();

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

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

person erickson    schedule 24.09.2008
comment
Я бы хотел, чтобы все проголосовавшие прокомментировали, почему за что-то проголосовали. Я всегда так делаю, если это не очевидно (например, ответ совершенно неправильный или бессмысленный). - person Jason Coco; 13.11.2008
comment
Вероятно, проголосовали люди, которые только что прочитали фрагменты кода и подумали, что вы защищаете такой код. - person Kris; 19.03.2009

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

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

person Dan Rosenstark    schedule 23.01.2010

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

5.asInteger

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

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

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

person supercat    schedule 30.01.2014

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

person Mark Cidade    schedule 10.09.2008