Руководство по созданию объектов в Java

Руководство по созданию объектов в Java

1. обзор

Проще говоря, прежде чем мы сможем работать с объектом в JVM, его нужно инициализировать.

В следующих разделах мы рассмотрим различные способы инициализации примитивных типов и объектов.

2. Декларация против инициализация

Давайте начнем с того, что убедимся, что мы на одной волне.

Declaration is the process of defining the variable вместе с его типом и именем.

Здесь мы объявляем переменнуюid:

int id;

С другой стороны, инициализация заключается в присвоении значения; Например:

id = 1;

Для демонстрации создадим классUser со свойствамиname иid:

public class User implements {
    private String name;
    private int id;

    // standard constructor, getters, setters,
}

Далее мы увидим, что инициализация работает по-разному в зависимости от типа поля, которое мы инициализируем.

3. Объекты против Примитивы

Java предоставляет два типа представления данных: примитивные типы и ссылочные типы. В этом разделе мы обсудим различия между ними в отношении инициализации.

Java имеет восемь встроенных типов данных, называемых примитивными типами Java; переменные этого типа хранят свои значения напрямую.

Ссылочные типы содержат ссылки на объекты (экземпляры классов). Unlike primitive types that hold their values in the memory where the variable is allocated, references don’t hold the value of the object they refer to.с

Вместо этогоa reference points to an object by storing the memory address where the object is located.

Обратите внимание, что Java не позволяет нам узнать, что такое адрес физической памяти. Скорее, мы можем использовать только ссылку для ссылки на объект.

Давайте посмотрим на пример, который объявляет и инициализирует ссылочный тип из нашего классаUser:

@Test
public void whenIntializedWithNew_thenInstanceIsNotNull() {
    User user = new User();

    assertThat(user).isNotNull();
}

Как мы видим здесь, ссылка может быть назначена новому объекту с помощью ключевого словаnew,, которое отвечает за создание нового объектаUser.

Давайте продолжим изучение создания объектов.

5. Создание объектов

В отличие от примитивов, создание объектов немного сложнее. Это потому, что мы не просто добавляем значение в поле; вместо этого мы запускаем инициализацию с помощью ключевого словаnew. Это, в свою очередь, вызывает конструктор и инициализирует объект в памяти.

Давайте обсудим конструкторы и ключевое словоnew более подробно.

Ключевое словоnew -responsible for allocating memory for the new object through a constructor.

A constructor is typically used to initialize instance variables representing the main properties of the created object.

Если мы не предоставим конструктор явно, компилятор создаст конструктор по умолчанию, который не имеет аргументов и просто выделяет память для объекта.

A class can have many constructors as long as their parameters lists are different (overload). Каждый конструктор, который не вызывает другой конструктор в том же классе, имеет вызов своего родительского конструктора, независимо от того, был ли он написан явно или вставлен компилятором черезsuper().

Давайте добавим конструктор в наш классUser:

public User(String name, int id) {
    this.name = name;
    this.id = id;
}

Теперь мы можем использовать наш конструктор для создания объектаUser с начальными значениями его свойств:

User user = new User("Alice", 1);

6. Переменная сфера

В следующих разделах мы рассмотрим различные типы областей видимости, в которых может существовать переменная в Java, и то, как это влияет на процесс инициализации.

6.1. Переменные экземпляра и класса

Instance and class variables don’t require us to initialize them. Как только мы объявляем эти переменные, им дается следующее значение по умолчанию:

image

Теперь давайте попробуем определить некоторые переменные, относящиеся к экземпляру и классу, и проверить, имеют ли они значение по умолчанию или нет:

@Test
public void whenValuesAreNotInitialized_thenUserNameAndIdReturnDefault() {
    User user = new User();

    assertThat(user.getName()).isNull();
    assertThat(user.getId() == 0);
}

6.2. Локальные переменные

Local variables must be initialized before use, поскольку у них нет значения по умолчанию, и компилятор не позволит нам использовать неинициализированное значение.

Например, следующий код генерирует ошибку компилятора:

public void print(){
    int i;
    System.out.println(i);
}

7. Ключевое словоFinal

Ключевое словоfinal, примененное к полю, означает, что значение поля больше не может быть изменено после инициализации. Таким образом, мы можем определить константы в Java.

Давайте добавим константу в наш классUser:

private static final int YEAR = 2000;

Константы должны быть инициализированы либо при их объявлении, либо в конструкторе.

8. Инициализаторы в Java

В Java,initializer is a block of code that has no associated name or data type и помещается вне любого метода, конструктора или другого блока кода.

Java предлагает два типа инициализаторов, статические и экземпляры инициализаторов. Давайте посмотрим, как мы можем использовать каждый из них.

8.1. Инициализаторы экземпляра

Мы можем использовать их для инициализации переменных экземпляра.

Чтобы продемонстрировать это, давайте предоставим значение для пользователяid, используя инициализатор экземпляра в нашем классеUser:

{
    id = 0;
}

8.2. Блок статической инициализации

Статический инициализатор или статический блок - это блок кода, который используется для инициализации полейstatic. Другими словами, это простой инициализатор, помеченный ключевым словомstatic:

private static String forum;
static {
    forum = "Java";
}

9. Порядок инициализации

Конечно, при написании кода, который инициализирует различные типы полей, мы должны следить за порядком инициализации.

В Java порядок операторов инициализации следующий:

  • статические переменные и статические инициализаторы в порядке

  • переменные экземпляра и инициализаторы экземпляра в порядке

  • конструкторы

10. Жизненный цикл объекта

Теперь, когда мы узнали, как объявлять и инициализировать объекты, давайте узнаем, что происходит с объектами, когда они не используются.

В отличие от других языков, где нам приходится беспокоиться об уничтожении объектов, Java заботится об устаревших объектах через сборщик мусора.

All objects in Java are stored in our program’s heap memory. Фактически, куча представляет собой большой пул неиспользуемой памяти, выделенной для нашего Java-приложения.

С другой стороны,garbage collector is a Java program that takes care of automatic memory management путем удаления объектов, которые больше не доступны.

Чтобы Java-объект стал недоступным, он должен столкнуться с одной из следующих ситуаций:

  • У объекта больше нет ссылок, указывающих на него

  • Все ссылки, указывающие на объект, находятся вне области видимости.

В заключение, объект сначала создается из класса, обычно с использованием ключевого словаnew.. Затем объект живет своей жизнью и предоставляет нам доступ к своим методам и полям.

Наконец, когда он больше не нужен, сборщик мусора уничтожает его.

11. Другие методы создания объектов

В этом разделе мы кратко рассмотримmethods other than new keyword to create objects and how to apply them, specifically reflection, cloning, and serialization.

Reflection is a mechanism we can use to inspect classes, fields, and methods at run-time. Вот пример создания нашего объектаUser с использованием отражения:

@Test
public void whenInitializedWithReflection_thenInstanceIsNotNull()
  throws Exception {
    User user = User.class.getConstructor(String.class, int.class)
      .newInstance("Alice", 2);

    assertThat(user).isNotNull();
}

В этом случае мы используем отражение, чтобы найти и вызвать конструктор классаUser.

Следующий метод,cloning, is a way to create an exact copy of an object. Для этого наш классUser должен реализовывать интерфейсCloneable:

public class User implements Cloneable { //... }

Теперь мы можем использовать методclone() для создания нового объектаclonedUser, который имеет те же значения свойств, что и объектuser:

@Test
public void whenCopiedWithClone_thenExactMatchIsCreated()
  throws CloneNotSupportedException {
    User user = new User("Alice", 3);
    User clonedUser = (User) user.clone();

    assertThat(clonedUser).isEqualTo(user);
}

Мы также можем использовать классsun.misc.Unsafe для выделения памяти для объекта без вызова конструктора:

User u = (User) unsafeInstance.allocateInstance(User.class);

12. Заключение

В этом уроке мы рассмотрели инициализацию полей в Java. Мы обнаружили разные типы данных в Java и способы их использования. Мы также подробно рассмотрели несколько способов создания объектов в Java.

Полную реализацию этого руководства можно найти вover on Github.