Khi tôi tháo rời một enum với javap, các đối số hàm tạo ngầm của enum dường như bị thiếu và tôi không thể hiểu tại sao.Enum tháo rời với javap không hiển thị đối số hàm tạo
Dưới đây là một enum:
enum Foo { X }
tôi biên dịch và tháo rời này (trên Java 8u60) với lệnh này:
javac Foo.java && javap -c -p Foo
Và đây là kết quả tôi nhận được:
final class Foo extends java.lang.Enum<Foo> {
public static final Foo X;
private static final Foo[] $VALUES;
public static Foo[] values();
Code:
0: getstatic #1 // Field $VALUES:[LFoo;
3: invokevirtual #2 // Method "[LFoo;".clone:()Ljava/lang/Object;
6: checkcast #3 // class "[LFoo;"
9: areturn
public static Foo valueOf(java.lang.String);
Code:
0: ldc #4 // class Foo
2: aload_0
3: invokestatic #5 // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
6: checkcast #4 // class Foo
9: areturn
private Foo(); // <--- here
Code:
0: aload_0
1: aload_1
2: iload_2
3: invokespecial #6 // Method java/lang/Enum."<init>":(Ljava/lang/String;I)V
6: return
static {};
Code:
0: new #4 // class Foo
3: dup
4: ldc #7 // String X
6: iconst_0
7: invokespecial #8 // Method "<init>":(Ljava/lang/String;I)V
10: putstatic #9 // Field X:LFoo;
13: iconst_1
14: anewarray #4 // class Foo
17: dup
18: iconst_0
19: getstatic #9 // Field X:LFoo;
22: aastore
23: putstatic #1 // Field $VALUES:[LFoo;
26: return
}
Sự nhầm lẫn của tôi là với hàm tạo riêng tư được sử dụng để khởi tạo từng hằng số enum. Việc tháo gỡ cho thấy rằng nó không có đối số (private Foo();
), nhưng nó chắc chắn không có đối số. Ví dụ: bạn có thể thấy các hướng dẫn load
đọc tên hằng số enum được truyền và thứ tự, cũng như con trỏ this
và chuyển chúng đến the superclass constructor, yêu cầu chúng. Mã trong khối khởi tạo tĩnh cũng cho thấy rằng nó đẩy các đối số đó vào ngăn xếp trước khi gọi hàm tạo.
Bây giờ tôi sẽ giả định đây chỉ là một lỗi khó hiểu trong javap, nhưng khi tôi biên dịch chính xác enum cùng với trình biên dịch của Eclipse và tháo rời rằng việc sử dụng javap, các nhà xây dựng là hoàn toàn giống nhau, ngoại trừ các đối số là hiển thị:
final class Foo extends java.lang.Enum<Foo> {
public static final Foo X;
private static final Foo[] ENUM$VALUES;
static {};
Code:
0: new #1 // class Foo
3: dup
4: ldc #12 // String X
6: iconst_0
7: invokespecial #13 // Method "<init>":(Ljava/lang/String;I)V
10: putstatic #17 // Field X:LFoo;
13: iconst_1
14: anewarray #1 // class Foo
17: dup
18: iconst_0
19: getstatic #17 // Field X:LFoo;
22: aastore
23: putstatic #19 // Field ENUM$VALUES:[LFoo;
26: return
private Foo(java.lang.String, int); // <--- here
Code:
0: aload_0
1: aload_1
2: iload_2
3: invokespecial #23 // Method java/lang/Enum."<init>":(Ljava/lang/String;I)V
6: return
public static Foo[] values();
Code:
0: getstatic #19 // Field ENUM$VALUES:[LFoo;
3: dup
4: astore_0
5: iconst_0
6: aload_0
7: arraylength
8: dup
9: istore_1
10: anewarray #1 // class Foo
13: dup
14: astore_2
15: iconst_0
16: iload_1
17: invokestatic #27 // Method java/lang/System.arraycopy:(Ljava/lang/Object;ILjava/lang/Object;II)V
20: aload_2
21: areturn
public static Foo valueOf(java.lang.String);
Code:
0: ldc #1 // class Foo
2: aload_0
3: invokestatic #35 // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
6: checkcast #1 // class Foo
9: areturn
}
câu hỏi của tôi là: những gì chất là khác nhau giữa một enum javac biên dịch và một enum Eclipse biên soạn gây javap để không hiển thị các đối số nhà xây dựng cho enum javac biên dịch? Và sự khác biệt này là một lỗi (trong javap, trong javac, hoặc Eclipse)?
Khi đoán, cài đặt cờ '-g' (kiểm soát việc tạo thông tin gỡ lỗi). – CPerkins
@CPerkins Giả thuyết tốt nhưng tôi đã so sánh '-g' (tạo tất cả thông tin gỡ lỗi) và' -g: none' (không tạo ra thông tin gỡ lỗi) và dường như không tạo ra sự khác biệt nào. – Boann
Bạn đã thử cờ '-v' (tiết) chưa? Nó ít nhất sẽ cho bạn thấy bộ mô tả của hàm tạo. Tôi đoán là 'javac' đánh dấu các tham số đầu tiên' MANDATED', có thể làm cho 'javap' bỏ qua chúng. – Clashsoft