Java. Начало программирования.

 
 
 
Сообщения:367
Раздел 0. Предыстория.
На мысль создать максимально понятное пособие для абсолютных новичков в программировании меня навело вот это обсуждение - http://javatalks.ru/topics/51510

Чуть-чуть предыстории и вообще. Программы на компьютере исполняются процессором. Процессор оперирует машинными кодами, обычно это наборы разного количества чисел диапазона от 0 до 255. Скажем, для процессоров интел инструкция "добавить к ячейке (регистру) al значение из bl" будет иметь два таких числа - "00, 216" (00 D8 в шестнадцатеричном виде).

Чтобы не кодировать числами, сделан так называемый "язык ассемблера". Это максимально близкий к машинным кодам язык программирования, который переводится в машинные коды один-в-один. Вышеприведенная инструкция на ассемблере будет выглядеть как "add al, bl". Ассемблер - самый быстрый, но наиболее долгий для кодирования язык.

На базе ассемблера был создан(ы) язык(ы) С/С++. Транслятор (или, компилятор) переводит текст программы на машинные коды, а они исполняются процессором. С/С++, в среднем, в 2-3 раза медленней ассемблера, но кодируется программа на нем примерно в 10 раз быстрей. Сама программа, выполняющая программы на Java, написана как раз на C/C++.

Java - это некое дальнейшее развитие C/C++, где во главу угла была поставлена задача еще ускорить разработку программ, даже ценой сокращения скорости исполнения. Программа на Java пишется также примерно в 10 раз быстрей, чем на C/C++, но исполняется также в 2-3 раза медленней C/C++. В основном ускорение было достигнуто сокращением времени отладки и поиска ошибок. Дополнительный момент заключается в том, что один раз написанная программа вроде как может исполняться на любых операционных системах, где есть транслятор и среда исполнения Java.

Дальнейшее развитие Java привело к созданию языка Kotlin, который абсолютно совместим с Java, и имеет такую же скорость исполнения, как Java, но разработка программ на нем еще в 2-3 раза ускорена. Но изучать Kotlin, без знания Java, не имеет смысла.

Программирование на Java имеет как бы бесконечное кольцо из шагов:
1. Программист пишет (редактирует) текст программы.
2. Программист программой "javac" преобразует текст программы в специальный(ые) .class файл(ы). Это называется "компиляция".
3. Программист программой "java" запускает выполнение программы, "натравив" ее на созданные .class файлы. Это называется "исполнение".
4. Программа java исполняет .class файлы, программист смотрит результат исполнения.
5. Повторяется п.1 и далее, пока программа не будет готова. По готовности программа передается пользователям.

Пользователи запускают Java программу от программиста (в виде скомпилированных .class файлов), опять таки через запуск программы "java".

Зачем так сделано? Компиляция - процесс долгий. А исходный текст Java программы очень большой в сравнении с .class файлами. Пользователям нужен быстрый запуск, а сама Java программа хорошо бы занимала поменьше места на диске и в оперативной памяти.

Существует два комплекта исполняемой среды java.
1. JDK (Java Development Kit). Имеет в составе и "javac" и "java", то есть с помощью этого комплекта можно создавать и тестировать исполнением новые Java программы. Устанавливается у разработчика. Не самообновляется (в Windows).
2. JRE (Java Runtime Engine). Имеет в составе только "java", то есть, с помощью этого комплекта можно только исполнять ранее созданный и скомпилированные программы Java. Устанавливается у пользователей. Самообновляется (в Windows).

Нам, для обучения программированию потребуется JDK.
Изменен:01 апр 2017 16:53
 
 
Сообщения:367
1. Устанавливаем JDK в Windows 7.
Начинаем поиск JDK в браузере в Гугле:


Первая же ссылка ведет куда надо. Открываем ее. В открывшейся ссылке выбираем загрузку JDK (отмечена красной стрелочкой):


Принимаем условия лицензии (синяя стрелка) и выбираем один из двух комплектов JDK(красная стрелка):


Windows x86 - это 32 битный JDK, исполняется на любых системах Windows, а x64 - 64битный, исполняется только на 64х битных системах. У 32 битного комплекта есть ограничение: исполняемая программа Java не сможет занять более 1.7 гигабайта оперативной памяти. 64х битная не имеет таких ограничений.

Как узнать, какая именно операционная система установлена? Самый простой способ: нажать комбинацию клавиш Win+Pause (отмечено красным):


Откроется панель управления, где это будет написано (отмечено красным):


Зная, какая у нас операционная система, сможем выбрать правильный комплект для скачивания.
Изменен:01 апр 2017 17:12
 
 
Сообщения:367
Закачав браузером установщик, открываем папку и запускаем установщик на исполнение:

(кстати, открыть список ранее закачанных файлов обычно в браузерах можно комбинацией Ctrl+J).

Соглашаемся с лицензией, жмем Next, попадаем на такое окно:


Тут у нас две задачи. Первая - отключить public JRE (отмечено красной стрелкой). JRE нужна только если мы работаем на одном компьютере с пользователями, под разными аккаунтами и пользователям разрешено только запускать Java программу, но не компилировать ее. Тогда JRE устанавливаем, пользователи будут ею пользоваться, а JRE будет самообновляться.

Вторая задача - запомнить путь установки (или поменять его, но потом запомнить). Для этого жмем кнопку Change (синяя стрелка №1), в открывшемся окошке копируем путь установки (синяя стрелка №2) комбинацией клавиш Ctrl-C:


Сохраняем путь установки через Notepad куда нибудь (я кинул на рабочий стол под именем "Java path.txt"). Если у нас есть русские буквы в пути установки, переключаем кодировку на UTF-8:


Закрываем notepad (или сворачиваем его), возвращаемся к установщику JDK, заканчиваем процесс установки.
Изменен:01 апр 2017 17:12
 
 
Сообщения:367
2. Настраиваем JDK в Windows 7.
Установка параметра JAVA_HOME:
Для настройки нам потребуется снова открыть панель управления Win+Pause:


Нажимаем Advanced system settings (русск. "Дополнительные параметры системы") (стрелочка №1), далее открываем Environment Variables (русск. Переменные среды) (стрелка №2), далее нажимаем New (русск. создать) (стрелочка №3). В появившемся окне создаем переменную JAVA_HOME (стрелка №4), и копируем путь установки из нашего "java path.txt" (стрелка №5). В одном из гайдов я видел настоятельную рекомендацию убрать пробел из "Program Files" путем замены на сокращенное название с тильдой. Если путь установки "Program Files" то меняем на Progra~1, если "Program Files (x32)" - то на Progra~2. Проверить правильность замены можно таким образом. Копируем текст с тильдой (в моем случае - C:\Progra~1\Java\jdk1.8.0_121), запускаем проводник комбинацией клавиш Win + E (вин + лат Е), вставляем в адресную строку наш путь (стрелка №6). Должен появиться список примерно как у меня на стрелочке №7. Если что-то не то, то просто перенесите путь без корректировки.

Нажимаем OK, пока все окошки не закроются и мы снова увидим панель управления Система.

Установка path:
Снова открываем переменные среды, но теперь выбираем переменную Path (стрелка №1) и нажимаем modify (русск. Изменить...) (стрелка №2):

В notepad к нашему пути установки допишем "\bin" (стрелка №3), скопируем текст, поставим курсов в поле Variable value, нажмем клавишу End (чтобы уйти в конец и не затереть предыдущее значение). В конце поставим ";" (стрелка №4) и положим скопированный нами путь (с дополнением \bin) (стрелка №5). Снова нажмем OK несколько раз, пока не увидим панель управления Система, дабы переменные сохранились.

Разлогинимся, залогинимся повторно.

Проверяем переменные.
Жмем Start (Пуск), в поле поиска набираем "cmd" (цэ-эм-дэ без кавычек), как система его найдет, запускаем. В программе пишем path, жмем enter. Убеждаемся, что path корректно установился, и отделен точкой с запятой от предыдущего пути (подчеркнуто красным):


Дабы проверить правильность установки JAVA_HOME, там же набираем "set JAVA_HOME":


Если все хорошо, переходим к последнему пункту проверки - тестовому запуску.
Вводим команды "javac -version" и потом "java -version". Программы должны запуститься и сообщить свою версию (синие стрелочки):


Если система не может их найти на выругается. Я специально запустил неправильно javac0, чтобы показать ошибку (красная стрелочка).

Если все хорошо, мы готовы перейти уже к программированию. Если запуск не прошел удачно, надо перепроверить переменную path.
 
 
Сообщения:367
Самое время создать каталог, где будем учиться. Я решил сделать его на рабочем столе, хотя можно где угодно. Обозвал JavaLearn, вошел в него, и мне открывается проводник:

Вот если поставить мышкой курсор в место, указанное красной стрелочкой, то система нарисует абсолютный путь к каталогу:

Правой клавишей мыши на нем и копируем его.

Запускаем cmd, и в строке команды вводим "copy con j.bat", жмем Enter:

Далее пишем "cd " (цэ-дэ пробел) и, подведя мышкой на черное поле, правой клавишей вставляем то, что скопировали. Enter, Ctrl-Z, Enter.

Таким образом мы создали файлик j.bat, с помощью которого мы всего лишь "j", "Enter" будем, каждый следующий раз после запуска cmd пропрыгивать в созданный нами каталог:


А вот находясь в том каталоге, с помощью javac и java, компилировать и запускать наши первые Java программы.
 
 
Сообщения:367
3. Java. Классы, объекты, пакеты.
Если на пальцах, то Класс - это как чертеж или инструкция к некоей сущности. Ну вот как чертеж автомобиля. Или инструкция по его эксплуатации. Как и полагается чертежу (инструкции), он имеет в себе сведения, что из себя представляет сущность, как ее создать, как ею манипулировать, как ее утилизировать. Объект - это как сам сделанный автомобиль. Чертеж (инструкция) есть всегда. Объектов может быть ни одного, один, много.

Класс описывает алгоритмы, общие для класса данные, а также описывает, как данные приписаны к каждому объекту. Попробуем на примере автомобиля. Пусть есть класс автомобиль. В нем есть алгоритмы, типа "как завести конкретный автомобиль", "как поехать", "как остановить", "как заглушить". Есть общие сведения, которые не привязаны к конкретным автомобилям. К примеру, "допустимая по нормативам нагрузка от оси на дорожное полотно на автомагистралях". Есть данные, которые характеризуют конкретный автомобиль. Это, к примеру, "допустимая нагрузка на ось этого автомобиля", "текущая нагрузка на ось", "запас бензина в баке", "сведения об установленном двигателе" и т.п. Алгоритм класса, к примеру, получив команду "поехать" на определенном автомобиле, проверит "а не превысили ли мы допустимый норматив текущей нагрузкой?" Если - "нет, не превысили!" - то проверит - "а не превысили ли мы текущей нагрузкой на ось допустимую нагрузку на дорожное полотно на автомагистралях?" Если "да", то на автомагистрали нас алгоритм не пустит, заставит ехать по проселкам, к примеру.

Пакеты - это группы классов, объединенные единым замыслом. В случае AI автомобиля, это видимо будет отдельный пакет классов работы с видеокамерами/лидарами и т.п., отдельный - управления двигателем и контроля его состояния, отдельный - система связи и интернета на борту и так далее. Каждый класс в пакете может быть объявлен или публичным, и тогда он будет доступен из других пакетов. Или внутренним, и тогда он будет доступен только и только для классов этого же пакета. Это позволяет гибко настраивать доступ к пакетам "снаружи", разделяя взаимодействие между пакетами и внутреннюю обработку внутри пакета.
 
 
Сообщения:367
4. Первая "программа".
Сделаем самую минимальную "программу". Почему в кавычках, будет ясно позже. Запускаем cmd, "j", enter. В каталоге пишем "copy con Z.java", "Enter". в новой строке "class A{}" (A - латинская!), "Enter", Ctrl-Z, "Enter". (см. стрелку 1):

Далее набираем dir (стрелка 2), и видим, что в каталоге появился файл Z.java (стрелка 3) (Z.java - случайно выбранное имя файла). Наша типа, первая "программа". Вся программа описывает один единственный класс A (на латинском!), в котором нет ничего - ни данных, ни алгоритмов. (Аналогично, "A" - случайно выбранное имя класса.)

Но тем не менее, командой "javac Z.java" мы его успешно компилируем (стр.4), и повторным вызовом dir убеждаемся, что появился .class файл A.class (стр.5).

Как его выполнить? Тут интересный момент, что если "компилятор" javac ожидает от нас имени файла, то "исполнитель" - только имя класса. Имя класса - "A", попробуем выполнить наш .class файл командой "java A":

Упс! Ошибка (Error): Метод Main на найден в классе А, пожалуйста, определите метод main ("главный", англ) как
public static void main(String[] args)
или, в случае приложения JavaFX, унаследуйтесь от "javafx.application.Application".

Что произошло? В программе есть блоки кода (алгоритмы), которые располагаются между фигурным скобками "{" и "}". Некоторые блоки кода поименованы (имеют имя). В Java поименованные блоки кода называются "методы", в других языках - "функции" и "процедуры".

"Исполнитель" java, опираясь на нашу команду "java A", нашел класс файл "A.class", но внутри не нашел метода main. О чем и выругался.
Вот потому "программа" была в кавычках. Она компилируется, но не исполняется. Будем исправлять!
Изменен:03 апр 2017 01:08
 
 
Сообщения:841
ну насчёт скорости работы ты загнул. разница примерно процентов 5 - 10.
да и Ява только на первый взгляд похожа на С.
Ява создавалась с учётом двух вещей:
она должна работать повсюду без переписывания и перекомпиляции.
и второе - техника безопасности. зачем учить студентов пять лет всем скользким местам, если они половину забудут, да и новые могут появиться. проще отгородить все ямы и пускать людей только туда, где они себе пальцы не отдавят.
 
 
Сообщения:367
А что если мы ошибемся?

Попробуем запустить java, указав ошибочный класс "xyz" - "java xyz":


java попробует найти файл xyz.class, ожидаемо его не найдет, и выругается:
Error: Could not find or load main class xyz
Ошибка: Не могу найти или загрузить main класс xyz


Более того, если присмотреться к картинке, хорошо видно, что java не нашла класс, когда он был написан не большой "А", а маленькой "а". Java - язык регистро-зависимый. "А" и "а" - для него разные вещи.
 
 
Сообщения:367
5. Редактируем через Notepad++ или jEdit

Дабы отредактировать наш Z.java файл, я рекомендую установить одну из программ - Notepad++ или jEdit (или обе).
1. Notepad++ - чисто Windows программа, но занимает мало места в памяти и позволяет работать с кучей другий языков, с xml, c html и т.п.
2. jEdit - написанный на Java редактор, поэтому кроссплатформенный и запускается на любой операционной системе, где есть java.

Я предпочитаю notepad++ (хотя у меня установлен и jEdit). Его можно найти и скачать тут - Загрузка notepad++
Выберите последнюю версию и выберете правильно разрядность:


Загружаем, устанавливаем, там ничего сложного нет. Запускаем через Пуск. И вот тут нам надо кое что настроить. Если посмотреть на три двухбуквенные комбинации -
aI al a1

- то краем глаза сложно понять, где какая буква вторая - И, Л, единица. Поэтому на старте я настоятельно рекомендую поменять шрифт в notepad++. a) Settings - Style configurator

б) Language: Global Style; Style: Default Style; Font name: Ubuntu mono; -

Если присмотреться, вверху слева видно, что шрифт стал гораздо более различимым. Другой вариант хорошего шрифта для программирования - Deja Vu Mono.
 
 
Сообщения:367
Отвлечение. После установки Notepad++ и привязки .java файлов к нему, иконка поменялась на текстовую. а расширение ".java" пропало:

Как "лечить", можно прочесть, к примеру, тут - Скрытие и отображение расширений имен файлов в проводнике Windows
После лечения выглядит так:

Что мне кажется удобней.
 
 
Сообщения:367
6. Первая "пустая" программа.
Открываем в notepad++ Z.java, ставим курсор между фигурных скобочек, жмем Enter, потом копируем ранее полученный текст из java про ошибку про метод main(), и после описание метода main() добавляем еще пару фигурных скобочек:

Сохраняем, переключаемся в cmd, компилируем, запускаем:

Мы видим, что ошибка пропала. Правда, наша программа вообще ничего не сделала, но только потому, что там в блоке кода у main() ничего и не было.
 
 
Сообщения:367
7. Первая "рабочая" программа.
Сделаем в нашей программе, чтобы она хоть что-то делала. Обычно первой программой ставят задачу вывести "Hello, world!" Дабы вывести данную фразу в консоль cmd, надо вставить такой вызов метода println():
System.out.println("Hello, world!");

в блок кода у метода main():
class A{
	public static void main(String[] args){
		System.out.println("Hello, world!");
	}
}

Сохраняем, компилируем, выполняем, наблюдаем успешный результат:

Отметим, что
  • Строки заключаются в двойные кавычки;
  • Каждое выражение заканчивается точкой с запятой.


А если мы хотим три раза вывести строки? Три раза вызовем println():
class A{
	public static void main(String[] args){
		System.out.println("Hello, world #1!");
		System.out.println("Hello, world #2!");
		System.out.println("Hello, world #3!");
	}
}

Сохраняем, компилируем, выполняем, получаем результат:


Подсказка. Чтобы не печатать каждый раза javac Z.java и java A, можно в cmd использовать стрелки вверх и вниз, выбирая предыдущие команды.
Изменен:04 апр 2017 16:01
 
 
Сообщения:367
8. Первая программа из двух классов.

Изменим программу, чтобы она выглядела так:
class A{
	public static void main(String[] args){
		System.out.println("Hello, world from a #1!");
		B.main(args);
		System.out.println("Hello, world from a #2!");
		
	}
}
class B{
	public static void main(String[] args){
		System.out.println("Hello, world from b #1!");
		System.out.println("Hello, world from b #2!");
	}
}


Я удалил третий вызов printl(), добавил в строки "from a", скопировал класс A в класс B, и поменял a на b. Также в A добавлен вызов метода main() из класса B:
		B.main(args);

Результат:

При вызове "java A", у нас выполняется строка
		System.out.println("Hello, world from a #1!"

Затем управление передается в класс B в метод main(), и там выполняются две строки:
		System.out.println("Hello, world from b #1!");
		System.out.println("Hello, world from b #2!");

Затем, увидев "}" система возвращается в метод A.main() и там выполняет оставшуюся строчку:
		System.out.println("Hello, world from a #2!");


Если посмотреть снимок экрана, видно, что я потом запускал "java B" и он спокойно выполнился, выдав свои две строчки:
		System.out.println("Hello, world from b #1!");
		System.out.println("Hello, world from b #2!");


Вот точно таким же образом, как я вызывал B.main(), java вызывает мой main() при запуске.

Еще ниже видно, что в каталоге три файла - два .class файла - A.class и B.class, и программа Z.java. Любопытно, что java программа занимает на диске 337 байт, а два класс-файла в сумме 945 байт.
 
 
Сообщения:367
9. Stack (Стек). Recursion (Рекурсия). StackOverflowError (ошибка переполнения стека).

А что будет, если в класс B поставить вызов метода main() из класса A? Мы можем это сделать? Да, можем. Теперь наша программа выглядит так:
class A{
	public static void main(String[] args){
		System.out.println("Hello, world from a #1!");
		B.main(args);
		System.out.println("Hello, world from a #2!");
		
	}
}
class B{
	public static void main(String[] args){
		System.out.println("Hello, world from b #1!");
		A.main(args);
		System.out.println("Hello, world from b #2!");
	}
}

как я буду исполнять:


В отличии от предыдущих случаев, я перенаправляю вывод в Z.txt, потому что там столько вывалится, что начало будет не видно. Сам же Z.txt я открою в Notepad++.

Что мы получим?
Hello, world from a #1!
Hello, world from b #1!
Hello, world from a #1!
Hello, world from b #1!
Hello, world from a #1!
Hello, world from b #1!
Hello, world from a #1!

... вырезан кусок

Hello, world from b #1!
Hello, world from a #1!
Hello, world from b #1!
Hello, world from a #1!
Hello, world from b #1!
Exception in thread "main" java.lang.StackOverflowError
	at java.io.FileOutputStream.write(FileOutputStream.java:326)
	at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
	at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
	at java.io.PrintStream.write(PrintStream.java:482)
	at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
	at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
	at sun.nio.cs.StreamEncoder.flushBuffer(StreamEncoder.java:104)
	at java.io.OutputStreamWriter.flushBuffer(OutputStreamWriter.java:185)
	at java.io.PrintStream.write(PrintStream.java:527)
	at java.io.PrintStream.print(PrintStream.java:669)
	at java.io.PrintStream.println(PrintStream.java:806)
	at A.main(Z.java:3)
	at B.main(Z.java:12)
	at A.main(Z.java:4)
	at B.main(Z.java:12)
	at A.main(Z.java:4)
	at B.main(Z.java:12)
	at A.main(Z.java:4)
	at B.main(Z.java:12)
	at A.main(Z.java:4)
	at B.main(Z.java:12)
	at A.main(Z.java:4)
	at B.main(Z.java:12)
	at A.main(Z.java:4)

.... вырезан кусок

	at A.main(Z.java:4)
	at B.main(Z.java:12)
	at A.main(Z.java:4)
	at B.main(Z.java:12)
	at A.main(Z.java:4)


Что получается? java выполняет
System.out.println("Hello, world from a #1!");

потом из A.main() вызывает B.main(), и ей нужно запомнить место, куда вернуться, чтобы выполнить в этом же классе A
System.out.println("Hello, world from a #2!");


В свою очередь, java, выполняя B.main(), исполнив
System.out.println("Hello, world from b #1!");

вызывает A.main() и ей надо опять таки запомнить, куда надо вернуться в B.main(), чтобы выполнить
System.out.println("Hello, world from b #2!");


Место, куда укладывается информация с адресом возврата, называется стек (stack). Информация в стек складывается по принципу LIFO - "последнее положили первым достали". Поскольку у нас не происходит возврата из-за ошибки в дизайне программы, в стеке кончается место. И мы получаем ошибку StackOverflowError:
Exception in thread "main" java.lang.StackOverflowError


Чуть ниже ошибки мы видим места в программе, которые сформировали эту ошибку (stacktrace - стектрейс):
	at A.main(Z.java:3)
	at B.main(Z.java:12)
	at A.main(Z.java:4)
	at B.main(Z.java:12)
....

Столкнувшись с такой ошибкой, опираясь на стек вызовов аналогично сформированному в нашем примере, можно и нужно исправить программу.

Сама по себе технология вот такого вызова методов "самого-себя" или вот таким вот "кроссом" легитимна, называется рекурсия, это можно делать, если нужно. Но нужно грамотно писать и проверять граничные условия, чтобы избегать такого бесконечного вызова.

upd. В стектрейсе самые последние вызовы методов будут самыми верхними, самые поздние - самыми нижними.
ps. Посмотрел по тексту и выяснил, что java вызвала последовательно методы main() из A и B 15448 раз.
Изменен:10 апр 2017 02:07
 
Модераторы:Нет
Сейчас эту тему просматривают:Нет