tgoop.com/javapro_ir/4429
Last Update:
🟢 تفاوت عمیق بین Lombok و Record
در جاوا برای ساخت کلاسهای دادهمحور دو رویکرد رایج وجود دارد: استفاده از Lombok (مثلاً با @Data) و استفاده از Recordهای زبان. در ظاهر هر دو «کد تکراری» (boilerplate) را کم میکنند، اما در فلسفه، گارانتیها و رفتار زمان اجرا تفاوتهای بنیادینی دارند.
تعریف و نگاه:
در سطح زبان، Record از جاوا ۱۶ به بعد یک ساختار value-based است که بهصورت ذاتی: اجزای دادهای را نهایی میکند، سازندهی قانونی، equals/hashCode/toString و accessorها را تولید میکند.
در سطح کتابخانه، Lombok با Annotation Processing در زمان کامپایل کد تولید میکند؛ یعنی زبان جاوا تغییر نمیکند، اما کلاس شما بر اساس annotationها «تکمیل» میشود.
تفاوت اصلی شماره ۱: تغییرپذیری (Mutability) و تضمینها
در Record، فیلدها نهایی و کلاس اساساً ناپذیرفتار (immutable) است (البته «سطحی»؛ اگر فیلدی خودش mutable باشد، محتوایش میتواند عوض شود).
در Lombok با @Data، کلاس بهطور پیشفرض قابل تغییر است؛ یعنی setter تولید میشود و میتوان پس از ساخت شیء، وضعیت را تغییر داد.
// Lombok – کلاس پیشفرض قابل تغییر
import lombok.Data;
@Data
public class UserLombok {
private String name;
private int age;
}
// Record – کلاس ذاتیِ ناپذیرفتار
public record UserRecord(String name, int age) { }
public class Demo {
public static void main(String[] args) {
UserLombok u1 = new UserLombok();
u1.setName("Ali"); u1.setAge(20); // قابل تغییر
UserRecord r1 = new UserRecord("Ali", 20);
// r1.age = 21; // خطا: فیلدها نهاییاند و setter وجود ندارد
}
}
تفاوت اصلی شماره ۲: برابری (Equality) و استفاده بهعنوان مقدار (Value Semantics)
در Record، برابری بهصورت ارزشمحور تعریف میشود؛ یعنی دو رکورد با اجزای برابر، برابرند و برای کلید/عضو کالکشنها ایدهآلاند.
در Lombok با @Data نیز equals/hashCode تولید میشود، اما چون کلاس معمولاً mutable است، تغییر فیلدی که در برابری دخیل است میتواند باعث رفتارهای خطرناک در HashMap/HashSet شود.
// خطر رایج با Lombok @Data و کلاسهای mutable
import java.util.*;
public class EqualityPitfall {
public static void main(String[] args) {
UserLombok u = new UserLombok();
u.setName("A"); u.setAge(1);
Set<UserLombok> set = new HashSet<>();
set.add(u);
u.setAge(2); // تغییر فیلدی که در hashCode دخیل است
System.out.println(set.contains(u)); // ممکن است false شود → رفتار مشکلزا
}
}
// رفتار امنتر با Record (تا وقتی اجزا تغییر نکنند)
import java.util.*;
public class EqualitySafe {
public static void main(String[] args) {
UserRecord r = new UserRecord("A", 1);
Set<UserRecord> set = new HashSet<>();
set.add(r);
System.out.println(set.contains(r)); // همیشه true چون رکورد ناپذیرفتار است
}
}
تفاوت اصلی شماره ۳: سازنده و اعتبارسنجی (Validation)
در Record، میتوانید سازندهی فشرده (compact constructor) تعریف کنید و قواعد اعتبارسنجی را همانجا اعمال کنید؛ اما همچنان ناپذیرفتاری حفظ میشود.
public record Email(String local, String domain) {
public Email {
if (local == null || local.isBlank()) throw new IllegalArgumentException("local required");
if (domain == null || !domain.contains(".")) throw new IllegalArgumentException("invalid domain");
}
}
در Lombok، میتوانید از annotationهایی مثل @NonNull یا سازندههای تولیدی (@AllArgsConstructor/@RequiredArgsConstructor) و حتی @Builder برای ساخت امنتر استفاده کنید، اما ماهیت کلاس لزوماً immutable نمیشود مگر اینکه از @Value بهره بگیرید.
import lombok.Builder;
import lombok.Value;
// Lombok – کلاس ناپذیرفتار با @Value + سازنده Builder
@Value
@Builder
public class EmailValue {
String local;
String domain;
}
تفاوت اصلی شماره ۴: وراثت و مدل شیءگرا
در Record، ارثبری از کلاسها ممنوع است (همه رکوردها ضمنی final هستند) اما پیادهسازی اینترفیس مجاز است.
در Lombok، کلاس شما یک کلاس «عادی» جاواست؛ میتواند از کلاس دیگری ارث ببرد یا اینترفیسها را پیادهسازی کند و Lombok صرفاً کدهای تکراری را تولید میکند.
تفاوت اصلی شماره ۵: نسخه و وابستگی
BY برنامه نویسی جاوا | Java
Share with your friend now:
tgoop.com/javapro_ir/4429