LINUX.ORG.RU

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

 ,


0

1
List list = null;
ArrayList arrlist = (ArrayList) list;
//ArrayList arrlist = list;

Почему второй код не приемлим? Я понимаю что там сужжение типа, но почему нужно указывать тип в скобках явно? Ведь во втором случае так и так подразумевается приведение к ArrayList

Перемещено tyamur из general

★★

Последнее исправление: tyamur (всего исправлений: 3)

Если не помещать задаваемый вопрос в блок кода, его легче читать и больше шансов получить ответ.

tailgunner ★★★★★
()

Потому что в статической типизации всегда должно быть приведение типов. Оно может быть имплицитным, в случае если ты делаешь list = arrlist, но оно всё равно будет.

mono ★★★★★
()
Ответ на: комментарий от mono

Я понимаю что будет. Но зачем лишние конструкции?
Тоесть почему первый вариант не эквивалентен второму?

tyamur ★★
() автор топика
Ответ на: комментарий от kazufukurou

В Kotlin тоже самое с точки зрения приведения типов. В val arrlist = list переменная arrlist будет иметь тип List<*>. Если ты явно напишешь val arrlist:ArrayList<*> = list, то компилятор потребует кастануть list как и в java.

Автоматический вывод типов ≠ автоматическое кастование.

mono ★★★★★
()
Ответ на: комментарий от tyamur

Потому что статическая типизация. Ты должен явно указывать тип, при приведении. Откуда компилятор может знать легален каст или нет? Делая явное указание типа ты соглашаешься с тем, что знаешь, что делаешь.

В случае если ты приводишь ArrayList к List, например, то там уже включается полиморфизм из ООП, но это упрощение.

mono ★★★★★
()
Последнее исправление: mono (всего исправлений: 1)

то, что справа не должно зависеть от того, что слева

oxo
()
Ответ на: комментарий от mono

Ну ок вот давайте с примитивами. Почему не сделали при сужение, не обязательным писать тип к которуму приводим? Если я написал int i = 0; byte a = i; Тут есть другие варианты кроме byte a = (byte) i;

tyamur ★★
() автор топика
Ответ на: комментарий от tyamur

Потому что примитивы в java живут по своим законам, и это изначально была не очень хорошая идея архитектурно. Ты ещё можешь вспомнить автоматический боксинг/анбоксиг.

С точки зрения примитивов в java так – есть автоматическое приведение примитивов, если возможно.

// можешь
byte a = 10;
int b = b;

// не можешь
int c = 10;
byte d = c;

В Kotlin, к примеру, не так – в любом случае приведение нужно явно писать, потому что примитивы, как и всё остальное, являются объектами:

val a: Byte = 5
val b: Int = a.toInt()

val c: Int = 5
val d: Byte = c.toByte()
mono ★★★★★
()
Последнее исправление: mono (всего исправлений: 1)

Потому что тип List шире, чем ArrayList, и компилятор не может быть уверен что в переменной типа List не находится какой-нибудь LinkedList.

lovesan ★★★
()
Ответ на: комментарий от mono

Почему ты считаешь её не очень хорошей идеей архитектурно? Когда сужаем тип - теряем данные, необходимо вручную обработать потерю данных.

Когда наоборот - данные не теряем. Строгой необходимости в ручной обработке нет.

Deleted
()
Ответ на: комментарий от lovesan

Ну вот поэтому мы и кастуем через скобки. Но почему эти скобки явно писать? Я не про архитектуру ооп. А сам синтаксис.

tyamur ★★
() автор топика
Ответ на: комментарий от Deleted

Я считаю не очень хорошим решением в pure-ООП языке иметь примитивные типы, которые не ООП. Из-за этого проблем получается больше, чем пользы.

mono ★★★★★
()
Ответ на: комментарий от tyamur

затем же, зачем оные скобки при приведении из float/double в int

Потому что неявное приведение типов с потерей/порчей данных, как в JS, или экспешном, это плохо.

lovesan ★★★
()
Ответ на: комментарий от tyamur

Явное привидение типа, компилятору недостаточно информации для выведения типа, только человек понимает чего делает, можно ведь и так:

Collection coll = new HashSet();
ArrayList al = (ArrayList) coll;
al.add("Hello");
Aber ★★★★★
()

Многие люди не любят, когда повсюду неявные преобразования. explicit is better than implicit, или как там...

anonymous
()
Ответ на: комментарий от tyamur

Все равно что передать компилятору хинт - «я знаю чего делаю», ide это обозначит ворнингом, опасный код. В скобках все нормально, другое дело что тип слева во многих языках опускается, его легко вывести, может в будущих версиях java введут var.

Aber ★★★★★
()

Почему второй код не приемлим?

Потому что потом твой код могут/будут читать другие люди. И по итогу я не хочу гадать ошибка у тебя тут или ты и правда хочешь кастануть List.

Хороший анализатор/IDE такие вещи еще подсветит, как хреновый дизайн кода. А компилятор может даже заставит тебя добавить @SafeArgs, но это неточно (а проверять лень). Потому что такие операции очень опасны в плане долгосрочной поддержки кода.

foror ★★★★★
()
Последнее исправление: foror (всего исправлений: 2)
Ответ на: комментарий от Aber

может в будущих версиях java введут var

В марте впилят уже.

foror ★★★★★
()

чтоб било по глазам и ты явно видел, что скорее всего написал «говнокод». +)

vtVitus ★★★★★
()

Потому что там может быть исключение. Исключение в строке a = b это плохо. Примерно по этой причине развиваются языки вроде Kotlin, которые делают так, что в строке a.f() исключения не может быть (в Java оно может быть и это вообще говоря тоже плохо).

Legioner ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.