Có cách nào để giải quyết các vấn đề tải lớp do có hai enums tham chiếu lẫn nhau không?Java Enums: Hai loại enum, mỗi loại chứa tham chiếu với nhau?
Tôi có hai bộ enumerations, Foo và Bar, được xác định như sau:
public class EnumTest {
public enum Foo {
A(Bar.Alpha),
B(Bar.Delta),
C(Bar.Alpha);
private Foo(Bar b) {
this.b = b;
}
public final Bar b;
}
public enum Bar {
Alpha(Foo.A),
Beta(Foo.C),
Delta(Foo.C);
private Bar(Foo f) {
this.f = f;
}
public final Foo f;
}
public static void main (String[] args) {
for (Foo f: Foo.values()) {
System.out.println(f + " bar " + f.b);
}
for (Bar b: Bar.values()) {
System.out.println(b + " foo " + b.f);
}
}
}
Đoạn mã trên tạo ra như đầu ra:
A bar Alpha
B bar Delta
C bar Alpha
Alpha foo null
Beta foo null
Delta foo null
Tôi hiểu tại sao nó xảy ra - JVM bắt đầu classloading Foo; nó thấy Bar.Alpha trong hàm tạo của Foo.A, vì vậy nó bắt đầu nạp lớp Bar. Nó nhìn thấy tham chiếu Foo.A trong lời gọi đến hàm tạo của Bar.Alpha, nhưng (vì chúng ta vẫn còn trong hàm tạo của Foo.A) Foo.A là null vào thời điểm này, nên hàm tạo của Bar.Alpha được truyền vào một giá trị rỗng. Nếu tôi đảo ngược hai vòng lặp (hoặc tham chiếu Bar trước khi Foo), đầu ra thay đổi để các giá trị của Bar là chính xác, nhưng giá trị của Foo thì không.
Có cách nào để giải quyết vấn đề này không? Tôi biết tôi có thể tạo ra một bản đồ tĩnh và một bản đồ tĩnh trong một lớp thứ ba, nhưng điều đó cảm thấy khá khó chịu với tôi. Tôi cũng có thể làm cho các phương thức Foo.getBar() và Bar.getFoo() tham chiếu đến bản đồ bên ngoài, vì vậy nó thậm chí sẽ không thay đổi giao diện của tôi (các lớp thực tế tôi đã sử dụng thanh tra thay vì các trường công khai), nhưng nó vẫn cảm thấy loại ô uế với tôi.
(Lý do tôi làm điều này trong hệ thống thực tế của mình: Foo và Bar đại diện cho các loại thông báo mà 2 ứng dụng gửi cho nhau; các trường Foo.b và Bar.f thể hiện kiểu phản hồi mong đợi cho một thông báo đã cho - vì vậy trong mã mẫu của tôi, khi app_1 nhận được Foo.A, nó cần phải trả lời bằng Bar.Alpha và ngược lại.)
Cảm ơn bạn trước!
Dường như với tôi như quá phức tạp. @ weiji của câu trả lời là sạch hơn nhiều, IMO. Tại sao cách tiếp cận này tốt hơn (bạn nói "tốt nhất")? –
@NoamNelke Tôi đã bình chọn cách tiếp cận của weiji, điều này rất thú vị. Mặc dù cá nhân tôi nghĩ tốt hơn cách tôi khuyên dùng vì tham chiếu tuần hoàn nằm trong enum của nó, khác biệt lớn giữa các câu trả lời của chúng tôi là tôi cũng cho phép bạn thực hiện bất kỳ logic thời gian chạy nào trước khi quay trở lại, ví dụ: 'public bar getBar (boolean nullIfAlpha) {return nullIfAlpha? null: Bar.Alpha; } '. Dù sao, tôi đã chỉnh sửa câu trả lời của tôi cho "một trong những điều tốt nhất" thay vào đó, vì nó có thể dựa trên ý kiến. Cảm ơn vì đã trả lời! – falsarella