Вибір першої мови програмування — огляд Java

Вибір першої мови програмування — огляд Java

  • 10 березня, 2016

Сьогодні найбільш популярною мовою програмування є Java. До того ж вона продовжує набирати оберти.

Спробуємо розібратися, чому Java обирають у сучасних проектах в якості основної мови програмування.

Сі-подібный синтаксис*

У той час, коли створювалася мова Java, найпопулярнішою мовою програмування була С++. Для того, щоб «переманити» програмістів на нову Java, було прийнято рішення зробити її максимально схожою на С++, узявши, за можливістю, краще від неї.

Java та С++ не єдині, хто володіє подібним синтаксисом. Праматір’ю С++ була мова С (Сі), тому усі мови, що використовують подібний синтаксис, називаються сі-подібними, та їх існує чимало (Wikipedia: C-family).

Таким чином, якщо ви вже знайомі хоча б з однією із цих мов, то велика кількість точок, фігурних та круглих дужок в Java здаватимуться вам чимось давно знайомим та звичним. З іншого боку, вивчивши синтаксис Java, вам буде значно легше осягнути й інші мови цього сімейства.

Плюси:

  • популярна.

Мінуси:

  • потребує звикання.

* Синтаксис - це набір правил, яким має відповідати текст програми. Якщо простіше: те, як виглядає програма. Більш складно - на вікі.

Мова загального призначення

За своїм призначенням мови програмування бувають:

  • спеціальні (вирішують задачі у певній галузі. Наприклад, у математиці Fortran, в базах даних SQL);
  • загального призначення (вирішують широкий спектр задач у будь-яких галузях. Наприклад, С++, Java, С#).

Java входить до другого типу - це мова загального значення, на якій можна написати практично будь-яку програму. Сьогодні на Java створюються програми будь-якого рівня складності: від програмування побутової техніки та мобільних приладів (Java МЕ) до складних високонавантажених сервісів (Java ЕЕ).

Плюси:

  • універсальна, розв’язує будь-які задачі.

Мінуси:

  • в окремих галузях поступається (швидкістю роботи та зручністю використання) спеціалізованим мовам.

Об’єктно-орієнтований

Усі комп’ютерні програми намагаються описати процеси нашого світу у командах процесора. Оскільки комп’ютер нічого не знає про об’єкти нашого світу, програмісту завжди доводилось «перекладати» усе на мову цифр та інструкцій. Так було до 70-х років, поки не з’явилась об’єктно-орієнтована парадигма програмування. З її допомогою виявилось можливим програмування на рівні об’єктів з нашого світу, а не на рівні цифр зі світу комп’ютерного.

Наприклад, ось так виглядає опис двох столів у не об’єктному вигляді:

  • довжина першого стола: 1200 мм
  • ширина першого стола: 500 мм
  • висота першого стола: 1000 мм
  • довжина другого стола: 1300 мм
  • ширина другого стола: 600 мм
  • висота другого стола: 1100 мм

Між параметрами немає ніякого зв’язку, крім їх назв. Можна легко зробити помилку у спробі порахувати площу стола: помножити довжину ПЕРШОГО стола на ширину ДРУГОГО.

Приклад об’єктно-орієнтованого опису:

Перший стіл:

  • довжина: 1200 мм
  • ширина: 500 мм
  • висота: 1000 мм

Другий стіл:

  • довжина: 1300 мм
  • ширина: 600 мм
  • висота: 1100 мм

У даному випадку, ми вже оперуємо не розрізненими параметрами, а цілими об’єктами: Перший стіл і Другий стіл.

Програми, написані на об’єктно-орієнтованих мовах, виконувались повільніше. Це було причиною того, що ця парадигма стала популярною лише в 90-х, коли “залізо” стало до цього готовим.

Java, майже як усі сучасні мови, є об’єктно-орієнтованою мовою, на якій достатньо просто моделювати процеси реального світу та користуватися всіма перевагами об’єктно-орієнтованого підходу.

Плюси:

  • ООП використовується у багатьох інших мовах програмування;
  • широко використовує абстракції;
  • легко моделювати об’єкти реального світу.

Мінуси:

  • потребує додаткового вивчення та розвитку абстрактного мислення.

Функційна

Коли необхідно зменшити час виконання програми, є два очевидні шляхи:

  1. Оптимізувати програму;
  2. Збільшити частоту процесора.

З оптимізацією маємо наступні проблеми:

  • оптимізувати доводиться УСІ програми;
  • існує логічний ліміт, далі якого оптимізувати неможливо.

Прискорення процесора вирішує цю проблему та прискорює виконання одразу усіх програм.

Завдяки законові Мура світ розвивався другим шляхом - прискорював процесори. Закон свідчив, що кожні два роки частота процесорів повинна подвоюватись. Але одного разу закон Мура припинив працювати та частота припинила рости. І ми припинили отримувати необхідне нам прискорення програм. У цьому відразу звинуватили Мура, сказали, що він усе не так зрозумів, і в закон внесли зміну: не частота подвоюється, а кількість транзисторів!

Таким чином останні роки частота процесорів не росте, а росте кількість транзисторів. Транзистори витрачаються на додаткові ядра процесорів. Але якщо подивитись на вище згадані два способи прискорення програм - там немає пункту про додавання ядер. Щоб програму можна було прискорити за допомогою додаткових ядер - вона має бути здатна виконуватись незалежними частинами.

Але зробити це не так просто: усі шматки програм залежать один від одного, залежать від загальних даних (особливо, якщо мова йде про об’єктно-орієнтоване програмування).

І тут на допомогу приходить функційне програмування, котре зводить до мінімуму (а у ідеалі повністю виключає) використання загальних даних, що дозволяє легко й просто виконувати програму на різних ядрах.

Об’єктно-орієнтованій парадигмі знадобилось 20 років, щоб пройти шлях від теорії до масового використання. Знаючи, як стрімко зараз змінюється наш світ, можна подумати, що це - виключення з правил, і ми приймаємо усе значно швидше та охочіше.

Однак функційній парадигмі програмування знадобилось значно більше часу, ніж об’єктно-орієнтованій. Вперше ця парадигма була представлена у 30-ті роки, однак у широкі маси функційне програмування починає входити лише у наші дні.

Існують повністю функційні мови (Haskel, Erlang) та гібридні - поєднуючі у собі об’єктно-орієнтований та функційний підходи (Scala, C++).

Починаючи з 8 версії Java набуває механізмів функційного програмування (такі як посилання на функції лямбда-вираження), що дозволяє легко створювати програми, котрі можуть виконуватись на декількох ядрах одночасно.

Плюси:

  • доступні нові прийоми програмування;
  • легко створюються програми, здатні використовувати одночасно кілька ядер процесора.

Мінуси:

  • потребує додаткового вивчення та розвитку функційного (математичного) мислення.

Типізація: сувора, статична, явна

СУВОРА ТИПІЗАЦІЯ

Судячи з назви, якщо типізація сувора - то існують якісь правила, порушувати які не можна.

Якщо типізація НЕ сувора (наприклад, в JavaScript), це не означає, що правил немає. Правила існують, до того ж є ще додаткові правила, котрі набувають чинності, коли порушуються основні.

Приклад (необхідно розуміти, що терміни та числа - це різні типи даних):

Складання двух чисел та двух рядків, незалежно від моделі типізації, усюди відбувається однаково:

5+5=10

«5»+«5»=«55»

Різниця буде, коли ми (можливо, помилково) намагатимемося скласти число та рядок:

5+«5» = ? (10 або «55»)

Суворо типізована мова скаже, що тут зачаїлася помилка, та змусить нас привести усе до якогось одного типу.

Не суворо типізований почне хитрувати: він вдасться до додаткового набору правил на випадок не відповідності типів. У залежності від цих правил буде обраний один із варіантів:

  1. Рядок «5» стане числом та результат буде 10 (складання чисел)
  2. Число «5» стане рядком та результат буде «55” ( конкатенція рядків)

Виходить, що при не суворій типізації, за помилкою ми можемо спробувати виконати операцію над несумісними типами даних та в залежності від «додаткових правил» отримати різний результат: 10 або «55».

В Java використовується суворий варіант, котрий надає перевагу повідомленню про помилку та змушує програміста явно привести до якогось типу - тим самим уникнути набору «додаткових правил», на випадок, коли типи не співпадають.

Плюси:

  • немає додаткових правил автоматичного перетворення типів: їх не потрібно знати та немає помилок неправильного перетворення;
  • швидко приходить розуміння типізації.

Мінуси:

  • усі необхідні перетворення доводиться виконувати явно.

Оскільки типи усіх змінних в Java визначаються статично на етапі компіляції, то існує можливість перевірити, чи правильно ці типи використані. Наприклад, якщо ми намагаємось відправити авто до ветеринара - Java нам скаже, що ветеринар не приймає об’єкти такого типу. Відповідно, про помилку ми дізнаємось, як тільки спробуємо компілювати код, а не коли запустимо додаток на сервері.

Таким чином Java уникає цілий клас помилок (помилок несумісності типів), адже вони усі виявляються під час компіляції завдяки статичній типізації.

Звичайно, у наші дні ніхто не пише код у блокноті, та не компілює з командного рядка - усе це вміють робити сучасні інструменти розробки IDE (IDEA, Eclipce, NetBeans). Та усі вказані IDE активно користуються тим, що типізація статична, та перевіряють помилки ще до того, як ми намагатимемося компілювати код.

Ще одним плюсом статичної типізації є те, що IDE здатна підказувати, які методи та властивості є у об’єкта. Це дуже спрощує і розробку, і навчання.

Плюси:

  • про помилки несумісних типів ми дізнаємось під час компіляції (з використанням IDE під час написання коду, а не під час виконання програми);
  • знаючи тип даних IDE, може підказувати, які операції з ним можна виконати (дуже корисно, особливо на початкових етапах знайомства з мовою).

Мінуси:

  • необхідність визначати типи самостійно.

Явна типізація

Для того, щоб оголосити змінну в Java необхідно явно вказати її тип. Наприклад, змінна і цілочисельного типу оголошується так:

int i = 5;

При цьому насправді Java вміє вивести тип змінної і без нашого 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 :)