2013-02-12 35 views
7

Tôi có một vấn đề với sự hiểu biết như phương pháp tổng quát gọi:Generic phương pháp gọi với <T>

object = ObjectGenerator.<T> getObject(objectName); 

Ở đây có một bối cảnh cho tình trạng trên:

class GenClass<T> { 

    private T object; 

    // ... some code 

    public void initObject(String objectName) { 
     object = ObjectGenerator.<T> getObject(objectName); 
    } 
} 

class ObjectGenerator { 

    public static <T extends Object> T getObject(String name) { 
     // some code 
     return someObject; 
    } 
} 

Câu hỏi đặt ra là vai trò gì chơi <T> trước getObject(objectName) yêu cầu?

+1

+1 vì trước đây tôi chưa từng thấy điều này. –

+0

Tôi không hỏi về ý nghĩa của nó, nhưng chỉ là về một dòng mã. Tôi có thể thay đổi chữ ký phương thức thành ' T getObject (Tên chuỗi, Class clazz)' - nó không quan trọng. Chỉ có một dòng này với lời gọi phương thức đó với '' gây nhầm lẫn cho tôi – emka86

Trả lời

7

Lưu ý: trong ví dụ cụ thể bạn đã đưa ra, ObjectGenerator.getObject(objectName); nên biên dịch tiền phạt.

Trong một số trường hợp, cơ chế suy luận kiểu không thể giải quyết một thực tế rằng trong:

T object; 
object = ObjectGenerator.getObject(objectName); 

loại trở nên T. Trong trường hợp này, bạn cần cung cấp cho trình biên dịch một chút trợ giúp bằng cách chỉ rõ kiểu trả về mà bạn mong đợi.

Dưới đây là một ví dụ giả tạo, nơi bạn cần phải xác định rõ kiểu dữ liệu tổng quát:

class Example { 
    public static <T> List<T> m1() { 
     return m2(Arrays.<T> asList()); //Arrays.asList() would not compile 
    } 
    public static <T> List<T> m2(List<T> l) { 
     return l; 
    } 
} 
+0

Trong tình huống nào thì "cơ chế suy luận kiểu" không thể biết kiểu trả về là gì? – asteri

+0

@ Jeff Tôi đã thêm một ví dụ - các tình huống chính xác khi điều này xảy ra phụ thuộc vào kết quả của việc áp dụng [quy tắc suy luận loại] (http://docs.oracle.com/javase/specs/jls/se7/html/jls- 15.html # jls-15.12.2.7), dài khoảng 12 trang trong phiên bản pdf của JLS, vì vậy không hoàn toàn chắc chắn phải trung thực. Cuối cùng cách tôi nhìn vào nó là: hoặc là nó biên dịch mà không có loại rõ ràng và tôi hạnh phúc hoặc nó không và tôi chỉ cần thêm nó ... – assylias

+0

Vâng, tôi hiểu rồi! Đây là lời giải thích rất tốt cho tôi và nhìn vào thông số này từ liên kết của bạn, tôi đoán có nhiều tình huống khó chịu hơn để khám phá! :) – emka86

0

object có thể con của T.

Tất nhiên getObject nên tốt hơn đã được xác định:

public static <T> T getObject(Class<T> objectClass, String name) { 
    return objectClass.getConstructor(String.class).newInstance(name); 
    //return objectClass.getConstructor().newInstance(); 
} 

khác không có loại an toàn xây dựng có thể, vì cái gọi là loại tẩy xoá.

-1
object = ObjectGenerator.getObject(objectName); 

luôn trả về đối tượng Object kể từ khi bạn đang gọi một phương thức tĩnh. Để nhận rõ ràng đối tượng chung mà bạn đã sử dụng cho T, trong mã của bạn,

object = ObjectGenerator.<T> getObject(objectName); 

<T> được sử dụng trong ngữ cảnh tĩnh. Đối với lời gọi không tĩnh, nó không cần thiết.

+0

-1 Ngữ cảnh tĩnh không liên quan gì đến việc cung cấp các đối số kiểu rõ ràng. –

+0

cảm ơn vì đã khai sáng cho tôi :) – prasanth

0

Tôi tìm thấy mọi thứ ở đây: https://stackoverflow.com/a/338906/443427 nó có thể giúp bạn.

Từ những gì tôi đọc được đại diện chung mà trình biên dịch phải sử dụng để tính toán các loại giá trị retuned, để vượt qua generic mong

như một ghi chú này cũng hoạt động tốt (kiểm tra ObjectGenerator khác với T):

public class ObjectGenerator<X> { 
    public static <T extends Object> Set<T> getObject(String name) { 
    // some code 
    return null; 
    } 
} 
0

tôi không hoàn toàn đồng ý với câu trả lời được chấp nhận, trong đó nó nói:

trong trường hợp này, bạn cần cung cấp cho các trình biên dịch một chút giúp đỡ bằng cách dứt khoát cho biết kiểu trả về bạn mong đợi.

Điều này không đúng với tôi. Khi tôi hiểu phương pháp chung và suy luận kiểu, kiểu được cung cấp trong dấu ngoặc vuông không trực tiếp biểu thị kiểu trả về của phương thức chung. Thay vào đó, loại T có thể là loại trả về, loại đối số, loại biến cục bộ được liên kết với phương pháp chung.

Thực tế, nhờ cơ chế suy luận loại, chúng tôi không cần phải chỉ định tham số loại T trong hầu hết các trường hợp (không chỉ trong một số trường hợp). Trong ví dụ của bạn, <T> có thể được bỏ qua một cách an toàn khỏi lời gọi phương thức ObjectGenerator.<T> getObject(objectName) như trong hầu hết các trường hợp khác. Điều này là do loại T của phương pháp chung có thể dễ dàng suy ra từ loại kết quả được chỉ định hoặc trả về. Nói cách khác, vì bạn khai báo private T object trước khi phương thức gọi loại T sẽ được suy ra thành công là T.

tuyên bố Mỹ có thể được hỗ trợ bởi các tuyên bố sau từ a definitive tutorial:

Loại suy luận là khả năng của một trình biên dịch Java để nhìn vào từng phương pháp invocation và tuyên bố tương ứng để xác định loại luận (hoặc đối số) điều đó làm cho lời gọi được áp dụng. Thuật toán suy luận xác định loại đối số và, nếu có sẵn, loại kết quả được gán hoặc trả về. Cuối cùng, thuật toán suy luận cố gắng tìm loại cụ thể nhất hoạt động với tất cả các đối số.

Hai ví dụ về cách suy luận hoạt động:

static <T> T pick(T a1, T a2) { return a2; } 
Serializable s = pick("d", new ArrayList<String>()); 

Loại T được suy ra như Serializable dựa trên loại chuyển nhượng kê khai.

public static <U> void addBox(U u, java.util.List<Box<U>> boxes) {} 
BoxDemo.<Integer>addBox(Integer.valueOf(10), listOfIntegerBoxes); 

Loại U được suy ra như Integer dựa trên các loại của các đối số truyền (nghĩa là., Integer.valueOf(10) là loại Integer). Do đó, <Integer> có thể được bỏ qua một cách an toàn khỏi lời gọi phương thức ở trên. Để tóm tắt, trừ khi chúng tôi không thể suy ra tham số kiểu của phương thức chung từ kiểu đối số hoặc loại kết quả được gán hoặc trả về (khi gọi phương thức), chúng tôi có thể bỏ qua một cách an toàn đặc tả kiểu ngay trước khi gọi phương thức.

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