2012-01-18 30 views
16

thể trùng lặp:
Java Class.cast() vs. cast operatorCast thông qua phản ánh và sử dụng Class.cast()

Tôi không thành công cố gắng tìm ra những gì hiện Class.cast() làm hoặc những gì nó có thể là tốt cho , trong cùng một thời gian, tôi tự hỏi liệu tôi có thể bằng cách nào đó đúc một đối tượng thông qua sự phản chiếu.

Trước tiên tôi nghĩ cái gì đó như dòng dưới đây có thể đã làm việc, sai:

Object o = "A string"; 
String str = Class.forName("java.lang.String").cast(object); 

Nhưng mà không cần diễn viên rõ ràng nó không hoạt động.

Vì vậy, phương pháp cast của lớp học Class là gì? Và bằng cách nào đó nó có thể chỉ với sự phản chiếu để đúc các đối tượng, vì vậy bạn tìm thấy lớp của đối tượng, sử dụng Class.forName trên nó và bỏ nó bằng cách nào đó?

+0

Có một lời giải thích tốt: [http://stackoverflow.com/questions/2092659/what-is-difference-between-class-forname-and-class-forname-newinstance][1] [1]: http://stackoverflow.com/questions/2092659/what-is-difference-between-class-forname-and-class-forname-newinstance – Pawel

Trả lời

23

Một ví dụ mà là làm việc:

class Favorites { 
    private Map<Class<?>, Object> map = new HashMap<Class<?>, Object>(); 

    public <T> T get(Class<T> clazz) { 
     return clazz.cast(map.get(clazz)); 
    } 

    public <T> void put(Class<T> clazz, T favorite) { 
     map.put(clazz, favorite); 
    } 
} 

cho phép bạn viết:

Favorites favs = new Favorites(); 
favs.put(String.class, "Hello"); 
String favoriteString = favs.get(String.class); 

Lý do mã của bạn không hoạt động là Class.forName() trả về một Class<?>, tức là một đối tượng lớp đại diện cho một loại không xác định. Trong khi trình biên dịch có thể suy ra loại trong ví dụ của bạn, nó có thể không nói chung. Hãy xem xét:

Class.forName(new BufferedReader(System.in).readLine()) 

loại biểu thức này là gì?Rõ ràng trình biên dịch không thể biết tên lớp sẽ là gì khi chạy, vì vậy nó không biết liệu

String s = Class.forName(new BufferedReader(System.in).readLine()).cast(o); 

là an toàn. Vì vậy nó yêu cầu một diễn viên rõ ràng.

4

Loại trả lại là Class.forName sẽ là Class<? extends Object>. Bạn muốn Class<? extends String>, ví dụ sử dụng String.class.

String str = String.class.cast(object); 

Không hữu ích lắm, cho đến khi bạn bắt đầu thay thế String bằng loại giao diện nào đó.

Trong mọi trường hợp, sự phản ánh thường là xấu.

+3

Nếu không có sự phản ánh, không ai trong chúng ta vẫn sẽ thảo luận về Java 17 năm sau khi nó được phát minh. – skaffman

+0

@staffman Vâng, tôi chắc chắn sẽ có một công việc nhỏ hơn. (Oh, và 17 năm sau khi fcs. (Mà không có sự phản ánh.)) –

2

Class.forName sẽ trả về đối tượng loại Class<?>. Phương thức cast sẽ trả về tham số kiểu của Lớp. Vì vậy, trong trường hợp này nó sẽ trả về một? (Object) loại đối tượng.

Bạn nên thử:

Class<String> strClass = (Class<String>) Class.forName("java.lang.String"); 
String str = strClass.cast(object); 

cũng Class.cast()

+2

'Lớp strClass = String.class.asSubclass (Class.forName ("java.lang.String")); ' –

+0

Đó là tốt đẹp, đã không nhận thức được nó. –

+0

điều gì sẽ xảy ra nếu kiểu trả về của lớp Class.cast (đối tượng) cũng là một lớp cần được phản ánh, làm thế nào để tôi đưa đối tượng vào nó? –

2

Xem Bạn có thể tránh được một cảnh báo ví dụ với đoạn mã sau:

public <T> T getObject(Class<T> type){ 
    Object o = getSomeObject(); 
    if (type.isInstance(o)){ 
    return type.cast(o); 
    } else { 
    return null; 
    } 
} 

trong khi đoạn mã sau sẽ nâng cao một cảnh báo:

public <T> T getObject(){ 
    return (T) getSomeObject(); 
} 
+0

Ai đó có thể đặt một ví dụ về việc sử dụng phương thức getObject đầu tiên? Cảm ơn bạn. – jechaviz

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