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

StackOverflow https://stackoverflow.com/questions/4242

  •  08-06-2019
  •  | 
  •  

Вопрос

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

myInt.toString();

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

int cannot be dereferenced

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

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

Это было полезно?

Решение

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

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

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

Integer.toString(myInt);

Другие советы

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

Integer.toString(myInt);

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

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

String.valueOf(myInt);

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

Видишь http://java.sun.com/javase/6/docs/api/java/lang/String.html.

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

Недостатков больше, и это тонкая тема.Проверить это вон:

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

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

((Integer) myInt).toString();

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

Integer.valueOf(myInt).toString();

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

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

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

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

Тоже интересно: "автобоксинг - это взлом на уровне компилятора" на языке Java.Автобоксинг - это, по сути, странный клудж, добавленный в Java.Проверьте этот пост подробнее о том, насколько это странно.

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

5.asInteger

было бы эквивалентно

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top