Рубрики
Без рубрики

Класс записей Java 14

Класс записей Java был представлен в Java 14 в качестве функции предварительного просмотра. Класс записи используется для создания объектов данных с компактным синтаксисом и без кода котельной.

Автор оригинала: Pankaj Kumar.

Java 14 представила новый способ создания классов, называемых записями. В этом уроке мы научимся:

  • Зачем нам нужны записи Java
  • Как создавать записи и использовать их
  • Переопределение и расширение классов записей

Рекомендуемое чтение : Функции Java 14

Зачем нам нужны записи Java?

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

  • Частные поля
  • Методы получения и установки
  • Конструкторы
  • Методы hashCode(), equals () и toString ().

Эта многословность является одной из причин высокого интереса к Котлину и проекту Ломбок .

На самом деле, явное разочарование от написания этих универсальных методов каждый раз приводит к тому, что для их создания используются ярлыки в Java IDE, такие как Eclipse и IntelliJ IDEA.

Вот снимок экрана, показывающий опцию Eclipse IDE для создания церемониальных методов для класса.

Записи Java предназначены для устранения этой многословности, предоставляя компактную структуру для создания классов POJO.

Как создавать записи Java

Записи Java – это функция предварительного просмотра, которая разработана в JEP 359 . Итак, вам нужны две вещи для создания записей в ваших Java-проектах.

  1. Установлен JDK 14. Если вы используете IDE, то она также должна обеспечивать поддержку Java 14. И Eclipse, и IntelliJ уже предоставляют поддержку Java 14, так что у нас все хорошо.
  2. Включить функцию предварительного просмотра : По умолчанию функции предварительного просмотра отключены. Вы можете включить его в Eclipse из настроек компилятора Java проекта.

Вы можете включить функции предварительного просмотра Java 14 в командной строке, используя параметр --enable-preview-source 14 .

Допустим, я хочу создать класс модели сотрудника. Это будет выглядеть примерно так, как показано в следующем коде.

package com.journaldev.java14;

import java.util.Map;

public class Employee {

	private int id;
	private String name;
	private long salary;
	private Map addresses;

	public Employee(int id, String name, long salary, Map addresses) {
		super();
		this.id = id;
		this.name = name;
		this.salary = salary;
		this.addresses = addresses;
	}

	public int getId() {
		return id;
	}

	public String getName() {
		return name;
	}

	public long getSalary() {
		return salary;
	}

	public Map getAddresses() {
		return addresses;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((addresses == null) ? 0 : addresses.hashCode());
		result = prime * result + id;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		result = prime * result + (int) (salary ^ (salary >>> 32));
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Employee other = (Employee) obj;
		if (addresses == null) {
			if (other.addresses != null)
				return false;
		} else if (!addresses.equals(other.addresses))
			return false;
		if (id != other.id)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		if (salary != other.salary)
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "Employee [id=" + id + ", name=" + name + ", salary=" + salary + ", addresses=" + addresses + "]";
	}

}

Фу, это более 70 строк автоматически сгенерированного кода. Теперь давайте посмотрим, как создать класс записей сотрудников, который, по сути, предоставляет те же функции.

package com.journaldev.java14;

import java.util.Map;

public record EmpRecord(int id, String name, long salary, Map addresses) {
}

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

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

# javac --enable-preview -source 14 EmpRecord.java
Note: EmpRecord.java uses preview language features.
Note: Recompile with -Xlint:preview for details.

# javap EmpRecord      
Compiled from "EmpRecord.java"
public final class EmpRecord extends java.lang.Record {
  public EmpRecord(int, java.lang.String, long, java.util.Map);
  public java.lang.String toString();
  public final int hashCode();
  public final boolean equals(java.lang.Object);
  public int id();
  public java.lang.String name();
  public long salary();
  public java.util.Map addresses();
}
# 

Если вам нужны дополнительные внутренние сведения, выполните команду javap с опцией-v.

# javap -v EmpRecord 

Важные моменты, касающиеся классов записей

  1. Класс записи является окончательным, поэтому мы не можем его продлить.
  2. Классы записей неявно расширяют java.lang.Запись класс.
  3. Все поля, указанные в объявлении записи, являются окончательными.
  4. Поля записи являются “неглубокими” неизменяемыми и зависят от типа. Например, мы можем изменить поле адреса, получив к нему доступ, а затем обновив его.
  5. Создается единый конструктор со всеми полями, указанными в определении записи.
  6. Класс записи автоматически предоставляет методы доступа к полям. Имя метода совпадает с именем поля, а не с общими и обычными методами получения.
  7. Класс записи также предоставляет реализации hashCode() , equals () и toString ().

Использование записей в программе Java

Давайте рассмотрим простой пример использования нашего класса EmpRecord.

package com.journaldev.java14;

public class RecordTest {

	public static void main(String[] args) {
		
		EmpRecord empRecord1 = new EmpRecord(10, "Pankaj", 10000, null);
		EmpRecord empRecord2 = new EmpRecord(10, "Pankaj", 10000, null);

		// toString()
		System.out.println(empRecord1);
		
		// accessing fields
		System.out.println("Name: "+empRecord1.name()); 
		System.out.println("ID: "+empRecord1.id());
		
		// equals()
		System.out.println(empRecord1.equals(empRecord2));
		
		// hashCode()
		System.out.println(empRecord1 == empRecord2);		
	}
}

Выход:

EmpRecord[id=10, name=Pankaj, salary=10000, addresses=null]
Name: Pankaj
ID: 10
true
false

Объект записи работает так же, как и любой класс модели, объект данных и т.д.

Расширение Конструктора Записей

Иногда мы хотим провести некоторые проверки или войти в наш конструктор . Например, идентификатор сотрудника и зарплата не должны быть отрицательными. Конструктор по умолчанию не будет иметь этой проверки. Мы можем создать компактный конструктор в классе record. Код этого конструктора будет помещен в начало автоматически сгенерированного конструктора.

public record EmpRecord(int id, String name, long salary, Map addresses) {
	
	public EmpRecord {
		if (id < 0)
			throw new IllegalArgumentException("employee id can't be negative");

		if (salary < 0)
			throw new IllegalArgumentException("employee salary can't be negative");
	}

}

Если мы создадим запись EmpRecord, как в следующем коде:

EmpRecord empRecord1 = new EmpRecord(-10, "Pankaj", 10000, null);

Мы получим исключение во время выполнения в виде:

Exception in thread "main" java.lang.IllegalArgumentException: employee id can't be negative
	at com.journaldev.java14.EmpRecord.(EmpRecord.java:9)

Могут Ли Классы Записей Иметь Методы?

Да, мы можем создать метод в записях.

public record EmpRecord(int id, String name, long salary, Map addresses) {

	public int getAddressCount() {
		if (this.addresses != null)
			return this.addresses().size();
		else
			return 0;
	}
}

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

Если вы считаете, что наличие метода необходимо для вашего класса записей, подумайте хорошенько, действительно ли вам нужен класс записей?

Вывод

Записи Java являются желанным дополнением к основным функциям программирования. Вы можете думать об этом как о “именованном кортеже”. Он предназначен для создания объекта-носителя данных с компактной структурой, избегая всего шаблонного кода.