ชั้นไม่เปลี่ยนรูป?


86

เราจะทำให้คลาส Java ไม่เปลี่ยนรูปได้อย่างไรความต้องการความไม่เปลี่ยนรูปคืออะไรและมีข้อได้เปรียบในการใช้สิ่งนี้หรือไม่?


2
มีคำแนะนำสำหรับคลาสที่ไม่เปลี่ยนรูป: javapractices.com/topic/…
qrtt1

ตรวจสอบ@Immutableคำอธิบายประกอบนี้จากjcabi ด้าน
yegor256

ดูเพิ่มเติมที่: stackoverflow.com/questions/3769607
Stephen C

คำตอบ:


136

วัตถุที่ไม่เปลี่ยนรูปคืออะไร?

วัตถุที่ไม่เปลี่ยนรูปคือวัตถุที่จะไม่เปลี่ยนสถานะหลังจากที่สร้างอินสแตนซ์แล้ว

จะทำให้วัตถุไม่เปลี่ยนรูปได้อย่างไร?

โดยทั่วไปออบเจ็กต์ที่ไม่เปลี่ยนรูปสามารถทำได้โดยการกำหนดคลาสที่ไม่มีสมาชิกใด ๆ เปิดเผยและไม่มีตัวเซ็ต

คลาสต่อไปนี้จะสร้างวัตถุที่ไม่เปลี่ยนรูป:

class ImmutableInt {
  private final int value;

  public ImmutableInt(int i) {
    value = i;
  }

  public int getValue() {
    return value;
  }
}

ดังที่เห็นในตัวอย่างข้างต้นค่าของImmutableIntสามารถตั้งค่าได้ก็ต่อเมื่อวัตถุถูกสร้างอินสแตนซ์และโดยมีเพียง getter (getValue ) สถานะของอ็อบเจ็กต์จะไม่สามารถเปลี่ยนแปลงได้หลังจากสร้างอินสแตนซ์

อย่างไรก็ตามต้องใช้ความระมัดระวังว่าวัตถุทั้งหมดที่อ้างอิงโดยวัตถุนั้นจะต้องไม่เปลี่ยนรูปเช่นกันหรืออาจเป็นไปได้ที่จะเปลี่ยนสถานะของวัตถุ

ตัวอย่างเช่นการอนุญาตให้อ้างอิงไปยังอาร์เรย์หรือArrayListได้รับผ่าน getter จะทำให้สถานะภายในเปลี่ยนแปลงได้โดยการเปลี่ยนอาร์เรย์หรือคอลเลกชัน:

class NotQuiteImmutableList<T> {
  private final List<T> list;

  public NotQuiteImmutableList(List<T> list) {
    // creates a new ArrayList and keeps a reference to it.
    this.list = new ArrayList(list); 
  }

  public List<T> getList() {
    return list;
  }
}

ปัญหาเกี่ยวกับรหัสข้างต้นคือArrayListสามารถรับผ่านgetListและถูกจัดการได้ซึ่งนำไปสู่สถานะของวัตถุที่จะเปลี่ยนแปลงดังนั้นจึงไม่เปลี่ยนรูป

// notQuiteImmutableList contains "a", "b", "c"
List<String> notQuiteImmutableList= new NotQuiteImmutableList(Arrays.asList("a", "b", "c"));

// now the list contains "a", "b", "c", "d" -- this list is mutable.
notQuiteImmutableList.getList().add("d");

วิธีหนึ่งในการแก้ไขปัญหานี้คือส่งคืนสำเนาของอาร์เรย์หรือคอลเลกชันเมื่อเรียกจาก getter:

public List<T> getList() {
  // return a copy of the list so the internal state cannot be altered
  return new ArrayList(list);
}

ข้อดีของการไม่เปลี่ยนรูปคืออะไร?

ข้อได้เปรียบของการไม่เปลี่ยนรูปมาพร้อมกับการทำงานพร้อมกัน เป็นการยากที่จะรักษาความถูกต้องในอ็อบเจ็กต์ที่ไม่แน่นอนเนื่องจากเธรดหลายเธรดอาจพยายามเปลี่ยนสถานะของอ็อบเจ็กต์เดียวกันทำให้เธรดบางเธรดเห็นสถานะที่แตกต่างกันของอ็อบเจ็กต์เดียวกันขึ้นอยู่กับเวลาของการอ่านและเขียนไปยังสิ่งที่กล่าว วัตถุ.

ด้วยการมีวัตถุที่ไม่เปลี่ยนรูปเราสามารถมั่นใจได้ว่าเธรดทั้งหมดที่มองไปที่วัตถุจะเห็นสถานะเดียวกันเนื่องจากสถานะของวัตถุที่ไม่เปลี่ยนรูปจะไม่เปลี่ยนแปลง


5
ความปลอดภัยของเธรด (สำคัญสำหรับการเกิดพร้อมกัน) ไม่ใช่ข้อดีเพียงอย่างเดียวของความไม่เปลี่ยนรูป นอกจากนี้ยังหมายความว่าคุณไม่จำเป็นต้องทำสำเนาวัตถุป้องกันและป้องกันข้อบกพร่องเนื่องจากคุณไม่สามารถแก้ไขวัตถุที่ไม่ควรแก้ไขได้โดยไม่ได้ตั้งใจ
Jesper

7
แทนที่จะส่งคืนสำเนาของรายการคุณยังสามารถreturn Collections.unmodifiableList(list);ส่งคืนมุมมองแบบอ่านอย่างเดียวในรายการได้
Jesper

19
ชั้นต้องทำfinalด้วย มิฉะนั้นสามารถขยายด้วยเมธอด setter (หรือวิธีการกลายพันธุ์ชนิดอื่น ๆ และฟิลด์ที่เปลี่ยนแปลงได้)
Abhinav Sarkar

6
@AbhinavSarkar ไม่จำเป็นต้องเป็นfinalถ้าคลาสมีเฉพาะprivateเขตข้อมูลเนื่องจากไม่สามารถเข้าถึงได้จากคลาสย่อย
icza

3
คลาส @icza จะต้องเป็นที่สิ้นสุดเนื่องจากเรามีวิธี public getter เราสามารถขยายคลาสและแทนที่เมธอด getter จากนั้นเปลี่ยนฟิลด์ในแบบของเรา .. ดังนั้นมันจะไม่เปลี่ยนรูปอีกต่อไป
sunil

19

นอกเหนือจากคำตอบที่ให้ไปแล้วฉันขอแนะนำให้อ่านเกี่ยวกับความไม่เปลี่ยนรูปใน Effective Java, 2nd Ed. เนื่องจากมีรายละเอียดบางอย่างที่พลาดง่าย (เช่นสำเนาป้องกัน) นอกจากนี้ Java 2nd Ed ที่มีประสิทธิภาพ เป็นสิ่งที่ต้องอ่านสำหรับนักพัฒนา Java ทุกคน


3
นี่คือแหล่งข้อมูลที่แน่นอนที่จะดู ประโยชน์ที่กล่าวถึงมีตั้งแต่โค้ดที่มีแนวโน้มผิดพลาดน้อยไปจนถึงความปลอดภัยของเธรด
gpampara

6

คุณทำให้คลาสไม่เปลี่ยนรูปแบบนี้:

public final class Immutable
{
    private final String name;

    public Immutable(String name) 
    {
        this.name = name;
    }

    public String getName() { return this.name; } 

    // No setter;
}

ต่อไปนี้เป็นข้อกำหนดในการทำให้คลาส Java ไม่เปลี่ยนรูป:

  • ต้องประกาศคลาสเป็นfinal(เพื่อให้ไม่สามารถสร้างคลาสย่อยได้)
  • สมาชิกในคลาสจะต้องได้รับการประกาศเป็นfinal(ดังนั้นเราจึงไม่สามารถเปลี่ยนค่าของมันได้หลังจากสร้างวัตถุ)
  • เขียนเมธอด Getterสำหรับตัวแปรทั้งหมดเพื่อรับค่าMembers
  • ไม่มีวิธีการ Setters

คลาสที่ไม่เปลี่ยนรูปมีประโยชน์เนื่องจาก
- ปลอดภัยต่อเธรด
- พวกเขายังแสดงบางสิ่งบางอย่างที่ลึกซึ้งเกี่ยวกับการออกแบบของคุณ: "ไม่สามารถเปลี่ยนแปลงสิ่งนี้ได้" เมื่อนำไปใช้ก็เป็นสิ่งที่คุณต้องการ


5

ความไม่เปลี่ยนรูปสามารถทำได้โดยส่วนใหญ่สองวิธี:

  • โดยใช้ finalแอตทริบิวต์อินสแตนซ์เพื่อหลีกเลี่ยงการมอบหมายใหม่
  • ใช้อินเทอร์เฟซคลาสที่ไม่อนุญาตให้มีการดำเนินการใด ๆ ที่สามารถแก้ไขสิ่งที่อยู่ในคลาสของคุณได้ (มีเพียงแค่gettersและไม่มีsetters

ข้อดีของการไม่เปลี่ยนรูปคือสมมติฐานที่คุณสามารถทำได้กับวัตถุเหล่านี้:

  • คุณได้รับกฎไม่มีผลข้างเคียง (ซึ่งเป็นที่นิยมอย่างมากในภาษาโปรแกรมที่ใช้งานได้) และช่วยให้คุณใช้วัตถุในสภาพแวดล้อมพร้อมกันได้ง่ายขึ้นเนื่องจากคุณรู้ว่าไม่สามารถเปลี่ยนแปลงได้ในทางปรมาณูหรือไม่ใช่อะตอมเมื่อเป็น ใช้โดยหลายเธรด
  • การใช้งานภาษาสามารถปฏิบัติต่อออบเจ็กต์เหล่านี้ในลักษณะที่แตกต่างกันโดยวางไว้ในโซนของหน่วยความจำที่ใช้สำหรับข้อมูลคงที่ทำให้สามารถใช้อ็อบเจ็กต์เหล่านี้ได้เร็วขึ้นและปลอดภัยยิ่งขึ้น (นี่คือสิ่งที่เกิดขึ้นภายใน JVM สำหรับสตริง)

ไม่เปลี่ยนรูปไม่เหมือนกับผลข้างเคียงที่เท่าเทียมกัน ตัวอย่างเช่นวัตถุที่ไม่เปลี่ยนรูปอาจทำให้เกิดผลข้างเคียงเช่นการเข้าสู่ไฟล์ เป็นเรื่องไม่ถูกต้องเล็กน้อยที่จะกล่าวว่าการทำให้วัตถุไม่เปลี่ยนรูปยังทำให้ปราศจากผลข้างเคียง
Grundlefleck

1
@Grundleflek ฉันคิดว่านี่อาจเป็นการแยกเส้นขน คลาสจะไม่เปลี่ยนรูปหากแก้ไขไฟล์บันทึกเป็นส่วนหนึ่งของสัญญาและไฟล์บันทึกนั้นสามารถเข้าถึงได้โดยคลาสอื่น ๆ หากไฟล์บันทึกถูกซ่อนจากคลาสอื่น ๆ และไม่ได้เป็นส่วนหนึ่งของสัญญาของคลาสคลาสนั้นจะไม่เปลี่ยนรูปอย่างมีประสิทธิภาพและสำหรับทุกเจตนาและวัตถุประสงค์โดยไม่มีผลข้างเคียง คำนำ (ไม่ระบุแหล่งที่มา) ในหน้าผลข้างเคียงของ Wikipedia อ่านว่า "... มีการกล่าวว่านิพจน์มีผลข้างเคียงหากนอกเหนือจากการสร้างค่าแล้วยังแก้ไขสถานะบางอย่างหรือมีปฏิสัมพันธ์ที่สังเกตได้กับฟังก์ชันการโทรด้วย"
Jeff Axelrod

3

คลาสที่ไม่เปลี่ยนรูปไม่สามารถกำหนดค่าใหม่ได้หลังจากสร้างอินสแตนซ์แล้วตัวสร้างกำหนดค่าให้กับตัวแปรส่วนตัว จนกว่าอ็อบเจ็กต์จะกลายเป็นโมฆะจะไม่สามารถเปลี่ยนค่าได้เนื่องจากเมธอด setter ไม่พร้อมใช้งาน

ไม่เปลี่ยนรูปควรตอบสนองต่อไปนี้

  • ตัวแปรควรเป็นแบบส่วนตัวส่วนตัว
  • ไม่มีผู้กลายพันธุ์วิธีการ (setters) ไว้ให้
  • หลีกเลี่ยงการลบล้างวิธีการโดยการทำให้คลาสเป็นขั้นสุดท้าย (Strong Immutability) หรือวิธีสุดท้าย (Week ไม่เปลี่ยนรูป)
  • โคลนอย่างละเอียดหากมีคลาสที่ไม่ใช่คลาสดั้งเดิมหรือไม่แน่นอน

/**
* Strong immutability - by making class final
*/
public final class TestImmutablity {

// make the variables private
private String Name;

//assign value when the object created
public TestImmutablity(String name) {
this.Name = name;
}

//provide getters to access values
public String getName() {

return this.Name;
}
}

ข้อได้เปรียบ: วัตถุที่ไม่เปลี่ยนรูปมีค่าเริ่มต้นจนกว่ามันจะตาย

java ไม่เปลี่ยนรูปแบบเรียนสั้นหมายเหตุ


2

คลาสไม่เปลี่ยนรูปคือที่ไม่สามารถเปลี่ยนแปลงวัตถุได้หลังจากสร้าง

คลาสที่ไม่เปลี่ยนรูปมีประโยชน์สำหรับ

  • วัตถุประสงค์ในการแคช
  • สภาพแวดล้อมพร้อมกัน (ThreadSafe)
  • ยากสำหรับการสืบทอด
  • ค่าไม่สามารถเปลี่ยนแปลงได้ในทุกสภาพแวดล้อม

ตัวอย่าง

คลาสสตริง

ตัวอย่างรหัส

public final class Student {
    private final String name;
    private final String rollNumber;

    public Student(String name, String rollNumber) {
        this.name = name;
        this.rollNumber = rollNumber;
    }

    public String getName() {
        return this.name;
    }

    public String getRollNumber() {
        return this.rollNumber;
    }
}

2

เราจะทำให้คลาส Java ไม่เปลี่ยนรูปได้อย่างไร

จาก JDK 14+ ซึ่งมีJEP 359เราสามารถใช้ "records " ได้ เป็นวิธีที่ง่ายที่สุดและไม่เร่งรีบในการสร้างคลาสที่ไม่เปลี่ยนรูปแบบ

คลาสเร็กคอร์ดเป็นพาหะที่โปร่งใสและไม่เปลี่ยนรูปตื้น ๆสำหรับชุดฟิลด์คงที่ซึ่งเรียกว่าเร็กคอร์ดcomponentsที่ให้stateคำอธิบายสำหรับเร็กคอร์ด แต่ละฟิลด์componentก่อให้เกิดfinalฟิลด์ที่เก็บค่าที่ระบุและaccessorวิธีการดึงค่า ชื่อฟิลด์และชื่อผู้เข้าถึงตรงกับชื่อของคอมโพเนนต์

ลองพิจารณาตัวอย่างของการสร้างสี่เหลี่ยมผืนผ้าที่ไม่เปลี่ยนรูป

record Rectangle(double length, double width) {}

ไม่จำเป็นต้องประกาศตัวสร้างใด ๆ ไม่จำเป็นต้องใช้เมธอด equals & hashCode เพียงแค่บันทึกใด ๆ ต้องมีชื่อและคำอธิบายสถานะ

var rectangle = new Rectangle(7.1, 8.9);
System.out.print(rectangle.length()); // prints 7.1

หากคุณต้องการตรวจสอบความถูกต้องของค่าในระหว่างการสร้างวัตถุเราต้องประกาศตัวสร้างอย่างชัดเจน

public Rectangle {

    if (length <= 0.0) {
      throw new IllegalArgumentException();
    }
  }

เนื้อหาของเร็กคอร์ดอาจประกาศวิธีการแบบคงที่ฟิลด์แบบคงที่ตัวเริ่มต้นแบบคงที่ตัวสร้างวิธีการอินสแตนซ์และประเภทที่ซ้อนกัน

วิธีการอินสแตนซ์

record Rectangle(double length, double width) {

  public double area() {
    return this.length * this.width;
  }
}

เขตข้อมูลคงวิธี

เนื่องจากสถานะควรเป็นส่วนหนึ่งของส่วนประกอบเราจึงไม่สามารถเพิ่มฟิลด์อินสแตนซ์ลงในเรกคอร์ดได้ แต่เราสามารถเพิ่มฟิลด์และวิธีการคงที่:

record Rectangle(double length, double width) {

  static double aStaticField;

  static void aStaticMethod() {
    System.out.println("Hello Static");
  }
}

อะไรคือความจำเป็นของการไม่เปลี่ยนรูปและมีประโยชน์ในการใช้สิ่งนี้หรือไม่?

คำตอบที่โพสต์ไว้ก่อนหน้านี้ดีพอที่จะพิสูจน์ความจำเป็นของการไม่เปลี่ยนรูปและเป็นข้อดี


0

อีกวิธีในการสร้างวัตถุที่ไม่เปลี่ยนรูปคือการใช้ไลบรารีImmutables.org :

สมมติว่ามีการเพิ่มการอ้างอิงที่จำเป็นสร้างคลาสนามธรรมด้วยวิธีการเข้าถึงนามธรรม คุณสามารถทำได้โดยการใส่คำอธิบายประกอบกับอินเทอร์เฟซหรือแม้แต่คำอธิบายประกอบ (@interface):

package info.sample;

import java.util.List;
import java.util.Set;
import org.immutables.value.Value;

@Value.Immutable
public abstract class FoobarValue {
  public abstract int foo();
  public abstract String bar();
  public abstract List<Integer> buz();
  public abstract Set<Long> crux();
}

ตอนนี้คุณสามารถสร้างและใช้การใช้งานที่ไม่เปลี่ยนรูปได้แล้ว:

package info.sample;

import java.util.List;

public class FoobarValueMain {
  public static void main(String... args) {
    FoobarValue value = ImmutableFoobarValue.builder()
        .foo(2)
        .bar("Bar")
        .addBuz(1, 3, 4)
        .build(); // FoobarValue{foo=2, bar=Bar, buz=[1, 3, 4], crux={}}

    int foo = value.foo(); // 2

    List<Integer> buz = value.buz(); // ImmutableList.of(1, 3, 4)
  }
}

0

คลาสที่ไม่เปลี่ยนรูปเป็นเพียงคลาสที่ไม่สามารถแก้ไขอินสแตนซ์ได้

ข้อมูลทั้งหมดที่มีอยู่ในแต่ละอินสแตนซ์ได้รับการแก้ไขสำหรับอายุการใช้งานของวัตถุดังนั้นจึงไม่สามารถสังเกตการเปลี่ยนแปลงได้

คลาสที่ไม่เปลี่ยนรูปจะออกแบบนำไปใช้และใช้งานได้ง่ายกว่าคลาสที่เปลี่ยนแปลงไม่ได้

ในการทำให้คลาสไม่เปลี่ยนรูปให้ปฏิบัติตามกฎห้าข้อต่อไปนี้:

  1. อย่าระบุวิธีการที่ปรับเปลี่ยนสถานะของวัตถุ

  2. ตรวจสอบให้แน่ใจว่าไม่สามารถขยายชั้นเรียนได้

  3. ทำให้ฟิลด์ทั้งหมดเป็นที่สิ้นสุด

  4. ทำให้ฟิลด์ทั้งหมดเป็นแบบส่วนตัว

  5. ตรวจสอบให้แน่ใจว่าสามารถเข้าถึงส่วนประกอบที่ไม่แน่นอนได้

วัตถุที่ไม่เปลี่ยนรูปนั้นปลอดภัยต่อเกลียวโดยเนื้อแท้ พวกเขาไม่ต้องการการซิงโครไนซ์

สามารถแบ่งปันวัตถุที่ไม่เปลี่ยนรูปได้อย่างอิสระ

วัตถุที่ไม่เปลี่ยนรูปเป็นส่วนประกอบที่ยอดเยี่ยมสำหรับวัตถุอื่น ๆ


0

@Jack การมีฟิลด์สุดท้ายและตัวเซ็ตในคลาสจะไม่ทำให้คลาสไม่เปลี่ยนรูป คำหลักสุดท้ายตรวจสอบให้แน่ใจว่าไม่มีการกำหนดตัวแปรใหม่ คุณต้องส่งคืนสำเนาลึกของฟิลด์ทั้งหมดในวิธีการ getter สิ่งนี้จะทำให้แน่ใจว่าหลังจากได้รับวัตถุจากเมธอด getter แล้วสถานะภายในของวัตถุจะไม่ถูกรบกวน


-1

ในฐานะที่ไม่ใช่เจ้าของภาษาอังกฤษฉันไม่ชอบการตีความทั่วไปของ "คลาสที่ไม่เปลี่ยนรูป" ว่า "อ็อบเจ็กต์คลาสที่สร้างขึ้นไม่เปลี่ยนรูป"; แต่ฉันเองก็เอนเอียงที่จะตีความว่าเป็น "วัตถุคลาสนั้นไม่เปลี่ยนรูป"

ที่กล่าวว่า "คลาสไม่เปลี่ยนรูป" เป็นวัตถุที่ไม่เปลี่ยนรูป ความแตกต่างคือเมื่อตอบว่าประโยชน์คืออะไร สำหรับความรู้ / การตีความของฉันคลาสที่ไม่เปลี่ยนรูปจะป้องกันไม่ให้อ็อบเจ็กต์ถูกปรับเปลี่ยนพฤติกรรมรันไทม์


-1

คำตอบส่วนใหญ่ที่นี่เป็นคำตอบที่ดีและบางคนก็พูดถึงกฎ แต่ฉันรู้สึกดีที่จะพูดถึงเหตุผลและเวลาที่เราต้องปฏิบัติตามกฎเหล่านี้ ดังนั้นฉันจึงให้คำอธิบายด้านล่าง

  • ประกาศตัวแปรสมาชิกเป็น 'สุดท้าย' - เมื่อเราประกาศให้เป็นขั้นสุดท้ายคอมไพเลอร์จะบังคับให้เราเริ่มต้นตัวแปรเหล่านี้ เราสามารถเริ่มต้นได้โดยตรงโดยตัวสร้างเริ่มต้นโดยตัวสร้างอาร์กิวเมนต์ (ดูโค้ดตัวอย่างด้านล่าง) และหลังจากการเริ่มต้นเราไม่สามารถแก้ไขได้เนื่องจากเป็นขั้นสุดท้าย
  • และแน่นอนว่าถ้าเราพยายามใช้ Setters สำหรับตัวแปรสุดท้ายคอมไพเลอร์จะแสดงข้อผิดพลาด

    public class ImmutableClassExplored {
    
        public final int a; 
        public final int b;
    
        /* OR  
        Generally we declare all properties as private, but declaring them as public 
        will not cause any issues in our scenario if we make them final     
        public final int a = 109;
        public final int b = 189;
    
         */
        ImmutableClassExplored(){
            this. a = 111;
            this.b = 222;
        }
    
        ImmutableClassExplored(int a, int b){
            this.a = a;
            this.b= b;
        }
    }
    

เราจำเป็นต้องประกาศชั้นเรียนเป็น 'ขั้นสุดท้าย' หรือไม่?

  • หากไม่มีคีย์เวิร์ดสุดท้ายในการประกาศคลาสก็สามารถสืบทอดคลาสได้ คลาสย่อยสามารถแทนที่เมธอด getter ได้ ที่นี่เราต้องพิจารณาสองสถานการณ์:

1. มีเฉพาะสมาชิกดั้งเดิม:เราไม่มีปัญหาหากคลาสมีสมาชิกดั้งเดิมเท่านั้นเราไม่จำเป็นต้องประกาศคลาสเป็นขั้นสุดท้าย

2. การมีออบเจ็กต์เป็นตัวแปรสมาชิก:หากเรามีอ็อบเจกต์เป็นตัวแปรสมาชิกเราจะต้องทำให้สมาชิกของอ็อบเจ็กต์เหล่านั้นสิ้นสุดลงด้วย หมายความว่าเราต้องสำรวจลึกลงไปตามต้นไม้และทำให้วัตถุ / วัตถุดั้งเดิมทั้งหมดเป็นขั้นสุดท้ายซึ่งอาจเป็นไปไม่ได้ตลอดเวลา ดังนั้นวิธีแก้ปัญหาคือทำให้คลาสสุดท้ายซึ่งป้องกันการสืบทอด ดังนั้นจึงไม่มีคำถามเกี่ยวกับคลาสย่อยที่ลบล้างเมธอด getter


-1

คำอธิบายประกอบ @ มูลค่าของลอมบอกสามารถใช้เพื่อสร้างคลาสที่ไม่เปลี่ยนรูปได้ ง่ายๆเหมือนโค้ดด้านล่าง

@Value
public class LombokImmutable {
    int id;
    String name;
}

ตามเอกสารในเว็บไซต์ของลอมบอก:

@Value เป็นตัวแปรที่ไม่เปลี่ยนรูปของ @Data; ฟิลด์ทั้งหมดถูกทำให้เป็นส่วนตัวและสุดท้ายโดยค่าเริ่มต้นและไม่มีการสร้างตัวตั้งค่า คลาสเองก็ถูกทำให้เป็นขั้นสุดท้ายตามค่าเริ่มต้นเช่นกันเนื่องจากความไม่เปลี่ยนรูปไม่ใช่สิ่งที่สามารถบังคับให้เข้าสู่คลาสย่อยได้ เช่น @Data มีการสร้างเมธอด toString (), equals () และ hashCode () ที่เป็นประโยชน์เช่นกันแต่ละฟิลด์จะได้รับเมธอด getter และตัวสร้างที่ครอบคลุมทุกอาร์กิวเมนต์ (ยกเว้นฟิลด์สุดท้ายที่เริ่มต้นในการประกาศฟิลด์) จะถูกสร้างขึ้นด้วย .

ตัวอย่างการทำงานอย่างสมบูรณ์สามารถพบได้ที่นี่


ก่อนที่จะตอบคำถามเก่าที่มีคำตอบที่เป็นที่ยอมรับ (มองหา✓สีเขียว) รวมทั้งคำตอบอื่น ๆ ให้แน่ใจว่าคำตอบของคุณเพิ่มสิ่งใหม่หรือเป็นประโยชน์อย่างอื่นที่เกี่ยวข้องกับคำถามเหล่านี้ โปรดใช้ความระมัดระวังเมื่อตอบคำถามของ OP เราจะทำให้คลาส Java ไม่เปลี่ยนรูปได้อย่างไรความต้องการความไม่เปลี่ยนรูปคืออะไรและมีประโยชน์ในการใช้สิ่งนี้หรือไม่? . - คุณให้คำตอบเพียงบางส่วนซึ่งระบุว่าเราสามารถใช้ Lombok ซึ่งเป็นกรอบงาน / ไลบรารีของบุคคลที่สามซึ่งไม่จำเป็นต้องเป็นคำถามของ OP Java 15 ยังใช้ไม่ได้ทำไมต้องใช้ Lombok เมื่อrecordสามารถใช้Java ได้
Ivo Mori

ฉันกำลังให้ทางเลือกหนึ่งในการบรรลุเป้าหมายนี้ ไม่ใช่ทุกคนที่ใช้ Java 15 แอปพลิเคชันส่วนใหญ่ในปัจจุบันทำงานบนเวอร์ชันก่อนหน้าคุณจึงบอกว่าทำไมใช้ Lombok จึงไม่สมเหตุสมผล ในโครงการปัจจุบันของฉันเราเพิ่งย้ายไปที่ Java 11 และกำลังใช้ Lombok เพื่อให้ได้คลาสที่ไม่เปลี่ยนรูป นอกจากนี้คำตอบของฉันคือเพิ่มเติมจากคำตอบที่มีอยู่แล้ว สิ่งที่ไม่เปลี่ยนรูปได้มีคำตอบแล้วฉันเดาว่าคุณคาดหวังให้ฉันเขียนใหม่เพื่อให้เสร็จสมบูรณ์
Anubhav

พอใช้. ฉันไม่ลงหรือโหวตขึ้น ฉันพยายามชี้ให้เห็นเหตุผลที่คนอีกสองคนโหวตคำตอบนี้ ขึ้นอยู่กับคุณว่าคุณต้องการแก้ไขคำตอบของคุณอย่างไรและอย่างไร
Ivo Mori
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.