Будь-яка ідея, чому мені потрібно тут подати ціле число, яке буквально (int)?


122

У наступному прикладі

int i = -128;
Integer i2 = (Integer) i; // compiles

Integer i3 = (Integer) -128; /*** Doesn't compile ***/

Integer i4 = (Integer) (int) -128; // compiles
Integer i4 = -128; // compiles
Integer i5 = (int) -128; // compiles
Integer i6 = (Integer) (-128); // compiles
Integer i7 = (Integer) 0-128; // compiles

Я не можу кинути -128з , (Integer)але я можу кинути (int) -128.

Я завжди думав, що -128це intтип, і кастинг з ним (int)повинен бути зайвим.

Помилка в рядку з i3є

cannot find symbol variable Integer

Я спробував це за допомогою оновлення Java 6 та оновлення Java 7.

EDIT: Ви маєте таку саму поведінку, +128а не -128. Схоже, це плутанина між одинарними та бінарними операторами.


5
який ваш компілятор? Integer i = -128;це, однак, має складатись.
bestsss

wierd, Integer i3 = (Integer) (-128);хоча поступається .
Фуад

2
@ Eng.Fouad, Пітер, одинарні символи (+ -) мають право на ліву асоціативність і плюс, мінус - зліва направо. Ефект від -128 буде таким самим, як +128, а поставлення 0 попереду має фіксувати, тобто 0-128 або 0 + 128. (Не можу перевірити атм, але я
сподіваюся, що

Гарне питання! Я особисто хотів би побачити JLS-посилання на дозвіл унарних / бінарних операторів, і коли трансляція трактується як вираз. В іншому випадку можливо, що інші компілятори не вважають це помилкою!
Bringer128

1
Також FYI помилка, яку я отримую в своєму IDE, є Expression expectedде Integer.
Bringer128

Відповіді:


151

Компілятор намагається відняти 128від (Integer)замість того, -128щоб передати Integer. Додати, ()щоб виправити це

Integer i3 = (Integer) -128; // doesn't compile
Integer i3 = (Integer) (-128); // compiles

За словами BoltClock в коментарях, акторський склад intпрацює як задумано, оскільки це зарезервоване слово і тому його не можна інтерпретувати як ідентифікатор, що для мене є сенсом.

І Bringer128 знайшов посилання JLS 15.16 .

 CastExpression:
    (PrimitiveType Dims opt ) UnaryExpression
    (ReferenceType) UnaryExpressionNotPlusMinus

Як бачимо, для введення примітивного типу потрібне будь-яке UnaryExpression, тоді як для лиття до еталонного типу потрібне: a UnaryExpressionNotPlusMinus. Вони визначені безпосередньо перед CastExpression на JLS 15.15 .


31
Я думаю, що intце ключове слово на Java, але Integerце не так. Оскільки intце ключове слово, ви не можете використовувати його як ідентифікатор для змінної чи класу, залишаючи єдину можливість, щоб він був набором тексту. Це пояснило б це.
BoltClock

@BoltClock Включив ваш коментар у відповідь.
Єнс Шодер

3
Щоб зробити це ще більш зоряною відповіддю, ви хочете додати моє посилання на JLS?
Bringer128

3
Цікавою (для мене) зморшкою в цьому питанні є те, як ми вирішуємо аналогічну задачу в C #, яка також має неоднозначність у граматиці між "круглим виразом як операнд до двійкового оператора віднімання" та "оператором кинутих, де правий операнд лиття - вираз унарного мінусу ". Дивіться розділ 7.7.6 специфікації C # для детального опису евристики, яку ми використовуємо, щоб постаратися вирішити двозначність.
Ерік Ліпперт

1
@BillK Чому ти це кажеш? Специфікація C # не стосується перевантаження оператора в розділі 7.7.6, тому для них це не було проблемою.
Bringer128

48

Я знайшов посилання на JLS. 15.16 .

 CastExpression:
    (PrimitiveType Dims opt ) UnaryExpression
    (ReferenceType) UnaryExpressionNotPlusMinus

Як бачимо, для введення примітивного типу потрібне будь-яке UnaryExpression, тоді як для лиття до еталонного типу потрібне: a UnaryExpressionNotPlusMinus. Вони визначені безпосередньо перед CastExpression на JLS 15.15 .

Вам потрібно або змінити склад на примітивний тип:

... (int) -128;

Або ви можете змінити вираз праворуч на команду на не-плюс-мінус одинарний вираз:

... (Integer) (-128);  // Either
... (Integer) 0 - 128; // Or

12

Компілятор інтерпретує -оператор як два аргументи мінус, тобто він намагається відняти 128 з якогось іншого числа, названого Integer, але такої змінної в області застосування немає.

Це компілює:

Integer i3 = (Integer) (-128)

Ви можете додати коментар, чому це (int)має значення.
Пітер Лорі

1
Це пов'язано з автобоксингом, ні?
Брайан Роуч

9

Це може стосуватися синтаксичного розбору. Зауважте це

Integer i4 = (Integer) (-128); 

працює просто чудово.

Взагалі, вам не слід кидати в клас Integer. Це передбачає щось, що називається автобокс, і може спричинити деякі тонкі помилки у вашому коді. Кращий метод робити те, що ви хочете, це:

Integer i6 = Integer.valueOf(-128)

1
литий до Integer - це саме синтетичний цукор для valueOf.
bestsss

4
так, але іноді синтетичний цукор виходить з ладу тонко. Мені було важко відслідковувати винятки з нульових покажчиків у великих програмах через автоматичний бокс. Ми пішли так само, як трактувати автобокс як помилки, щоб зберегти головний біль у майбутньому. Магія приємна, але коли вона провалюється, болять голови. Я вважаю, що краще бути явним і врятувати себе від головних болів.
Кристіян Цибульський

NPE - це b1tch w / outboxing, правда. Такі випадки, як for (int i in Collection<Integer>)b / c NPE, знаходяться в абсолютно несподіваному місці. Я фактично не використовую Integer w / autoboxing, оскільки діапазон кешу невеликий (хоча він може бути збільшений з опцією XX /), але для класу, який називається IntegerProvider (починаючи з 1.1), можна робити ті самі речі. Використання картки (будь-якої з java.util) Integer-> Все, як правило, є враженням від продуктивності, якщо не використовується для тривіальних випадків і майже завжди є краще рішення.
bestsss

Передача int до Integer ніколи не може спричинити жодних помилок, крім переповнення купи. Однак зворотне не вірно.
Інго

@MattBall, я зовсім не розумію, синтетичний цукор використовується широко: eggcorns.lascribe.net/forum/viewtopic.php?id=4400 і синтетичні звуки мені краще.
bestsss

9

Він аналізує його як Integer <minus operator> 128і не знаходить змінної Integer. Вам потрібно загорнути -128в дужки:

Integer i3 = (Integer) (-128);  // compiles

Я присудив +1 до всіх інших відповідей, тому що вони теж всі вірні :)
Богем


6

Рядок 3 інтерпретується так, що ви намагаєтесь вивести 128 з виразу в дужках, а вираз у дужках - не та вираз типу int (трактує оператор '-' як '-'). Якщо ви зміните вираз на:

Integer i3 = (Integer) (-128);

тоді компілятор зрозуміє «-» - одинарний мінус, який вказує на негативне ціле число.


3

Компілятор C # має таку саму поведінку. Це дає кращу підказку, чому він не може компілювати:

Щоб присвоїти негативне значення, ви повинні вкласти це значення в круглі дужки

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.