# 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 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 {} ``` Интерфейсы могут расширять друг друга ```Java interface Foo { void foo(); } interface Bar extends Foo { default void bar() { return; } } class Baz implements Bar { public void foo() {} } ``` Интерфейсы могут быть вложены в классы ```Java class Printer { interface Printable { void print(); } } class Journal implements Printer.Printable { public void print() { System.out.println("Priniting journal"); } } ``` ### Классы обёртки *Обёртка* - класс, хранящий внутри значение примитива. Эти классы содержат полезные методы и являются не изменяемыми #### Автораспаковка, автоупаковка ```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 set = new HashSet(); set.add("A"); set.add("B"); Iterator iter = set.iterator(); while (iter.hasNext()) { String text = iter.next(); System.out.println(text); } ``` ```Java Map map = new HashMap(); map.put("first", "A"); Iterator> iter = map.entrySet().iterator(); while (iter.hasNext()) { Map.Entry pair = iter.next(); String key = pair.getKey(); String value = pair.getValue(); System.out.println(key + ":" + value); } ``` Можно использовать *foreach* ```Java Set set = new HashSet(); set.add("A"); set.add("B"); for (String text : set) { System.out.println(text); } ``` ### ArrayList ```Java ArrayList nums = new ArrayList(); 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 = Collections.unmodifiableList(new ArrayList<>(Arrays.asList(1, 2, 3))); ``` ### LinkedList *LinkedList* - двусвязный список ```Java LinkedList nums = new LinkedList(); 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 words = new ArrayList<>(); while (scanner.hasNext()) { words.add(scanner.next()); } Collections.sort(words); System.out.println(words); } } ``` ## Generic ```Java class Account { // Account account = new Account("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 void print(T[] items) { // Вызывать так: Printer.print(new String[]{"a", "b"}); for(T item: items) { System.out.println(item); } } } interface Acountable { String getId(); } class Account2 implements Acountable { String id; public Account2(T id) { // Account account = new Account(5); this.id = id.toString(); } public String getId() { return id; } } class Transaction { // T может быть только наследником Account T account; } class Transaction2 { // T имплементирует Acountable T account; } class Transaction3 { // T имплементирует Accountable и наследует Account T account; } ``` ## Records > Записи или Records позволяют быстро содздавать классы, уменьшая количесво бойлерплейта. Записи автоматически определяют инициализатор, методы hashCode, toString и equals. Поля являются *private* и *final* и имеют одноимённые геттеры ```Java record Person(String name, int age) { } ``` Можно добавить дополнительную логику в созданный конструктор ```Java record Person(String name, int age) { Person { if(age < 1 || age > 110) { age = 18; } } } ``` Можно полностью переписать изначальный конструктор ```Java record Person(String name, int age) { Person(String name, int age) { this.name = name; if(age < 1 || age > 110) { age = 18; } this.age = age; } } ``` Мы можем определять какие-то другие конструкторы, но они вызывать канонический конструктор ```Java record Person(String name, int age) { Person(String firstName, String lastName, int age) { this(firstName + " " + lastName, age); } } ``` Можно также переопределить остальные методы ```Java 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* не могут наследовать, быть наследованными и абстрактными, но могут имплементировать интерфейсы. Нельзя добавлять дополнительные нестатические пора и инициализаторы ```Java record Person(String name, int age) { static int minAge; static { // Это статический инициализатор minAge = 18; } } ``` ## Upcasting & Downcasting ```Java 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 ```Java import java.util.Comparator; import java.util.TreeSet; class Person implements Comparable { 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 { public int compare(Person a, Person b) { return a.getName().compareTo(b.getName()); } } class PersonAgeComparator implements Comparator { public int compare(Person a, Person b) { return a.getAge() - b.getAge(); } } class Main { public static void main(String[] args) { Comparator pcomp = (new PersonNameComparator()).thenComparing(new PersonAgeComparator()); TreeSet people = new TreeSet(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()); } } } ``` ## Лямбда > Лямбда представляет набор инструкций,которые можно выделить в отдельную переменную ```Java 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 ```Java interface Printer { void print(String s); } class Main { public static void main(String[] args) { Printer p = (s) -> System.out.println(s); } } ``` Переменные, которые используются в лямбде нельзя менять ### Блоки кода в лямбда-функциях ```Java 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); } ``` ### Обобщённые лямбды ```Java public class Main { public static void main(String[] args) { Operation op = (x, y) -> { if(x < 0) { x = -x; } return x + y; }; } } interface Operation { T calculate(T x, T y); } ``` ## Ссылки на метод, как параметр методов ```Java 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\* - *boolean test(T t)* * *BinaryOperator\* - *T apply(T t1, T t2)* * *UnaryOperator\* - *T apply(T t)* * *Function\* - *R apply(T t)* * *Consumer\* - *void accept(T t)* * *Supplier\* - *T get()* ## *Java.Util* ### Класс *Locale* > Локали - боль... страдания... *C++* *Locale.getDefault()* чтобы получить текущую ### *Date* > *Date* - штука для работы с датами. Можно использовать для форматирования с помощью *Locale* ### *Calendar* & *GregorianCalendar* > *Calendar* - абстрактный класс, а *GregorianCalendar* - имплементация. Он также держит часы, минуты, секунды. Класс *DateFormat* для красивого вывода ### *TimeZone* & *SimpleTimeZone* > *Calendar* - абстрактный класс, а *GregorianCalendar* - имплементация. Он также держит часы, минуты, секунды. Нужны для работы с часовыми поясами ### *UUID* > *UUID* - класс для работы с UUID ```Java 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 ```Java 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 ```Java 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\* * *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 с маленькой буквы ```Java 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 - унифицированный способ создания репозиториев для хранилищ разных типов