32 KiB
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 - унифицированный способ создания репозиториев для хранилищ разных типов