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

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

myInt.toString();

Это терпит неудачу с ошибкой:

int cannot be dereferenced

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

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

7.08.2008 01:05:15
8 ОТВЕТОВ
РЕШЕНИЕ

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

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

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

Integer.toString(myInt);
46
23.05.2012 14:14:20

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

Integer.toString(myInt);

Это сохраняет распределение или два и более читабельно.

27
13.08.2008 01:43:32

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

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

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

9
7.08.2008 07:26:31

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

String.valueOf(myInt);

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

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

15
10.08.2008 07:32:41

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

1
10.09.2008 21:20:19

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

((Integer) myInt).toString();

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

Integer.valueOf(myInt).toString();

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

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

5
26.09.2008 17:05:39
Хотелось бы, чтобы все избиратели-комментаторы прокомментировали, почему что-то проголосовало Я всегда так делаю, если это не очевидно (например, ответ совершенно неправильный или бессмысленный).
Jason Coco 12.11.2008 22:49:59
Вероятно, проголосовали люди, которые просто читали биты кода и думали, что вы защищаете такой код.
Kris 19.03.2009 17:09:04

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

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

1
23.01.2010 14:16:42

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

5.asInteger

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

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

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

1
30.01.2014 23:26:36