Выбор первого языка программирования — обзор Java
- 16471
- 39
- 10 марта, 2016
На сегодняшний день самым популярным языком программирования является Java. При этом он продолжает набирать обороты.
Попытаемся разобраться почему Java выбирается в современных проектах в качестве основного языка программирования.
Си-подобный синтаксис*
В то время, когда создавался язык Java, самым популярным языком программирования был C++. Для того, чтобы «переманить» программистов на новый Java было принято решение сделать его максимально похожим на С++, взяв по возможности лучшее от него.
Java и С++ не единственные, кто обладает подобным синтаксисом. Прародителем C++ был язык C (Си), потому все языки использующие подобный синтаксис называются си-подобными, и их существует великое множество (Wikipedia: C-family).
Таким образом если вы уже знакомы хотя бы с одним из этих языков, то обилие точек, фигурных и круглых скобок в Java покажутся вам чем-то давно знакомым и привычным. С другой стороны изучив синтаксис Java вам будет гораздо проще постигнуть и остальные языки этого семейства.
Плюсы:
- популярен
Минусы:
- требует привыкания
* Синтаксис — это набор правил, которым должен соответствовать текст программы. По-простому: то, как выглядит программа. Более сложно - на вики.
Язык общего назначения
По своему назначению языки программирования бывают:
- специальные (решающие задачи в определённой отрасли. Например, в математике Fortran, в базах данных SQL);
- общего назначения (решающие широкий спектр задач в любых отраслях. Например С++, Java, C#).
Java относится ко второму типу - это язык общего назначения, на котором можно написать практически любую программу. На сегодняшний день на Java создаются программы любого уровня сложности: от программирования бытовой техники и мобильных устройств (Java ME) до сложных высоко нагруженных сервисов (Java EE).
Плюсы:
- универсален, решает любые задачи
Минусы:
- в отдельных отраслях уступает (по скорости работы и удобству использования) специализированным языкам
Объектно-ориентированный
Все компьютерные программы пытаются описать процессы нашего мира в командах процессора. Поскольку компьютер ничего не знает об объектах нашего мира, программисту всегда приходилось «переводить» всё на язык цифр и инструкций. Так было до 70-х годов, пока не появилась объектно ориентированная парадигма программирования. С её помощью оказалось возможным программирование на уровне объектов из нашего мира, а не на уровне цифр из мира компьютерного.
Например, вот так выглядит описание двух столов в не-объектном виде:
- длина первого стола: 1200 мм
- ширина первого стола: 500 мм
- высота первого стола: 1000 мм
- длина второго стола: 1300 мм
- ширина второго стола: 600 мм
- высота второго стола: 1100 мм
Между параметрами нет никакой связи, кроме их названий. Можно легко допустить ошибку в попытке посчитать площадь стола: умножить длину ПЕРВОГО стола на ширину ВТОРОГО.
Пример объектно-ориентированного описания:
Первый стол:
- длина: 1200 мм
- ширина: 500 мм
- высота: 1000 мм
Второй стол:
- длина: 1300 мм
- ширина: 600 мм
- высота: 1100 мм
В данном случае, мы уже оперируем не разрозненными параметрами, а целыми объектами: Первый стол и Второй стол.
Программы, написанные на объектно-ориентированных языках, выполнялись медленней. Это было основной причиной, почему эта парадигма стала популярной лишь в 90-х, когда «железо» стало к этому готово.
Java, как почти все современные языки - это объектно-ориентированный язык, на котором достаточно просто моделировать процессы реального мира, и пользоваться всеми преимуществами объектно-ориентированного подхода.
Плюсы:
- ООП используется во многих других языках программирования
- широко использует абстракции
- легко моделировать объекты реального мира
Минусы:
- требует дополнительного изучения и развития абстрактного мышления
Функциональный
Когда необходимо уменьшить время выполнения программы, есть два очевидных пути:
- Оптимизировать программу;
- Увеличить частоту процессора.
С оптимизацией имеем следующие проблемы:
- оптимизировать приходится ВСЕ программы;
- существует логический лимит, дальше которого оптимизировать невозможно.
Ускорение процессора решает эти проблемы, и ускоряет выполнение сразу всех программ.
Благодаря закону Мура мир развивался вторым путём — ускорял процессоры. Закон гласил, что каждые два года частота процессоров обязана удваиваться. Но однажды закон Мура перестал работать и частота перестала расти. И мы перестали получать необходимое нам ускорение программ. Во всём сразу обвинили Мура, сказали, что он всё не так понял, и в закон внесли поправку: не частота удваивается, а количество транзисторов!
Таким образом последние годы частота процессоров не растёт, а растет количество транзисторов. Транзисторы расходуются на дополнительные ядра процессоров. Но если посмотреть на выше упомянутые два способа ускорения программ — там нет пункта о добавлении ядер. Чтобы программу можно было ускорить с помощью дополнительных ядер — она должна быть способна выполняться независимыми частями.
Но сделать это не так-то просто: все куски программ зависят друг от друга, зависят от общих данных (особенно если речь идёт об объектно-ориентированном программировании).
И тут на помощь приходит функциональное программирование, которое сводит к минимуму (а в идеале полностью исключает) использование общих данных, что позволяет легко и просто выполнять программу на разных ядрах.
Объектно-ориентированной парадигме потребовалось 20 лет, чтобы пройти путь от теории к массовому использованию. Зная, как стремительно сейчас изменяется наш мир, можно подумать, что это - исключение из правил, и мы принимаем всё новое гораздо быстрее и охотней.
Однако функциональной парадигме программирования потребовалось гораздо больше времени, чем объектно-ориентированной. Впервые эта парадигма была представлена в 30-е годы, однако в широкие массы функциональное программирование начинает входить только в наши дни.
Существуют полностью функциональные языки (Haskel, Erlang) и гибридные — сочетающие в себе объектно-ориентированный и функциональный подходы (Scala, C++).
Начиная с 8 версии Java приобретает механизмы функционального программирования (такие как ссылки на функции и лямбда-выражения), что позволяет легко создавать программы, которые могут выполняться на нескольких ядрах одновременно.
Плюсы:
- доступны новые приёмы программирования
- легко создаются программы, способные использовать одновременно несколько ядер процессора
Минусы:
- требует дополнительного изучения и развития функционального (математического) мышления
Типизация: строгая, статическая, явная
Строгая типизация
Судя из названия, если типизация строгая — то существуют какие-то правила, нарушать которые нельзя.
Если типизация НЕ строгая (например как в JavaScript), это не значит что правил нет. Правила есть, при чём есть ещё дополнительные правила, которые вступают в силу, когда нарушаются основные.
Пример (необходимо понимать что строки и числа — это разные типы данных):
Сложение двух чисел и двух строк, не зависимо от модели типизации, везде происходит одинаково:
5 + 5 = 10
«5» + «5» = «55»
Разница будет когда мы (возможно по ошибке) попытаемся сложить число и строку:
5 + «5» = ? (10 или «55»)
Строго типизированный язык скажет, что здесь затаилась ошибка, и заставит нас явно привести всё к какому-то одному типу.
Не строго типизированный начнёт хитрить: он прибегнет к дополнительному набору правил на случай не соответствия типов. В зависимости от этих правил будет выбран один из вариантов:
- Строка «5» станет числом,и результат будет 10 (сложение чисел)
- Число «5» станет строкой,и результат будет «55» (конкатенация строк)
Получается, что при не строгой типизации, по ошибке мы можем попытаться выполнить операцию над несовместимыми типами данных, и в зависимости от «дополнительных правил» получить разный результат: 10 или «55».
В Java используется строгий вариант, который предпочитает сообщить об ошибке и заставить программиста явно привести к какому-то типу - тем самым избежать набора «дополнительных правил», на случай, когда типы не совпадают.
Плюсы:
- нет дополнительных правил автоматического преобразования типов: их не нужно знать и нет ошибок неправильного преобразования
- быстро приходит понимание типизации
Минусы:
- все необходимые преобразования приходится выполнять явно
Поскольку типы всех переменных в Java определяются статически на этапе компиляции, то есть возможность проверить правильно ли эти типы использованы. Например, если мы пытаемся отправить автомобиль к ветеринару — Java нам скажет, что ветеринар не принимает объекты такого типа. Следовательно, об ошибке мы узнаем, как только попробуем скомпилировать код, а не когда запустим приложение на сервере.
Таким образом Java избегает целый класс ошибок (ошибок несовместимости типов), т.к. они все обнаруживаются во время компиляции благодаря статической типизации.
Естественно, что в наши дни никто не пишет код в блокноте, и не компилирует из командной строки — всё это умеют делать современные инструменты разработки IDE (IDEA, Eclipse, NetBeans). И все указанные IDE активно пользуются тем, что типизация статическая, и проверяют ошибки ещё до того, как мы попытаемся код скомпилировать.
Ещё одним плюсом статической типизации является то, что IDE способна подсказывать, какие методы и свойства есть у объекта. Это очень сильно упрощает и разработку, и обучение.
Плюсы:
- об ошибках несовместимых типов мы узнаём во время компиляции (с использованием IDE во время написания кода), а не во время выполнения программы
- зная тип данных IDE может подсказывать, какие операции с ним можно выполнить (очень полезно, особенно на начальных этапах знакомства с языком)
Минусы:
- необходимость определять типы самостоятельно
Явная типизация
Для того, чтобы объявить переменную в Java, необходимо явно указать её тип. Например, переменная i целочисленного типа объявляется так:
int i = 5;
При этом на самом деле Java умеет вывести тип переменной i и без нашего int. Достаточно было бы написать:
var i = 5;
Однако, Java не поддерживает объявление переменных с помощью var и, возможно, никогда не будет поддерживать.
Плюсы:
- нет
Минусы:
- необходимость указывать типы явно (микро-проблема)
Кросс-платформенный
Для того, чтобы написанное вами приложение могло запускаться на разных платформах (Linux, Windows, Android), оно должно быть преобразовано (скомпилированно) в совместимые с этой платформой процессорные инструкции.
Java декларирует, что для её программ этого не требуется. За счёт чего это достигается?
Код, написанный на Java, компилируется не в инструкции процессора (как у большинства компилируемых языков), а в специальный байт-код. Этот байт-код запускается на Java-машине — специальной программе, которая умеет преобразовать байт-код в процессорные инструкции.
Таким образом от платформы зависит не код, а Java-машина. Установив соответствующую Java-машину на каждую платформу, наш код будет одинаково работать на каждой из них.
Плюсы:
- программы могут работать на разных системах
Минусы:
- страдает производительность (незначительно)
Сборщик мусора
Память. Она не резиновая. В процессе работы программы создаются объекты, загромождая память. На плечи программиста ложится бремя следить за этими объектами, и когда они становятся не нужны — удалять их. Задача не из простых. Если что-то пошло не так — образуется утечка памяти, и приложение неизбежно (это вопрос времени) остановится с ошибкой об исчерпании всей доступной памяти.
Так вот Java решает эту проблему с помощью сборщика мусора. Вы просто не должны думать о ненужных объектах, думайте только о нужных! А о не нужных позаботится сборщик. Сам. Без напоминаний.
Попутно сборщик решает ещё одну проблему — фрагментацию памяти. Если в двух словах, суть проблемы в следующем: есть кусок памяти на 10 ячеек, 5 из них заняты и 5 свободны. Вы хотите записать целый объект на 5 ячеек в память — но не можете сделать этого. Т.к. свободные ячейки расположены не подряд, а три вначале, и две в конце.
Плюсы:
- не нужно следить за объектами, и принимать решение об очистке памяти
- нет проблемы фрагментации памяти
Минусы:
- страдает производительность
Hello world
Обзор языка был бы не полным без классического примера самой простой программы:
public class MyFirstClass {
public static void main(String[] args) {
System.out.println("Hello world!");
}
}
Из-за многословности этого, казалось бы, элементарного действия считают, что «порог входа» в Java слишком велик, и это отпугивает многих потенциальных пользователей этого языка. Действительно, hello world на Java окунает в ООП, заставляя задуматься, что такое класс. Почему он паблик? Зачем статик? Однако, на самом деле достаточно относиться первое время к этому как к магии и продолжать изучение этого замечательного языка.
И со временем Вам будут открыты все таинства заклинаний Java :)
Похожие материалы
- Разница между языками программирования C++ и Java
- 14014
- 20
Разница между языками программирования C++ и Java
читать 3 мин - Laravel vs Symfony
- 61
- 1
Laravel vs Symfony
читать 15 мин-
Денис Розганяев Software Engineer в Mobilunity
- Unit тесты в Java. Краткое руководство
- 23141
- 28
Unit тесты в Java. Краткое руководство
-
Платон Цыбульский Java developer в Brain agency