---
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)