--- tags: прога, джава --- # Java 1 Конспект по первому семинару по Джаве. ## Как вообще запускаются программы на Java? ИЕ просил перед парой установить JDK, чтобы радотали команды `javac`, `javap`, `java`. `javac` компилирует `.java` в `.class`, синтаксис (базовый) такой: `javac Main.java` После этой операции полявляется файл `Main.class` `javap` -- дизассемблер для файлов `.class`, синтаксис: `javap Main` Выводит интерфейс класса `Main`, который лежит в `Main.class` `java` -- запускает JVM, `Java Virtual Machine`. Синтаксис: `java Main` Находит метод p`ublic static void main(String[] args)` и исполняет его, иначе ругается. JVM интерпретирует `.class` файлы на ходу, но может компилировать код в байтный код. При обычном запуске используется усреднённая комбинация компиляции и интерпретации. Есть ключи запуска, например, `-Xcomp` (`-X*** `ключи секретные и о них никто не знает) (есть ещё `-XX:***` ключи, о которых вообще никто не знает). `-Xcomp` говорит JVM скомпилировать код полностью и только потом исполнять. Подробнее про команды есть в `man` и в документации от Oracle. ## Немного про JVM С одной стороны, JVM -- удобная вещь. Можно скомпилировать один раз и запускать где угодно, где есть JVM (ИЕ почему-то посмеялся над кроссплотформенностью программ на Java, я лично не поняла почему). С другой стороны, на JVM идут накладные расходы, и в среднем код на Java будет исполняться дольше, чем код на Си. ## Мы писали код Сначала простой код: ```java // Main.java public class Main { public static void main(String[] args) { System.out.println("Hello, world!"); } } ``` Классы должны объявляться как public/private, в отличие от C++, здесь каждая функция отдельно объявляется как публичная/приватная. `System.out.println` полностью называется `java.lang.System.out.println`, но для удобства не нужно писать `java.lang`. Эта функция выводит в стандартный поток вывода указанную строку. Запускаем в консоли код: ``` javac Main.java java Main ``` и получаем вывод: ``` Hello, world! ``` ## Мы усложнили код и узнали рефлексию ```java // ClassToLoad.java public class ClassToLoad { public void methodToInvoke() { System.out.println("Method invoked!!!one!!"); } @Override public String toString() { return "I am The Instance of ClassToLoad!"; } } // Main.java public class Main { public static void main(String[] args) throws Exception { System.out.println("Hello, world!"); Class c = null; try { c = java.lang.Class.forName("ClassToLoad"); } catch (Exception e) { System.out.println("Caught an exception!"); return; } Object o = c.getDeclaredConstructor().newInstance(); System.out.println(o.toString()); } } ``` В Java все классы наследуются от [`Object`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html) (название класса такое). И со всеми классами можно общаться через класс [`Class`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Class.html). У него определены некоторые функции, например, `toString()`, и мы оверрайднули его и вызвали. Java много ругается, и если сначала мы оборачивали функцию `Class.forName(String)` в `try/catch` блок, то дальше компилятор ругался на непойманные ошибки от `getDeclaredConstructor()` и `newInstance()`, в итоге ИЕ для простоты написал `throws Exception` в прототипе функции. Нам в лабах так делать нельзя. ### Про рефлексию Можно получить доступ к классу, просто зная его имя и имея скомпилированный `.class` файл. И также вызывать методы: ```java import java.lang.reflect.Method; public class Main { public static void main(String[] args) throws Exception { Class c = null; try { c = java.lang.Class.forName("ClassToLoad"); } catch (Exception e) { System.out.println("Caught an exception!"); return; } Object o = c.getDeclaredConstructor().newInstance(); System.out.println(o.toString()); Method[] methods = c.getDeclaredMethods(); for (Method m : methods) { System.out.println(m); if (m.getName() == "methodToInvoke") { m.invoke(o); } } } } ``` Можно получить все методы класса и пойти с ними что-то делать! Мы на паре просто выводили их прототипы. Кроме `getDeclaredMethods()` есть `getMethods()`. Разница в том, что первая показывает только наши вручную описанные методы, а вторая -- все-все методы этого класса, в том числе доставшиеся от `Object`. Внимание на строчку с `m.invoke(o);`, необходимо подать объект этого класса как `this`, поскольку нами объявленный метод `methodToInvoke()` не статический. Здесь понадобилось импортировать `java.lang.reflect.Method`, чтобы использовать класс `Method` без `java.lang.reflect`. В Java используются модули и нет тех страшных инклюдов, которые копипастят всё, нуждаются в стражах включения и т.д. ## Мы немного написали лабу Этот код -- идея реализации. ```java // in main ArrayList code; ExecutionContext ctx; while (true) { char c = ...; Command cmd = (Command) Factory.createCommandByChar(c); cmd.execute(ctx); } // Factory class Factory { Object createCommandByChar(char c) { Class c = Class.forName(" " + c); return c.getDeclaredConstructor().newInstance(); } } ``` Контекст -- некоторое окружение. Флаги, стек, что-то произвольное, что может меняться. В `Factory` на самом деле должна быть некоторая мапа символов эзотерического языка и классов. ## javadoc `javadoc` генерит документацию в том же стиле, что и официальная документация. Синтаксис: ``` javadoc Main.java ``` Для написания нужны специальные коментарии с неполноценным маркдауном: ```java // Main.java public class Main { public static void main(String[] args) { System.out.println("Hello, world!"); } } ``` Генерится вот такая документация: ![](https://i.imgur.com/iA3XuFv.png) Для сравнения [официальная документация](https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html): ![](https://i.imgur.com/dyd45en.png)