2011-02-09 57 views
11

Nếu tôi có một lớp học com.example.test.Enum2.Test như trong mã bên dưới, tại sao getCanonicalName() trả lại com.example.test.Enum2.Test nhưng Class.forName() yêu cầu "com.example.test.Enum2$Test" làm đối số?

Có cách nào nhất quán không, vì vậy mà tôi có thể tuần tự hóa/deserialize một giá trị enum theo tên của nó, mà không cần phải kiểm tra từng $ vs . khả năng, khi enum là một lớp lồng nhau?

package com.example.test; 

import java.util.Arrays; 

public class Enum2 { 

    enum Test { 
     FOO, BAR, BAZ; 
    } 

    public static void main(String[] args) { 
     for (String className : Arrays.asList(
       "com.example.test.Enum2.Test", 
       "com.example.test.Enum2$Test")) 
     { 
      try { 
       Class<?> cl = Class.forName(className); 
       System.out.println(className+" found: "+cl.getCanonicalName()); 
      } 
      catch (ClassNotFoundException e) { 
       e.printStackTrace(); 
      } 
     } 

     System.out.println(Test.FOO.getDeclaringClass().getCanonicalName()); 
    } 
} 

làm rõ: Tôi đang tìm kiếm một cách tốt để đối phó với vấn đề này trong một ứng dụng thực tế (không chỉ các trường hợp thử nghiệm giả tạo ở trên), hoặc là:

a. serialize/deserialize bằng cách sử dụng kết quả đầu ra của getCanonicalName() (chỉ có tên chấm chấm), và đối với mỗi lần Class.forName(), hãy thử từng khả năng, ví dụ: trước tiên "com.example.test.Enum2.Test", sau đó "com.example.test.Enum2$Test", sau đó "com.example.test$Enum2$Test", v.v.

b. sử dụng ký hiệu $ thích hợp, để Class.forName() hoạt động ngay lần đầu tiên. Nhưng điều này đòi hỏi tôi phải thực hiện một thay thế cho getCanonicalName() tạo ra một chuỗi phù hợp với Class.forName().

Tôi nghiêng về phía tiếp cận (b), một phần do cảm giác ruột, và một phần vì phương pháp tiếp cận (a) có sự mơ hồ nếu có tên gói có chữ in hoa: com.example.Test.Enum2 và com.example.Test $ Enum2 có thể là đầu vào hợp lệ cho Class.forName() nếu có một com/example/Test/Enum2.java, và một ví dụ// Test.java chứa một lớp bên trong Enum2.

... nhưng tôi không biết cách triển khai. Ý tưởng nào?

Trả lời

9

ARGH: Tôi phải sử dụng đơn giản Class.getName() thay vì Class.getCanonicalName().

5

Vâng, tài liệu cho getCanonicalName nhà nước:

Trả về tên kinh điển của lớp cơ bản theo quy định của ngôn ngữ Java Specification.

(tôi nhấn mạnh).

Trong Java các ngôn ngữ, làm tổ được biểu thị bằng một dấu chấm. Theo như các thư viện và máy ảo có liên quan, lớp lồng nhau chỉ là một lớp với một $ trong tên.

Bạn chưa nói loại serialization nào bạn đang nói - miễn là bạn nhất quán cho cả hai hướng, nó sẽ ổn thôi.

+0

bummer. do đó tên của ngôn ngữ! = tên của máy ảo. :-(Có cách nào dễ dàng hơn để chuyển đổi ký hiệu chấm chấm thành $ thích hợp, mà không phải thử từng khả năng lần lượt không? (Ví dụ: com.example.test.Enum2.Test, com.example.test.Enum2 $ Test, com .example.test $ Enum2 $ Test, v.v.) –

+0

@Jason S: Không, tiếc là nó không rõ ràng. xyz.ABC có thể có nghĩa là 'xyz.ABC', hoặc' xyz.AB $ C', hoặc 'xyz.A $ B $ C' hoặc 'xyz $ A $ B $ C'." Phiên bản đô la "là rõ ràng mặc dù –

+0

ok, cảm ơn, đó là những gì tôi nghĩ. (+1 cho lời giải thích) –

Các vấn đề liên quan