Почему объявление типа важно в статически типизированном языке?

Я пытаюсь понять преимущества статической типизации языка программирования, и поэтому мне интересно, почему нам нужно включать тип в объявление? Служит ли это какой-либо цели, а не для явного определения типа? Если это так, я не вижу в этом смысла. Я понимаю, что статическая типизация позволяет проверять тип во время компиляции, но если мы не укажем явное объявление типа, не сможет ли Java вывести тип во время компиляции?

Например, допустим, у нас есть в Java:

myClass test = new myClass();

Разве здесь не нужно объявление типа? Если я не ошибаюсь, это статическая привязка, и Java должна знать test имеет тип myClass без явного объявления типа даже во время компиляции.

Ответ на возможное дублирование: это вопрос не относительно статического и динамического типов, а скорее о выводе типа в статически типизированных языках, как объясняется в принятом ответе.


person rb612    schedule 25.12.2015    source источник
comment
что, если у вас есть class B extends A и A a = new B()? Как компилятор должен определить тип a?   -  person gefei    schedule 25.12.2015
comment
@femtoRgon Этот вопрос касается вывода типов в статически типизированных языках, о динамически типизированных языках.   -  person yshavit    schedule 25.12.2015
comment
Извините, * не о языках с динамической типизацией. :)   -  person yshavit    schedule 25.12.2015


Ответы (2)


Существуют языки со статической типизацией, которые позволяют опускать объявление типа. Это называется выводом типа. Недостатком является то, что его сложнее спроектировать (для разработчиков языка), сложнее реализовать (для разработчиков компилятора) и сложнее понять, когда что-то пойдет не так (для программистов). Проблема с последним из них заключается в том, что, если выводятся многие (или все) ваши типы, компилятор не может сказать вам гораздо больше, чем «типы не все согласованы» - часто с помощью загадочного сообщения.

В таком тривиальном случае, как тот, который вы цитируете, да, это легко. Но чем дальше от тривиального случая, тем сложнее становится система.

Java действительно выполняет некоторый вывод типов в очень ограниченных формах. Например, в этом фрагменте:

List<String> emptyStrings = Collections.emptyList();

... компилятор сделал вывод, что вызов метода emptyList возвращает List<String>, а не только List<T>, где тип T не указан. Непредвиденная версия этой строки (которая также является допустимой для Java):

List<String> emptyStrings = Collections.<String> emptyList();
person yshavit    schedule 25.12.2015
comment
Это именно то, что мне было интересно, спасибо !! Итак, теперь у меня есть еще один похожий вопрос: выделяет ли объявленный тип другой объем памяти на таком языке, как Java? Подобно A a; vs B b;, если A имеет 100 переменных экземпляра, а B имеет 0, скажем, будет ли это иметь значение во время объявления, или это происходит только при создании экземпляра? А как насчет примитивов? - person rb612; 25.12.2015
comment
@ rb612 Нет никакой разницы; память определяется исключительно объектом, а не ссылкой на него. Ссылка имеет фиксированный размер, поэтому все три ссылки String a, List<String> b и ArrayList<HashMap<String, String>> c будут занимать одно и то же пространство (и на самом деле JVM даже не узнает, что это что-то иное, кроме ссылки на какой-то объект). Примитивы вообще не имеют полиморфизма, но имеют разные размеры (байт - это всего один байт, короткий - два байта и т. Д.). - person yshavit; 25.12.2015
comment
это здорово, спасибо! так что, по сути, явное объявление типа в статически типизированном языке, таком как Java, служит только для предотвращения вывода типа и не имеет ничего общего с распределением памяти? - person rb612; 25.12.2015

Это необходимо. У вас может быть наследование там, где необходимы типы.

Например:

Building build1 = new House();
Building build2 = new SkyScraper();

То же самое и в полиморфизме.

Затем вы можете, например, собрать все Building в массив. Если будет один House и один SkyScraper, вы не сможете этого сделать.

person maskacovnik    schedule 25.12.2015
comment
Хорошо, я это вижу. Но если вы хотите, чтобы build1 был просто домом, как House build1 = new House();, не могли бы вы отбросить первый дом и просто написать build1 = new House();? - person rb612; 25.12.2015
comment
Спасибо. Я думаю, что мой вопрос сформулирован неправильно и больше связан с выводом типа, что объясняется в ответе @yshavit. - person rb612; 25.12.2015