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
2023-12-03 14:53:17 +03:00

26 KiB
Raw 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));
        });
    }
}