This repository has been archived on 2024-08-23. You can view files and clone it, but cannot push or open issues or pull requests.
lessons/Java/Java.md
2024-06-03 17:00:44 +03:00

32 KiB
Raw Permalink Blame History

Java

Функция main

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). Для изменения копии

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

StringBuffer и StringBuilder

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

// Можно передать строку в инициализатор, но не обязательно
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

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

Var

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

var x = 5;

Константы

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

final int LIMIT = 5;

Массивы

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

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

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

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

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

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

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

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

Их нету!!!

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

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

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

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

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

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

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

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

try-catch-finally

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

throw

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

throws

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

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

OOP

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

public class Foo {
    int bar;
    string baz;

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

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

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

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

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

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

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

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

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

public class Foo {}

public class Bar extends Foo {}

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

Override

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

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

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

super

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

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

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

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

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

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

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

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

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

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

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

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
  • Интерфейс не расширяется классом, а реализуется
  • Интерфейс может расширить множество интерфейсов
public interface Swimmable {
    public void swim();
}

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

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

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

class Duck implements Swimmable {}

Могут быть статические и приватные (доступные только внутри интерфейса) методы и константы

public interface Foo {
    int VALUE = 5; // Подразумевается public static final т.е. публичная константная

    static void foo() {
        System.out.println("Foo");
    }

    private int bar(int a, int b) {
        return a + b;
    }
}

class Bar implements Foo {}

Интерфейсы могут расширять друг друга

interface Foo {
    void foo();
}

interface Bar extends Foo {
    default void bar() {
        return;
    }
}

class Baz implements Bar {
    public void foo() {}
}

Интерфейсы могут быть вложены в классы

class Printer {
    interface Printable {
        void print();
    }
}

class Journal implements Printer.Printable {
    public void print() {
        System.out.println("Priniting journal");
    }
}

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

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

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

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

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

Коллекции

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

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

Итераторы

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

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

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

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

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

ArrayList

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

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

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

LinkedList

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

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

enum Country {
    CANADA, NETHERLANDS
}

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

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

  • FileWriter
  • FileReader

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

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

Generic

class Account<T> { // Account<String> account = new Account<String>("FooBar");
    private T id;
    public int sum;

    public Account(T id, int sum) {
        this.id = id;
        this.sum = sum;
    }

    public T getId() {
        return id;
    }
}

class Printer {
    public static <T> void print(T[] items) { // Вызывать так: Printer.<String>print(new String[]{"a", "b"});
        for(T item: items) {
            System.out.println(item);
        }
    }
}

interface Acountable {
    String getId();
}

class Account2 implements Acountable {
    String id;

    public <T>Account2(T id) { // Account account = new Account(5);
        this.id = id.toString();
    }

    public String getId() {
        return id;
    }
}

class Transaction<T extends Account> { // T может быть только наследником Account
    T account;
}

class Transaction2<T extends Acountable> { // T имплементирует Acountable
    T account;
}

class Transaction3<T extends Account & Accountable> { // T имплементирует Accountable и наследует Account
    T account;
}

Records

Записи или Records позволяют быстро содздавать классы, уменьшая количесво бойлерплейта. Записи автоматически определяют инициализатор, методы hashCode, toString и equals. Поля являются private и final и имеют одноимённые геттеры

record Person(String name, int age) { }

Можно добавить дополнительную логику в созданный конструктор

record Person(String name, int age) {
    Person {
        if(age < 1 || age > 110) {
            age = 18;
        }
    }
}

Можно полностью переписать изначальный конструктор

record Person(String name, int age) {
    Person(String name, int age) {
        this.name = name;
        if(age < 1 || age > 110) {
            age = 18;
        }
        this.age = age;
    }
}

Мы можем определять какие-то другие конструкторы, но они вызывать канонический конструктор

record Person(String name, int age) {
    Person(String firstName, String lastName, int age) {
        this(firstName + " " + lastName, age);
    }
}

Можно также переопределить остальные методы

record Person(String name, int age) {
    public String name() {
        return "Mister " + name;
    }

    public String toString() {
        return "What a fine gentleman we have here"
    }
}

Ограничения record

Классы record не могут наследовать, быть наследованными и абстрактными, но могут имплементировать интерфейсы. Нельзя добавлять дополнительные нестатические пора и инициализаторы

record Person(String name, int age) {
    static int minAge;

    static { // Это статический инициализатор
        minAge = 18;
    }
}

Upcasting & Downcasting

class Person {}

class Employee {}

class Main {
    public static void main(String[] args) {
        Object bob = new Person(); // Upcasting
        Person tom = new Employee(); // тоже upcasting
        Person bob2 = (Person)bob;
    }
}

Comparator & Comparable

import java.util.Comparator;
import java.util.TreeSet;

class Person implements Comparable<Person> {
    private String name;
    private int age;

    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    String getName() {
        return name;
    }

    int getAge() {
        return age;
    }

    // Отриц число, если меньше, 0, если равно, и полож число, если больше
    public int compareTo(Person p) {
        return name.compareTo(p.getName());
    }
}

class PersonNameComparator implements Comparator<Person> {
    public int compare(Person a, Person b) {
        return a.getName().compareTo(b.getName());
    }
}

class PersonAgeComparator implements Comparator<Person> {
    public int compare(Person a, Person b) {
        return a.getAge() - b.getAge();
    }
}

class Main {
    public static void main(String[] args) {
        Comparator<Person> pcomp = (new PersonNameComparator()).thenComparing(new PersonAgeComparator());
        TreeSet<Person> people = new TreeSet<Person>(pcomp);
        people.add(new Person("Tom", 10));
        people.add(new Person("Tam", 12));
        people.add(new Person("Tim", 13));
        people.add(new Person("Bill", 40));
        people.add(new Person("Bob", 15));
        for(Person p : people) {
            System.out.println(p.getName());
        }
    }
}

Лямбда

Лямбда представляет набор инструкций,которые можно выделить в отдельную переменную

public class Main {
    public static void main(String[] args) {
        Operation op = (x, y) -> x + y;
        Operation op2 = (int x, int y) -> x - y;

        int result = op.calculate(10, 20);
        System.out.println(result);
        System.out.println(op.calculate(10, 20));
    }
}

interface Operation {
    int calculate(int x, int y);
}

Альтернативные формы:

  • () -> 30 + 30

  • n -> n * n

Лямбда функции могут возвращать void

interface Printer {
    void print(String s);
}

class Main {
    public static void main(String[] args) {
        Printer p = (s) -> System.out.println(s);
    }
}

Переменные, которые используются в лямбде нельзя менять

Блоки кода в лямбда-функциях

public class Main {
    public static void main(String[] args) {
        Operation op = (int x, int y) -> {
            if(x < 0) {
                x = -x;
            }
            return x + y;
        };
    }
}

interface Operation {
    int calculate(int x, int y);
}

Обобщённые лямбды

public class Main {
    public static void main(String[] args) {
        Operation<Integer> op = (x, y) -> {
            if(x < 0) {
                x = -x;
            }
            return x + y;
        };
    }
}

interface Operation<T> {
    T calculate(T x, T y);
}

Ссылки на метод, как параметр методов

interface Operation {
    int calculate(int x, int y);
}

class Operations {
    static int Add(int x, int y) {
        return x + y;
    }
}

class Main {
    public static void main(String[] args) {
        Operation op = Operations::Add;
    }
}

Также можно ссылаться на методы объекта, через переменная::метод, и на конструктор, через класс::new. Лямбды также можно возврощать

Встроенные функцианальные интерфейсы

  • Predicate<T> - boolean test(T t)
  • BinaryOperator<T> - T apply(T t1, T t2)
  • UnaryOperator<T> - T apply(T t)
  • Function<T, R> - R apply(T t)
  • Consumer<T> - void accept(T t)
  • Supplier<T> - T get()

Java.Util

Класс Locale

Локали - боль... страдания... C++

Locale.getDefault() чтобы получить текущую

Date

Date - штука для работы с датами. Можно использовать для форматирования с помощью Locale

Calendar & GregorianCalendar

Calendar - абстрактный класс, а GregorianCalendar - имплементация. Он также держит часы, минуты, секунды. Класс DateFormat для красивого вывода

TimeZone & SimpleTimeZone

Calendar - абстрактный класс, а GregorianCalendar - имплементация. Он также держит часы, минуты, секунды. Нужны для работы с часовыми поясами

UUID

UUID - класс для работы с UUID

UUID id = UUID.randomUUID();

StringTokenizer

StringTokenizer нужен для разделения строк на токены, используя данный разделитель (по умолчанию пробел)

Android Studio

Устройство платформы Android

  • Базовый уровень (Linux Kernel) - firmware
  • Библиотеки и среда исполнения (Libraries & Android Runtime)
  • Каркас приложений (Application Framework)
  • Уровень приложений (Applications)

Комплекты разработчика

  • JDK (Java Development Kit) - комплект разработчика на Java. Включает компилятор, библиотеки, примеры, документацию, утилиты и исполнительную среду
  • SDK (Software Development Kit) - утилиты для создания и тестирования приложений
  • SDK Manager - инструмент для заргузки компонентов Android SDK
  • Android Emulator - эмулирует телефон на компьютере
  • AVD Manager - графический интерфейс для создания виртуальных Android устройст
  • Android Debig Bridge - управление состоянием эмулятора или реального устройства, подключённого к компьютеру

Структура Android приложения

  • Gen файлы генерируются Java. Являются обязательным компонентом
  • AndroidManifest.xml - файл манифеста предоставляет системе лсновную информацию о программе
  • Src - каталог с исходным компонентом
  • Assets - произвольное собрание каталогов и файлов
  • Res - катагол с ресурсами прилодения. Там подкапки drawable, anum, layout, menu, values, xml и raw

Инициализация объектов Activity

package com.example.myapplication;

import androidx.appcompat.app.AppCompatActivity;

import android.graphics.Color;
import android.os.Bundle;
import android.view.View;

import com.example.myapplication.databinding.ActivityMainBinding;

public class MainActivity extends AppCompatActivity {
    private ActivityMainBinding binding;
    int counter = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityMainBinding.inflate(getLayoutInflater());
        View view = binding.getRoot();
        setContentView(view);

        binding.textView.setText("0");
        binding.textView.setTextSize(33);
        binding.textView.setTextColor(Color.RED);

        binding.button.setOnClickListener((foo) -> {
            counter += 1;
            binding.textView.setText(String.valueOf(counter));
        });
    }
}

Переключение Activity

Intent intent = new Intent(MainActivity.this, SecondActivity.class);
startActivity(intent);

Fragments

Fragment - подобие activity, но одно activity может содержать несколько фрагментов.

Для взаимодействия фрагментов используется FragmentManager, а для удаления, добавления и замены FragmentTransaction

Основные методы FragmentManager:

  • findFragmentById(int id)
  • findFragmentByTag(String tag)

Методы FragmentTransaction:

  • add
  • remove
  • replace
  • hide
  • show
  • detach - открепляет от GUI, но экземпляр сохраняется
  • attach - обратный метод detach

Для получения экземляра FragmentTransaction нужно вызвать FragmentManager.beginTransaction. После транзакции вызывается commit

Адаптеры

  • ArrayAdapter<T>
  • ListAdapter
  • SpinnerAdapter
  • SimpleAdapter

LayoutInflater

Позволяет из содержимого layout файла создать View элемент

Spring

Аннотации

  • @Component - помечает класс как bean (зависимость, которую можно использовать в проекте)
  • @Autowired - автоматически ещет зависимости метода, конструктора и поля
  • @Primary - помечает приорететный bean для @Autowired
  • @Scope("singleton" | "prototype")
  • @PostConstruct
  • @PreDestroy
  • @Controller - просто контроллер (контроллер тоже bean)
  • @RestController - помечает класс как Bean и содержит анотацию @ResponseBody, позволяющюю преобразовывать в Json любой возвращаемый объект
  • @RequestMapping(route) - позволяет запросы на методы контроллеров. Пример route - "/users/v1/"
  • @Service - помечает класс с бизнес-логикой

Qualifier

Позволяет указатать какой класс использовать для интерфейса, когда Primary не подходит. Все qualifier с маленькой буквы

public MusicPlauer(@Qualifier("rockMusic") Music music) {
    music.playMusic();
}

Lombok

Генерирует геттеры и сеттеры

  • @Getter

  • @Setter

  • @NoArgsConstructor

  • @AllArgsConstructor

  • @RequiredArgsConstructor

  • @Data* включает все вышеперечисленные

Jakatra validation

  • @NotNull подтверждает, что значение аннотированного свойства не является нулевым.
  • @AssertTrue подтверждает, что значение аннотированного свойства является истинным.
  • @Size проверяет, что аннотированное значение свойства имеет размер между атрибутами min и max. Мы можем применить его к свойствам String, Collection, Map и Array.
  • @Min проверяет, что аннотированное свойство имеет значение не меньше, чем атрибут value.
  • @Max проверяет, что аннотированное свойство имеет значение не больше, чем атрибут value.
  • @Email подтверждает, что аннотированное свойство является действительным адресом электронной почты. Некоторые аннотации принимают дополнительные атрибуты, но атрибут сообщения является общим для всех из них. Это сообщение, которое обычно отображается, когда значение соответствующего свойства не проверяется.
  • @NotEmpty подтверждает, что свойство не является нулевым или пустым. Мы можем применить его к значениям String, Collection, Map или Array.
  • @NotBlank может быть применен только к текстовым значениям и проверяет, что свойство не является нулевым или пробелом.
  • @Positive и @PositiveOrZero применяются к числовым значениям и подтверждают, что они строго положительные или положительные, включая 0.
  • @Negative и @NegativeOrZero применяются к числовым значениям и подтверждают, что они строго отрицательные или отрицательные, включая 0.
  • @Past и @PastOrPresent подтверждают, что значение даты находится в прошлом или в прошлом, включая настоящее. Мы можем применить его к типам дат, в том числе к тем, которые добавлены в Java 8.
  • @Future и @FutureOrPresent подтверждают, что значение даты находится в будущем или в будущем, включая настоящее.\

Базы данных

  • JPA описывает взаимодействие с Бд
  • Hibernate - ORM
  • Spring Data - унифицированный способ создания репозиториев для хранилищ разных типов