05. Статика
Статические методы
Бывают случаи, когда метод не использует ни одного поля класса. В таких случаях его делают статическим. Статический метод - это метод, который можно вызвать без создания экземпляра класса. Такие методы вызываются непосредственно от класса, а не от объекта (его экземпляра).
Например, Math.sqrt()
- статический метод, потому что Math
– это класс. Он сделан статическим,
т. к. не завязан на характеристиках объекта, поэтому он не создаётся.
Можно провести аналогию: обычные методы и поля - это локальные переменные, определённые внутри объекта, а статические поля и методы - глобальные, они определены для самого класса.
Но это накладывает определённые ограничения: статические элементы могут взаимодействовать только со статическими переменными. Статические методы и поля создаются во время компиляции самого класса, а обычные поля - только при создании объекта, т. е. гарантированно позже, во время исполнения кода.
Для примера рассмотрим класс двухмерного вектора. Если мы хотим написать метод, который бы складывал два вектора и возвращал бы их сумму, то нам не нужно привязывать метод к конкретному объекту, а значит, он должен быть статическим.
Чтобы сделать метод статическим, нужно при объявлении метода написать ключевое слово static
:
- Main.java
- Vector2.java
package com.company;
public class Main {
public static void main(String[] args) {
Vector2 v1 = new Vector2(1,4); // [1,4]
Vector2 v2 = new Vector2(-1,1); // [-1,1]
Vector2 v3 = Vector2.sum(v1,v2); // [0,5]
}
}
package com.company;
// класс вектора
public class Vector2 {
// x - координата
public double x;
// x - координата
public double y;
// конструктор
public Vector2(double x, double y) {
this.x = x;
this.y = y;
}
// сумма двух векторов
public static Vector2 sum(Vector2 a, Vector2 b) {
return new Vector2(a.x + b.x, a.y + b.y);
}
}
Константы
Вторым методом, который мы разберём, будет метод умножения вектора на константу. Но задача состоит в том, чтобы написать независимый метод: в аргументе мы передаём вектор, который надо умножить, а метод нам возвращает новый вектор, равный исходному, умноженному на константу.
- Main.java
- Vector2.java
public static void main(String[] args) {
Vector2 v1 = new Vector2(1,4); // [1,4]
Vector2 v2 = new Vector2(-1,1); // [-1,1]
Vector2 v4 = Vector2.modify(v1); // [5,20]
}
}
package com.company;
// класс вектора
public class Vector2 {
// константа
private static double k = 5;
// x - координата
public double x;
// x - координата
public double y;
// конструктор
public Vector2(double x, double y) {
this.x = x;
this.y = y;
}
// сумма двух векторов
public static Vector2 sum(Vector2 a, Vector2 b) {
return new Vector2(a.x + b.x, a.y + b.y);
}
// домножение вектора на константу
public static Vector2 modify(Vector2 v) {
return new Vector2(v.x * k, v.y * k);
}
}
В классическом смысле константы простым добавлением ключевого слова final
не создаются,
ведь константа должна быть глобальной, а не привязанной к конкретному объекту. Поэтому константы
в классическом смысле создаются при помощи комбинации ключевых слов static
и final
.
Т.е. чтобы сделать коэффициент k
из прошлого примера константой, достаточно изменить
переписать его объявление следующим образом:
private static final double k = 5;
Если вы хотите запретить переопределять метод в классах-потомках, вам также нужно
использовать ключевое слово final
:
public final int f(){
...
}
Метод f()
будет доступен отовсюду, но при этом в классах-потоках изменять
его реализацию будет запрещено.
Блок статической инициализации
Статический блок инициализации можно назвать статическим конструктором. Ведь конструктор - это метод объекта, а статика подразумевает работу без объектов. Поэтому, чтобы выполнить ряд операций при создании класса, например, вычисление коэффициентов, инициализацию констант и т.д., создан специальный блок статической инициализации. Он выполняется при первом обращении к классу.
Этот блок создаётся достаточно просто: в теле класса нужно написать ключевое слово static
, после чего разместить
весь код статической инициализации в фигурных скобках:
....
// класс вектора
public class Vector2 {
// константа
public static double k;
// блок статической инициализации
static {
k = 5;
}
...
Математика
Поворот вектора на угол :
Длина вектора равна
Нормированный вектор сонаправлен с исходным и при этом его длина равна .
Задание
В качестве задания вам необходимо написать требуемые классы либо решить задачу с их использованием. Система совмещает ваш код со своим и запускает тестирование.
Прочитайте внимательно, что именно нужно отправить в тот или иной тест.
Часть вывода в консоль система выполняет за вас. Вам нужно выводить только то, что требуется в задании.