# Java

## Функция main

```Java
package org.example;

public class Main {
    public static void main(String[] args) {
        System.out.println("Hello world!");
    }
}
```

## Сокращения InteliJ

* psvm - public static void main
* sout - Sytem.out.println()
* serr - System.err.println()
* I - for(Object object: ){}
* fori - for (int i = 0; i< ; i++) {}
* shift + shift - поиск по проекту
* ctrl + alt + t - сниппеты для блоков кода (циклы, if, switch, try-catch)
* alt + insert - сниппеты для класса

## Строки

Строки неизменяемые (immutable) и не могут иметь наследников (final). Для изменения копии

```Java
// foo и bar - 1 объект в Pool (аля static)
String foo = "foo";
String bar = "foo";
// baz - объект в куче
String baz = new String("baz");
```

### StringBuffer и StringBuilder

Данные типы - изменяемые строки с изменениями на месте. StringBuffer синхронизирует методы, поэтому медленее, но можно работать в многопотоке. StringBuilder быстрее, но методы не синхронизирует

```Java
// Можно передать строку в инициализатор, но не обязательно
StringBuffer sb = new StringBuffer(); 

sb.append("foo");
sb.append(5);
```

#### Методы StringBuffer и StringBuilder

* append (смотреть выше)
* delete(int start, int end)
* insert(int offeset, String str)
* replace(int start, int end, String str)
* reverse()
* substring(int start, int end) - создаст новую строку
* toString - перевести в строку

### RegEx

RegEx - щаблон для поиска строки в тексте

#### Примеры RegEx

* "java" - только слово java подойдёт
* "\\d{3}" - 3 цифры

#### Pattern для RegEx

Pattern - скомпилированный RegEx

```Java
Pattern p = Pattern.compile("java");
p = Pattern.compile("java", Pattern.CASE_INSENSETIVE);
```

## Var

Var выбирает тип по типу данных, который мы присваеваем. Нужно инициализировать при объявлении

```Java
var x = 5;
```

## Константы

В Java константы объявляются словом *final*

```Java
final int LIMIT = 5;
```

## Массивы

Объявлять массивы можно разными способами

```Java
int nums[] = new int[] {10, 20};
int[] nums = {10, 20, 30};
```

### Многомерный массив

```Java
int[][] nums = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
```

## Параметры переменной длины

```Java
static void sum(int ...nums) {
    int result = 0;
    for(int n: nums) {
        result += n;
    }
    System.out.println(result);
}
```

Все обязательные параметры до параметрвов переменной длины

## Значения по умолчанию для параметров

**Их нету!!!**

## Перегрузка методов

Перегрузка позволяет определять функции с одинаковым именем, но с разными типами и/или кол-вом параметров.

```Java
static int sum(int a, int b) {
    return a + b;
}

static double sum(double a, double b) {
    return a + b;
}
```

Если отличается только выходной тип, то останется только последняя имплементация

```Java
// Эту версию не получится вызвать
static int sum(int a, int b) {
    return a + b;
}

// Будет вызываться эта версия
static double sum(int a, int b) {
    return a + b;
}
```

## Обработка ошибок

### try-catch-finally

```Java
try {
    int[] a = new int[3];
    a[4] = 5;
} catch (Exception e) {
    e.printStackTrace();
} finally {
    System.out.println("Will always print this");
}
```

### *throw*

```Java
throw new Exception("Very important exception! Don't you dare not handle it");
```

### *throws*

Позволяет кинуть ошибку вверх по стаку

```Java
public static void main(String[] args) throws Exception {}
```

## OOP

OOP - бяка, Java - OOP => Java - бяка

```Java
public class Foo {
    int bar;
    string baz;

    void fooBar() {
        System.out.println("FooBaz");
    }
}
```

### Модификаторы доступа

* public - везде
* private - только внутри класса
* protected - подклассы и сам класс

Если не указан, то применяется модификатор по умолчанию. Он делает переменную public в пределах данного пакета

### Конструктор и инициализатор

```Java
public class Test {
    int age;
    int age2;
    int age3;

    // Блок - инициализатор
    {
        age = 5
    }

    // Конструктор
    public Test(int age2, int age3_input) {
        this.age2 = age2;
        age3 = age3_input; // Такое не делать, ибо не красиво
    }
}
```

### Наследование

```Java
public class Foo {}

public class Bar extends Foo {}
```

Множественное наследование низя. Приватное не наследуется

#### *Override*

```Java
class Foo  {
    int foo() {
        return 5;
    }
}

class Bar extends Foo {
    @Override
    int foo() {
        return 6;
    }
}
```

Уровень видимости при *Override* не может понижаться. У переопределённого метода должен быть такой же интерфейс, как и у родителя

#### *super*

*super* позволяет обратиться к методам родительского класса

```Java
class Foo  {
    int foo() {
        return 5;
    }
}

class Bar extends Foo {
    @Override
    int foo() {
        return super.foo();
    }
}
```

#### *final* при наследовании

*final* запрещает наследование

#### Наследование конструктора

```Java
class Foo {
    int a, b;

    Foo(int a, int b) {
        this.a = a;
        this.b = b;
    }
}

class Bar extends Foo {
    int c;

    Bar(int a, int b, int c) {
        // Тут super должен быть сверху, иначе ошибка
        super(a, b);
        this.c = c;
    }
}
```

#### *instanceof*

Позволяет проверить, создан ли объект на основе какого-то класса

```Java
class Foo {
    int a, b;

    Foo(int a, int b) {
        this.a = a;
        this.b = b;
    }
}

class Bar extends Foo {
    int c;

    Bar(int a, int b, int c) {
        // Тут super должен быть сверху, иначе ошибка
        super(a, b);
        this.c = c;
    }
}

class Main {
    public static void main() {
        Bar bar = new Bar();
        System.out.println(bar instanceof Foo);
    }
}
```

#### Абстрактные классы

Абстрактные классы могут иметь абстрактные методы (без имплементации), но от них низя создать объект.

```Java
abstract class Car {
    int speed;

    public int getSpeed() {
        return speed;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }

    abstract int brake();
}

class Sedan extends Car {
    @Override
    int brake() {
        return 5;
    }
}

public class Main {
    public static void main(String[] args) {
        Car car = new Car(); // Низя. Класс абстрактный
        Sedan sedan = new Sedan();
    }
}
```

### Интерфейсы

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

* Bird - абстрактный класс
* Flyable - интерфейс. Его могут имплементировать и птицы, и самолёты, и Карлсон

Отличия от классов:

* Нельзя создать экземпляр
* Не содержатся конструкторы
* Все методы абстрактные
* Все поля и  *static* и *final*
* Интерфейс не расширяется классом, а реализуется
* Интерфейс может расширить множество интерфейсов

```Java
public interface Swimmable {
    public void swim();
}

class Duck implements Swimmable {
    public void swim() {
        System.out.println("A duck is swimming");
    }
}
```

Могут быть определения по умолчанию

```Java
public interface Swimmable {
    default public void swim() {
        System.out.println("Something is swimming")
    }
}

class Duck implements Swimmable {}
```

### Классы обёртки

*Обёртка* - класс, хранящий внутри значение примитива. Эти классы содержат полезные методы и являются не изменяемыми

#### Автораспаковка, автоупаковка

```Java
int x = 5;
Integer y = x; // Автоупаковка
x = y; // Автораспаковка
```

Автоупаковка и автораспаковка не работает для массивов

## Коллекции

Основные виды:

* *Set*
  * *HashSet*
  * *TreeSet*
  * *SortedSet*
* *List*
  * *ArrayList*
  * *LinkedList*
  * *Vector*
  * *Stack*
* *Map*
  * *HashMap*
  * *TreeMap*
  * *SortedMap*
  * *Hashtable*

### Итераторы

Позволяет перебирать значения коллекций. Может использоваться для неупорядоченных коллекций

```Java
Set<String> set = new HashSet<String>();

set.add("A");
set.add("B");

Iterator<String> iter = set.iterator();

while (iter.hasNext()) {
    String text = iter.next();

    System.out.println(text);
}
```

```Java
Map<String, String> map = new HashMap<String, String>();

map.put("first", "A");

Iterator<Map.Entry<String, String>> iter = map.entrySet().iterator();

while (iter.hasNext()) {
    Map.Entry<String, String> pair = iter.next();

    String key = pair.getKey();
    String value = pair.getValue();

    System.out.println(key + ":" + value);
}
```

Можно использовать *foreach*

```Java
Set<String> set = new HashSet<String>();

set.add("A");
set.add("B");

for (String text : set) {
    System.out.println(text);
}
```

### ArrayList

```Java
ArrayList<Integer> nums = new ArrayList<int>();

nums.add(5);
nums.add(5);
nums.add(5);
nums.add(5);
nums.add(5);

System.out.println(nums.get(1));
System.out.println(nums.indexOf(5));
System.out.println(nums.contains(3));

nums.add(4, 3); // insert`ит на 4 индекс число 3
nums.set(4, 5); // Меняет число на 4 индексе на 5

System.out.println(nums.toString());
nums.clear();
nums.add(5);
nums.add(5);
nums.add(5);


Integer[] numss = nums.toArray(new Integer[0]);

nums = new ArrayList<>(Arrays.asList(numss));

Collections.sort(nums);
```

Ещё методы у Collections:

* *min*
* *max*
* *reverse*
* *shuffle*
* *swap*
* *disjoint* - если есть пересечение коллекций, то false, иначе true

#### Неизменяемый список

```Java
List<Integer> = Collections.unmodifiableList(new ArrayList<>(Arrays.asList(1, 2, 3)));
```

### LinkedList

*LinkedList* - двусвязный список

```Java
LinkedList<Integer> nums = new LinkedList<Integer>();

nums.add(5);
nums.add(5);
nums.add(5);
```

Особые методы:

* *addFirst*
* *addLast*
* *peekFirst*
* *peekLast*
* *pollFirst* - получить первый и удалить его (null, если пусто)
* *pollLast*

### Vector

*Vector* - синхронизированный *ArrayList*, который всё хранит как Object. Синтаксис страшный.

### Stack

*Stack* - LIFO

Методы:

* *empty* - возвращает bool
* *peek*
* *pop*
* *push*
* *search* - возвращает offset от вершины стека

### Deque

*Deque* - двунаправленный стек с фиксированной длинной

Методы:

* *addFirst*
* *addLast*
* *getFirst* - без удаления
* *getLast*
* *offerFirst*
* *offerLast*
* *peekFirst*
* *peekLast*
* *pollFirst* - с удалением
* *pollLast*

### ArrayDeque

*ArrayDeque* - двунаправленный стек с динамической длиной

Методы:

* *addFirst*
* *addLast*
* *getFirst* - без удаления
* *getLast*
* *pollFirst* - с удалением
* *pollLast*

### HashSet

Аля Rust. Использует метод hashCode() для получения хеша значений

Методы:

* add
* remove
* contains
* size
* clear
* isEmpty
* iterator

## Enum

```Java
enum Country {
    CANADA, NETHERLANDS
}

enum Country2 {
    CANADA("CAN"), NETHER("NTH"), ENGLAND
}
```

## Работа с файлами

* FileWriter
* FileReader

В конце их нужно закрывать

```Java
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) throws Exception {
        FileReader fr = new FileReader("Foo.txt");
        Scanner scanner = new Scanner(fr);
        ArrayList<String> words = new ArrayList<>();

        while (scanner.hasNext()) {
            words.add(scanner.next());
        }

        Collections.sort(words);

        System.out.println(words);
    }
}
```
