Поля и методы класса
Класс состоит из полей (данные) и методов (действия). Узнайте, как их объявлять, зачем нужен this, и как работают геттеры и сеттеры.
Поля: состояние объекта
Поля — это переменные, объявлённые внутри класса. Они хранят данные объекта. У каждого объекта КОПИЯ своих полей. Представьте форму для анкеты: форма одна (класс), но каждая заполненная анкета (объект) содержит свои данные.
public class Student {
String name;
int age;
double grade;
boolean active;
String email;
}
Здесь 5 полей: name (строка), age (целое число), grade (вещественное число), active (логическое), email (строка). Каждый объект типа Student будет иметь свои значения этих полей.
Student s1 = new Student();
s1.name = "Алиса";
s1.age = 20;
s1.grade = 4.5;
s1.active = true;
Student s2 = new Student();
s2.name = "Борис";
s2.age = 22;
s2.grade = 3.8;
s2.active = false;
Сравните: Алиса и Борис — два разных объекта. У Алисы name = "Алиса", а у Бориса — name = "Борис". Они не пересекаются.
Значения по умолчанию для полей
Если вы не задали значение поля при создании объекта, Java автоматически присваивает значение по умолчанию:
int,long,short,byte→ 0double,float→ 0.0boolean→ falsechar→ '\u0000' (нулевой символ)- Все ссылочные типы (String, объекты) → null
Student s = new Student();
System.out.println(s.name); // null
System.out.println(s.age); // 0
System.out.println(s.grade); // 0.0
System.out.println(s.active); // false
ВАЖНО: локальные переменные внутри методов НЕ имеют значений по умолчанию! Они обязаны быть инициализированы перед использованием, иначе компилятор выдаст ошибку.
public void doSomething() {
int x;
// System.out.println(x); // Ошибка компиляции!
x = 10;
System.out.println(x); // 10 — работает
}
Методы: поведение объекта
Методы — это функции внутри класса. Они описывают, что объект МОЖЕТ ДЕЛАТЬ. Методы определяют поведение объекта.
public class BankAccount {
String number;
String owner;
double balance;
void deposit(double amount) {
if (amount > 0) {
balance += amount;
System.out.println("Зачислено " + amount + " руб. Баланс: " + balance);
}
}
boolean withdraw(double amount) {
if (amount <= 0) {
System.out.println("Сумма должна быть положительной");
return false;
}
if (amount > balance) {
System.out.println("Недостаточно средств. Баланс: " + balance);
return false;
}
balance -= amount;
System.out.println("Списано " + amount + " руб. Баланс: " + balance);
return true;
}
void transfer(BankAccount target, double amount) {
if (this.withdraw(amount)) {
target.deposit(amount);
System.out.println("Перевод " + amount + " руб. выполнен");
}
}
void displayInfo() {
System.out.println("Счёт: " + number);
System.out.println("Владелец: " + owner);
System.out.println("Баланс: " + balance + " руб.");
}
}
Обратите внимание на структуру метода:
- Модификатор доступа (void, boolean) — что метод возвращает.
- Имя метода — что делает (deposit, withdraw, transfer).
- Параметры — входные данные (amount, target).
- Тело метода — логика между фигурными скобками.
Методы без возвращаемого значения используют void. Если метод должен что-то вернуть — укажите тип (boolean, int, String и т.д.).
Ключевое слово this
this — это ссылка на текущий объект. Представьте, что вы в команде: «Это Я делаю». Параметры метода могут иметь те же имена, что и поля. В этом случае this помогает различить их.
public class Person {
String name;
int age;
void setName(String name) {
this.name = name;
}
void setAge(int age) {
this.age = age;
}
void display() {
System.out.println("Имя: " + this.name + ", возраст: " + this.age);
}
}
Здесь this.name — это поле объекта, а name (без this) — это параметр метода. Без this компилятор не понял бы, что вы имели в виду.
Аналогия: вы в классе и говорите «дайте учебник». Учитель спрашивает: «Какой учебник — тот, что на парте, или тот, что у вас в руках?» Вы отвечаете: «Тот, что на парте» (= this.name = name).
this нельзя использовать в статических методах (static), потому что статические методы не привязаны к конкретному объекту. Подробнее об этом в уроке 5.
Геттеры и сеттеры
Геттеры (getters) — методы, которые ВОЗВРАЩАЮТ значение поля. Сеттеры (setters) — методы, которые УСТАНАВЛИВАЮТ значение поля.
Зачем нужны? Потому что поля обычно делаются private (об этом в уроке 4), а доступ к ним осуществляется через методы. Это позволяет контролировать, как читать и изменять данные.
public class Employee {
private String name;
private double salary;
public String getName() {
return name;
}
public void setName(String name) {
if (name != null && !name.isEmpty()) {
this.name = name;
}
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
if (salary > 0) {
this.salary = salary;
} else {
System.out.println("Зарплата не может быть отрицательной!");
}
}
}
Обратите внимание: сеттер setSalary проверяет значение перед установкой. Нельзя задать отрицательную зарплату. Это защита данных — инкапсуляция.
Соглашения об именовании:
- Геттер:
getИмяПоля()— например, getName(), getSalary() - Сеттер:
setИмяПоля(значение)— например, setName("Иван"), setSalary(50000) - Для boolean:
isИмяПоля()— например, isActive(), isOpen()
Бизнес-методы
Бизнес-методы — это методы, реализующие логику предметной области. Не просто get/set, а реальные действия.
public class Counter {
private int count;
private int min;
private int max;
public Counter(int min, int max) {
this.min = min;
this.max = max;
this.count = min;
}
public void increment() {
if (count < max) {
count++;
}
}
public void decrement() {
if (count > min) {
count--;
}
}
public void reset() {
count = min;
}
public int getCount() {
return count;
}
public boolean isMin() {
return count == min;
}
public boolean isMax() {
return count == max;
}
}
Counter c = new Counter(0, 10);
c.increment(); // count = 1
c.increment(); // count = 2
c.increment(); // count = 3
System.out.println(c.getCount()); // 3
c.reset();
System.out.println(c.getCount()); // 0
Ещё пример — класс Temperature:
public class Temperature {
private double celsius;
public Temperature(double celsius) {
this.celsius = celsius;
}
public double getCelsius() {
return celsius;
}
public void setCelsius(double celsius) {
this.celsius = celsius;
}
public double getFahrenheit() {
return celsius * 9.0 / 5.0 + 32;
}
public void setFahrenheit(double fahrenheit) {
this.celsius = (fahrenheit - 32) * 5.0 / 9.0;
}
public boolean isFreezing() {
return celsius <= 0;
}
public boolean isBoiling() {
return celsius >= 100;
}
public void display() {
System.out.printf("%.1f°C = %.1f°F%n", celsius, getFahrenheit());
}
}
Temperature t = new Temperature(37.5);
t.display(); // 37.5°C = 99.5°F
t.setFahrenheit(212);
t.display(); // 100.0°C = 212.0°F
System.out.println(t.isBoiling()); // true
Соглашения об именовании
Следование соглашениям об именовании — признак профессионального разработчика:
- Методы — глаголы: getName, calculateTotal, setAge, isRunning, hasChildren
- Поля — существительные: name, age, count, isOpen, maxCount
- camelCase — первое слово с маленькой буквы, остальные с большой: firstName, lastName, numberOfStudents
- Геттеры: getXxx() — например, getName(), getAge()
- Сеттеры: setXxx() — например, setName("Иван"), setAge(25)
- Булевы геттеры: isXxx(), hasXxx(), canXxx() — isActive(), hasChildren(), canEdit()
Хорошие имена — это документация. Метод calculateDiscountedPrice() понятен сразу. Метод calc() — нет. Всегда давайте осмысленные имена!
Полный пример: класс Rectangle
Давайте создадим класс Прямоугольник со всеми концепциями этого урока:
public class Rectangle {
private double width;
private double height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
public double getWidth() {
return width;
}
public void setWidth(double width) {
if (width > 0) {
this.width = width;
}
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
if (height > 0) {
this.height = height;
}
}
public double getArea() {
return width * height;
}
public double getPerimeter() {
return 2 * (width + height);
}
public boolean isSquare() {
return width == height;
}
public boolean isLandscape() {
return width > height;
}
public void display() {
System.out.printf("Прямоугольник: %.1f x %.1f%n", width, height);
System.out.printf(" Площадь: %.1f%n", getArea());
System.out.printf(" Периметр: %.1f%n", getPerimeter());
System.out.printf(" Квадрат: %s%n", isSquare() ? "да" : "нет");
}
}
Rectangle r1 = new Rectangle(5, 3);
r1.display();
Rectangle r2 = new Rectangle(4, 4);
r2.display();
System.out.println("Площадь r1: " + r1.getArea());
System.out.println("Площадь r2: " + r2.getArea());
Возврат значений из методов
Методы могут возвращать значения любого типа:
public class Calculator {
private double result;
public double add(double a, double b) {
return a + b;
}
public double subtract(double a, double b) {
return a - b;
}
public double multiply(double a, double b) {
return a * b;
}
public double divide(double a, double b) {
if (b == 0) {
System.out.println("Деление на ноль!");
return 0;
}
return a / b;
}
public int max(int a, int b) {
return a > b ? a : b;
}
public boolean isPositive(double number) {
return number > 0;
}
public String formatResult(double value) {
return "Результат: " + String.format("%.2f", value);
}
}
Обратите внимание: метод может возвращать int, double, boolean, String или любой другой тип. Главное — указать возвращаемый тип перед именем метода и использовать return.
Методы, вызывающие другие методы
Методы могут вызывать другие методы того же объекта. Это помогает избежать дублирования кода:
public class Circle {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
public double getArea() {
return Math.PI * radius * radius;
}
public double getCircumference() {
return 2 * Math.PI * radius;
}
public double getDiameter() {
return 2 * radius;
}
public void display() {
System.out.printf("Круг с радиусом %.1f%n", radius);
System.out.printf(" Диаметр: %.1f%n", getDiameter());
System.out.printf(" Длина окружности: %.1f%n", getCircumference());
System.out.printf(" Площадь: %.1f%n", getArea());
}
}
Circle c = new Circle(5);
c.display();
Метод display() вызывает getDiameter(), getCircumference() и getArea(). Это нормально — методы могут использовать друг друга.
Параметры методов: передача по значению
В Java параметры передаются по значению. Для примитивов — копируется значение. Для объектов — копируется ссылка.
public class Example {
static void changeValue(int x) {
x = 100; // Изменяет локальную копию
}
static void changeName(Dog dog) {
dog.name = "Новое имя"; // Изменяет объект через ссылку
}
public static void main(String[] args) {
int a = 5;
changeValue(a);
System.out.println(a); // 5 — не изменилось!
Dog d = new Dog();
d.name = "Старое имя";
changeName(d);
System.out.println(d.name); // "Новое имя" — объект изменился!
}
}
Для примитивов: передаётся копия значения. Изменение параметра внутри метода НЕ влияет на оригинал.
Для объектов: передаётся копия ссылки. Изменение полей объекта ВЛИЯЕТ на оригинал (объект один). Но переприсваивание параметра НЕ влияет на оригинал.
Практический пример: класс Student
public class Student {
private String name;
private int age;
private double[] grades;
private int gradeCount;
public Student(String name, int age, int maxGrades) {
this.name = name;
this.age = age;
this.grades = new double[maxGrades];
this.gradeCount = 0;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void addGrade(double grade) {
if (grade >= 0 && grade <= 5 && gradeCount < grades.length) {
grades[gradeCount] = grade;
gradeCount++;
}
}
public double getAverage() {
if (gradeCount == 0) return 0;
double sum = 0;
for (int i = 0; i < gradeCount; i++) {
sum += grades[i];
}
return sum / gradeCount;
}
public boolean isHonors() {
return getAverage() >= 4.5;
}
public String getStatus() {
double avg = getAverage();
if (avg >= 4.5) return "отличник";
if (avg >= 3.5) return "хорошист";
if (avg >= 2.5) return "троечник";
return "отстающий";
}
public void displayInfo() {
System.out.println("Студент: " + name);
System.out.println("Возраст: " + age);
System.out.printf("Средний балл: %.1f%n", getAverage());
System.out.println("Статус: " + getStatus());
}
}
Student s1 = new Student("Алиса", 20, 5);
s1.addGrade(5);
s1.addGrade(4);
s1.addGrade(5);
s1.addGrade(4);
s1.addGrade(5);
s1.displayInfo();
Student s2 = new Student("Борис", 22, 3);
s2.addGrade(3);
s2.addGrade(4);
s2.addGrade(3);
s2.displayInfo();
Передача объектов в методы
Объекты передаются в методы по ссылке (точнее — по значению ссылки). Изменение полей объекта влияет на оригинал:
public class BankService {
public static void transfer(BankAccount from, BankAccount to, double amount) {
if (from.withdraw(amount)) {
to.deposit(amount);
System.out.println("Перевод выполнен");
}
}
public static void printAccountInfo(BankAccount acc) {
System.out.println("Счёт: " + acc.getNumber());
System.out.printf("Баланс: %.2f%n", acc.getBalance());
}
}
BankAccount acc1 = new BankAccount("001", 10000);
BankAccount acc2 = new BankAccount("002", 5000);
BankService.transfer(acc1, acc2, 3000);
BankService.printAccountInfo(acc1); // 7000
BankService.printAccountInfo(acc2); // 8000
Возврат объектов из методов
Методы могут возвращать объекты:
public class UserFactory {
public static User createUser(String name, String email) {
return new User(name, email);
}
public static User createGuest() {
return new User("Гость", "guest@mail.com");
}
}
User u1 = UserFactory.createUser("Иван", "ivan@mail.com");
User u2 = UserFactory.createGuest();
Возвращаемый тип — имя класса (User), а не void. Метод создаёт объект и возвращает ссылку на него.
Массивы объектов
Массивы могут хранить объекты:
Student[] students = new Student[3];
students[0] = new Student("Алиса", 10);
students[1] = new Student("Борис", 11);
students[2] = new Student("Варвара", 10);
for (Student s : students) {
System.out.println(s.getName() + " — " + s.getGrade());
}
Типичные ошибки
public class Mistakes {
private String name;
// Ошибка 1: забыли this
void setName(String name) {
name = name; // Параметр присваивает себя себе!
}
// Правильно:
void setNameCorrect(String name) {
this.name = name;
}
// Ошибка 2: возврат из void-метода
void getValue() {
return 5; // Ошибка! void не должен ничего возвращать
}
// Ошибка 3: забыли return
int getValue2() {
int x = 5;
// return забыли! Ошибка компиляции
}
// Правильно:
int getValueCorrect() {
return 5;
}
}
Итоги урока
- Поля хранят состояние объекта; у каждого объекта своя копия.
- Методы определяют поведение объекта.
thisссылается на текущий объект (различает поле и параметр).- Геттеры/сеттеры обеспечивают контролируемый доступ к полям.
- Поля имеют значения по умолчанию (0, false, null).
- Локальные переменные обязаны быть инициализированы явно.
- Методы могут вызывать другие методы того же объекта.
- Следуйте соглашениям об именовании: camelCase, глаголы для методов.
Следующий урок: Конструкторы — специальные методы для инициализации объектов.
Тест: Поля и методы класса
10 вопросов