2009-01-26 55 views
8

Tôi hiện đang sở hữu một danh sách các đối tượng (sử dụng Java 1.3), và giả sử rằng tôi muốn bỏ một trong các đối tượng được trả về từ list.get (i) đến một loại mà tôi chỉ biết tên của lớp là một chuỗi. Về cơ bản, làm thế nào để tôi Đối tượng o = (classname) list.get (i); trong đó className là một biến String của một className.Truyền tới loại không xác định Khi chỉ cho tên lớp là một chuỗi loại đó

Tôi nghĩ rằng tôi có thể sử dụng (Class.forName (className)) list.get (i), nhưng tôi đã nhận được một lỗi cú pháp tuyên bố rằng tôi đã quên dấu chấm phẩy.

Thật không may, vì tôi đang sử dụng Java 1.3, tôi không có quyền truy cập vào phương thức Class.cast (Object).

Tên của lớp được sử dụng khi truyền sang loại khác trong Java 1.3 là gì? Có một số phương pháp có thể cho tôi đúng loại tôi cần với một tham số String của tên lớp?

+0

Nếu bạn nâng cấp phiên bản java của mình, hãy chuyển thẳng đến Java 6 vì Java 5 sẽ là EOL trong tháng 10. : -] –

Trả lời

5

Không, và bạn không thể thực hiện việc này trên hầu hết các ngôn ngữ.

Lý do là loại truyền đến phải được biết tại thời gian biên dịch, không phải lúc chạy (đó là những gì bạn đang cố gắng làm).

Nếu bạn nghĩ về điều đó, có ý nghĩa, bởi vì cho rằng biến có thể là bất kỳ tên loại nào, bạn có thể truy cập vào các thành viên khác nhau bằng cách nào? Bạn không thể, trừ khi chúng được định nghĩa trong một kiểu cơ sở/giao diện mà tất cả các cá thể thực hiện, trong trường hợp đó bạn chỉ nên sử dụng nó.

1

Tôi cho rằng bạn thực sự muốn viết những điều sau, thay vì sử dụng Object ở phía bên trái. Vì nếu không, nó thực sự chỉ là về việc kiểm tra xem đối tượng trong danh sách có đúng loại hay không.

ClassName o = (classname)list.get(i); 

Vâng, Java được nhập tĩnh. Bạn không thể cho nó một chuỗi và nó cung cấp cho bạn loại tĩnh tương ứng, để bạn có thể đi mà không cần truyền. Ngay cả với generics và Class<T>.cast, loại đích diễn viên không được đưa ra bởi một chuỗi, nhưng bởi các loại chung-đối số T, được biết đến tại thời gian biên dịch. Bạn phải tự truyền sang đúng loại hoặc tiếp tục sử dụng loại phổ biến nhất (có thể là đối tượng trong trường hợp của bạn).

Nếu bạn làm Class.forName(className), nó mang lại cho bạn trở lại một đối tượng của loại Class chứa các thông tin về loại tại thời gian chạy, do đó nó cho phép bạn làm

Class.forName("my.stuff.MyClass").newInstance() 

Nhưng các diễn viên muốn có một kiểu - không một đối tượng của một số loại. Đó là lý do tại sao trình biên dịch nói với bạn rằng có điều gì đó sai trái với mã đó.

Loại tĩnh của tham chiếu được trả về là Object. Điều này quan trọng: Kiểu động của một đối tượng được tham chiếu, và kiểu tĩnh của tham chiếu trỏ đến đối tượng đó. Kiểu động của đối tượng là những gì có thể được "điều khiển" bởi một chuỗi (bằng cách sử dụng Class.forName), nhưng kiểu tĩnh của tham chiếu mà bạn phải làm với thời gian biên dịch, và đó là (chỉ để đưa ra một ví dụ) được sử dụng để chọn các hàm quá tải lẫn nhau, không thể xác định bằng một chuỗi.

10

điểm đúc khi tất cả những gì bạn làm là gán kết quả cho đối tượng? Tất cả các bạn sẽ đạt được là một ngoại lệ nếu nó không thực hiện giao diện/mở rộng hoặc là lớp hoặc không làm gì nếu nó đã làm.

Cho rằng một đơn giản:

public static boolean IsInstance(object x, String className) 
    { 
    Class cls = Class.forName(className); 
    return cls.isInstance(x); 
    } 

là đủ (và sạch)

Nếu bạn đã phản xạ sử dụng để có được ở các lĩnh vực/phương thức của lớp đó chỉ là tốt

+0

Đó chính xác là điểm --- thất bại nhanh chóng, với ngoại lệ, đúng nơi xảy ra sự cố, thay vì một số thời gian và địa điểm không xác định sau. – erickson

+0

Cảm ơn !!! Điều đó rất hữu ích –

0

Câu hỏi là answered rồi, nhưng tôi muốn thêm rằng có vẻ như một chút không rõ ràng là bạn nên có một Danh sách mà bạn giữ một số loại đối tượng khác nhau (trong trường hợp này là bất kỳ đối tượng) pparently muốn gọi hoạt động trên chúng được cụ thể cho từng loại khác nhau ...

Điểm của bộ sưu tập này là gì? Không phải các trường hợp bạn giữ trong đó có bất kỳ điều gì chung - bất kỳ loại siêu phổ biến nào mà bạn có thể truyền vào chúng?

2

Một trường hợp cần thiết cho điều này là khi thực thi an toàn loại với hệ thống cũ. Ví dụ: giả sử bạn có một hệ thống kiên trì như Hibernate cung cấp một kết quả thô từ một phương pháp "công cụ tìm kiếm". Việc đúc List thô này thành một loại được tham số sẽ dẫn đến cảnh báo không được kiểm soát và nếu Danh sách chứa đối tượng sai loại, thì có thể tăng ClassCastException vào thời gian không xác định trong một số mã có liên quan xa. Nó có thể là tốt nhất để xác nhận các nội dung của danh sách lên phía trước, sử dụng một cơ chế như OP gợi ý.

Dưới đây là phiên bản Java 1.3 (không có Generics):

private static void checkType(Collection objs, String className) 
    throws ClassNotFoundException 
{ 
    Class clz = Class.forName(className); 
    Iterator i = objs.iterator(); 
    while (i.hasNext()) { 
    Object obj = i.next(); 
    if (!clz.isInstance(obj)) { 
     throw new ClassCastException(); 
    } 
    } 
} 

Trong Java 5 và sau đó, với generics, bạn có thể làm điều gì đó tương tự với Class.cast() phương pháp để xác minh các nội dung của một bộ sưu tập, biện minh việc sử dụng của một chú thích SuppressWarnings. Trong quá trình xem xét của chúng tôi, ngăn chặn một cảnh báo mà không có một số "bằng chứng" rằng nó là an toàn được nộp như là một lỗi.

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