Классы и объекты в Java
Класс в Java — это шаблон (описание), по которому создаются объекты. Объект — это конкретный экземпляр класса, созданный оператором new и занимающий собственную память. Класс пишется один раз, объектов по нему можно создать сколько угодно, и у каждого будет свой набор значений полей.
1. Что такое объект и класс в Java
Класс определяет структуру и поведение, общие для набора объектов. Класс содержит переменные (поля) и методы — их называют членами класса, или элементами класса. Именно класс составляет основу инкапсуляции в Java: данные и работающий с ними код объединены в одной сущности.
Объект (экземпляр класса) получает всю структуру и поведение, описанные в классе. Каждый объект хранит собственную копию полей, поэтому два объекта одного класса могут иметь разные значения.
Методы описывают, что объект умеет делать или что можно с ним сделать. Поля (переменные экземпляра) описывают свойства и характеристики объекта.
Рассмотрим картинку ниже. Объявлен класс Student, у которого есть поля name и id, а также методы setName() и setId() для установки этих значений. На основе этого класса созданы объекты: Anna, Leo, Sara, Max. У каждого объекта, то есть у каждого студента, есть name и id, но значения у них разные.

Чем класс отличается от объекта: таблица
| Признак | Класс | Объект |
|---|---|---|
| Что это | Описание, шаблон, тип данных | Конкретный экземпляр, созданный по шаблону |
| Когда появляется | При написании и компиляции кода | Во время выполнения программы, после new |
| Память | Описание класса загружается JVM один раз | Каждый объект занимает свой участок в куче (heap) |
| Количество | Один класс на одно описание | Сколько угодно экземпляров одного класса |
| Как выглядит в коде | class Box { double width; } | Box myBox = new Box(); |
Бытовая аналогия: класс — это чертёж дома, объект — построенный по чертежу дом. По одному чертежу можно построить сто домов, и цвет стен у каждого будет свой.
2. Как создать класс в Java
Упрощённая общая форма определения класса:
class ИмяКласса {
тип переменнаяЭкземпляра1;
тип переменнаяЭкземпляра2;
// ...
тип переменнаяЭкземпляраN;
тип имяМетода1(список параметров) {
// тело метода
}
тип имяМетода2(список параметров) {
// тело метода
}
…
тип имяМетодаN(список параметров) {
// тело метода
}
}
После ключевого слова class пишется имя класса. В теле класса объявляются поля и методы. Их может быть сколько угодно, порядок объявления значения не имеет.
Опишем класс для объекта Box (коробка). У коробки есть три главные характеристики: ширина, высота и глубина. Сохраните этот класс в отдельном файле Box.java — имя public-класса обязано совпадать с именем файла:
public class Box {
double width;
double height;
double depth;
} Важно
В учебных примерах поля width, height, depth оставлены открытыми, чтобы не отвлекаться на лишний код. В реальном проекте поля объявляют private и дают доступ через методы — это и есть инкапсуляция. Подробнее в уроке управление доступом.
3. Создание объекта: оператор new
Объявление класса создаёт только шаблон, но не конкретный объект. Чтобы создать объект класса Box, используется оператор new:
Box myBox = new Box(); При создании экземпляра класса появляется объект, который содержит собственную копию каждой переменной экземпляра, определённой в данном классе.
Создание объекта класса представляет собой двухэтапный процесс:
- Объявление переменной типа класса. Эта переменная ещё не содержит объект. Она лишь может ссылаться на объект:
Box myBox; - Создание объекта оператором
new. Динамически (то есть во время выполнения) резервируется память под объект и возвращается ссылка на него:myBox = new Box();

Сам объект размещается в области памяти под названием куча (heap), а переменная myBox хранит только ссылку на него. Как устроена память JVM, разобрано в уроке структура памяти.
Круглые скобки в new Box() — это вызов конструктора. Если в классе не написан ни один конструктор, компилятор добавляет конструктор без параметров автоматически.
Сразу после создания объекта всем его полям присваиваются значения по умолчанию для их типа: 0 для чисел, false для boolean, null для ссылочных типов. Чтобы прочитать или изменить поле, используется имя переменной, точка и имя поля:
public class BoxExample1 {
public static void main(String[] args) {
Box myBox = new Box();
// присвоить значения полям объекта myBox
myBox.width = 10;
myBox.height = 20;
myBox.depth = 15;
// рассчитать объем параллелепипеда
double volume = myBox.width * myBox.height * myBox.depth;
System.out.println("Объем равен " + volume);
}
}
Объем равен 3000.0 В следующем примере объявляются два объекта класса Box, и каждому устанавливаются свои значения. Изменения полей одного объекта не влияют на поля другого:
public class BoxExample7 {
public static void main(String[] args) {
Box myBox1 = new Box();
Box myBox2 = new Box();
double volume;
// присвоить значения полям объекта myBox1
myBox1.width = 10;
myBox1.height = 20;
myBox1.depth = 15;
// присвоить другие значения полям объекта myBox2
myBox2.width = 3;
myBox2.height = 6;
myBox2.depth = 9;
// рассчитать объем первой коробки
volume = myBox1.width * myBox1.height * myBox1.depth;
System.out.println("Объем myBox1 равен " + volume);
// рассчитать объем второй коробки
volume = myBox2.width * myBox2.height * myBox2.depth;
System.out.println("Объем myBox2 равен " + volume);
}
} Объем myBox1 равен 3000.0
Объем myBox2 равен 162.0 Обратите внимание
Значения по умолчанию получают только поля объекта и статические поля. Локальные переменные внутри метода не инициализируются автоматически: попытка прочитать такую переменную до присваивания — ошибка компиляции «variable might not have been initialized».
4. Присваивание переменным ссылок на объекты
Возможна ситуация, когда две переменные указывают на один и тот же объект в памяти:

Разберём, как это происходит. При объявлении переменной b1 создаётся новый объект в памяти. При объявлении переменной b2 новый объект не создаётся — переменной присваивается ссылка на тот же объект, что и у b1. Далее объекту, на который указывает b1, присваиваются значения 10, 20 и 15. А ширине объекта, на который указывает b2, присваивается значение 3:
public class BoxExample6 {
public static void main(String[] args) {
Box b1 = new Box();
Box b2 = b1;
b1.width = 10;
b1.height = 20;
b1.depth = 15;
b2.width = 3;
System.out.println("Width: " + b1.width);
System.out.println("Width: " + b2.width);
}
} Обе переменные указывают на один и тот же объект, поэтому результат выполнения программы будет таким:
Width: 3.0
Width: 3.0 Когда две переменные ссылаются на один объект, изменение через любую из них видно через обе. Важно понимать: b2 = b1 копирует ссылку, а не сам объект. Чтобы получить независимую копию, объект нужно создать заново или клонировать.
5. Добавляем методы в класс
Кроме полей класс может содержать методы, которые позволяют скрыть детали реализации и избежать дублирования кода. Добавим в класс Box два метода: getVolume() — для вычисления объёма коробки и setDim() — для установки размеров. Обратите внимание: методы объявлены нестатическими (без ключевого слова static), поэтому внутри них доступны поля конкретного объекта.
public class Box {
double width;
double height;
double depth;
/**
* Подсчитать объем коробки
*
* @return Объем
*/
double getVolume() {
return width * height * depth;
}
/**
* Установить размер коробки
*
* @param w - ширина
* @param h - высота
* @param d - глубина
*/
void setDim(double w, double h, double d) {
width = w;
height = h;
depth = d;
}
} В следующей программе создаются два объекта класса Box. Вместо того чтобы присваивать значения каждому полю напрямую, вызывается метод setDim(), куда передаются ширина, высота и глубина. Программа становится компактнее. Нестатический метод всегда вызывается для конкретного объекта, поэтому объём считаем отдельно для каждой коробки:
public class BoxExample2 {
public static void main(String[] args) {
Box myBox1 = new Box();
Box myBox2 = new Box();
myBox1.setDim(10, 20, 15);
myBox2.setDim(1, 5, 5);
System.out.println("Объем: " + myBox1.getVolume());
System.out.println("Объем: " + myBox2.getVolume());
}
} Объем: 3000.0
Объем: 25.0 Внутри метода setDim() параметры названы w, h, d, чтобы не совпадать с именами полей. Если назвать параметры так же, как поля (width, height, depth), понадобится ключевое слово this: this.width = width;.
6. Класс Object — общий предок всех классов
Класс Box написан «с нуля» и ничего не наследует явно. Тем не менее у его объектов уже есть методы: любой класс в Java неявно наследуется от класса java.lang.Object. Запись class Box {} компилятор понимает как class Box extends Object {}.
Поэтому у объекта myBox сразу доступны методы класса Object. Самые востребованные:
toString()— строковое представление объекта. По умолчанию возвращает что-то вродеBox@1b6d3586(имя класса и хеш-код в шестнадцатеричном виде).equals(Object obj)— сравнение объектов. По умолчанию сравнивает ссылки, то есть работает так же, как==.hashCode()— целочисленный хеш-код, нужен для работыHashMapиHashSet.getClass()— возвращает объектClassс информацией о типе во время выполнения.clone(), а такжеwait(),notify(),notifyAll()для работы с потоками.
Box myBox = new Box();
System.out.println(myBox); // Box@1b6d3586 - вызвался toString()
System.out.println(myBox.getClass()); // class Box
System.out.println(myBox.equals(myBox)); // true Методы toString(), equals() и hashCode() почти всегда переопределяют в своих классах. Подробный разбор — в уроке класс Object.
7. Где чаще всего ошибаются новички
- Обращение к полю без создания объекта. Строка
Box myBox;объявляет только ссылку. Попытка выполнитьmyBox.width = 10;безnewприведёт к ошибке компиляции (переменная не инициализирована) либо, если ссылке присвоенnull, кNullPointerExceptionво время выполнения. - Сравнение объектов через
==. Оператор==сравнивает ссылки, а не содержимое. Два разных объекта с одинаковыми полями дадутfalse. Для сравнения по значению используйте equals(). - Путаница между копией ссылки и копией объекта.
Box b2 = b1;не создаёт вторую коробку, оба имени указывают на одну. - Вызов нестатического метода из
mainнапрямую. МетодgetVolume()принадлежит объекту, поэтому вызывается какmyBox.getVolume(). Без объекта его вызвать нельзя — будет ошибка «non-static method cannot be referenced from a static context». - Имя файла не совпадает с именем public-класса. Класс
public class Boxобязан лежать в файлеBox.java, иначе компилятор выдаст ошибку.
Совет
Явно удалять объекты в Java не нужно. Как только на объект не остаётся ни одной ссылки, он становится кандидатом на утилизацию, и память освободит сборщик мусора. Присваивание myBox = null; лишь обрывает ссылку, а не удаляет объект немедленно.
Закрепить материал помогут задачи по ООП в Java.
Часто задаваемые вопросы
Сколько объектов можно создать из одного класса?
Сколько угодно — ограничение только объём доступной памяти. Каждый вызов new создаёт новый объект с собственной копией полей. Общими для всех экземпляров остаются лишь статические поля, объявленные с модификатором static.
Можно ли объявить несколько классов в одном файле .java?
Да, но public может быть только один класс, и его имя должно совпадать с именем файла. Остальные классы объявляются без модификатора доступа. Компилятор всё равно создаст отдельный файл .class для каждого класса.
Что происходит с объектом, если переменная перестала на него ссылаться?
Объект становится недостижимым, и занятую им память рано или поздно освободит сборщик мусора. Момент удаления не гарантирован: разработчик не управляет им напрямую, а вызов System.gc() лишь рекомендация для JVM.
Почему при обращении к полю объекта возникает NullPointerException?
Потому что переменная объявлена, но объект не создан: ссылка равна null. Строка Box myBox = null; не резервирует память под коробку. Нужно выполнить myBox = new Box(); до первого обращения к полям и методам.
Какие методы есть у объекта, если класс пустой?
Любой класс неявно наследуется от java.lang.Object, поэтому даже у пустого класса объекты имеют методы toString(), equals(), hashCode(), getClass(), clone(), а также wait(), notify() и notifyAll().
Video Explanation
Prefer video format? Watch this lesson with examples and explanations.
Comments