2010-04-05 33 views
25

Tôi đang cố gắng di chuyển một dự án nhỏ, thay thế một số nhà máy với Guice (đây là thử nghiệm Guice đầu tiên của tôi). Tuy nhiên, tôi bị mắc kẹt khi cố gắng tiêm thuốc generic. Tôi quản lý để trích xuất một ví dụ đồ chơi nhỏ với hai lớp và một mô-đun:Tiêm generics với Guice

import com.google.inject.Inject; 

public class Console<T> { 
    private final StringOutput<T> out; 
    @Inject 
    public Console(StringOutput<T> out) { 
    this.out = out; 
    } 
    public void print(T t) { 
    System.out.println(out.converter(t)); 
    } 
} 

public class StringOutput<T> { 
    public String converter(T t) { 
    return t.toString(); 
    } 
} 

import com.google.inject.AbstractModule; 
import com.google.inject.Guice; 
import com.google.inject.Injector; 
import com.google.inject.TypeLiteral; 


public class MyModule extends AbstractModule { 

    @Override 
    protected void configure() { 
    bind(StringOutput.class); 
    bind(Console.class); 
    } 

    public static void main(String[] args) { 
    Injector injector = Guice.createInjector(new MyModule()); 
    StringOutput<Integer> out = injector.getInstance(StringOutput.class); 
    System.out.println(out.converter(12)); 
    Console<Double> cons = injector.getInstance(Console.class); 
    cons.print(123.0); 
    } 

} 

Khi tôi chạy ví dụ này, tất cả tôi nhận được là:

Exception in thread "main" com.google.inject.CreationException : Lỗi tạo sự cố:

1) playground.StringOutput<T> cannot be used as a key; It is not fully specified. 
    at playground.MyModule.configure(MyModule.java:15) 

1 error 
    at com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:354) 
    at com.google.inject.InjectorBuilder.initializeStatically(InjectorBuilder.java:152) 
    at com.google.inject.InjectorBuilder.build(InjectorBuilder.java:105) 
    at com.google.inject.Guice.createInjector(Guice.java:92) 

Tôi đã tìm kiếm thông báo lỗi nhưng không tìm thấy bất kỳ gợi ý hữu ích nào. Hơn nữa trên các câu hỏi thường gặp Guice Tôi vấp ngã khi một câu hỏi về cách tiêm generics. Tôi đã cố gắng thêm ràng buộc sau vào phương thức configure:

bind(new TypeLiteral<StringOutput<Double>>() {}).toInstance(new StringOutput<Double>()); 

Nhưng không thành công (cùng một thông báo lỗi).

Ai đó có thể giải thích cho tôi thông báo lỗi và cung cấp cho tôi một số mẹo không? Cảm ơn.

Trả lời

27

Tôi nghĩ rằng vấn đề cụ thể mà bạn đang thấy có thể là do tuyên bố bind(Console.class). Nó cũng nên sử dụng TypeLiteral. Hoặc, bạn chỉ có thể ràng buộc không phải của những người và các ràng buộc JIT sẽ chăm sóc nó cho bạn vì cả hai loại liên quan ở đây là các lớp cụ thể.

Ngoài ra, bạn nên lấy Console với:

Console<Double> cons = 
    injector.getInstance(Key.get(new TypeLiteral<Console<Double>>(){})); 

Edit: Bạn không cần phải liên kết với một thể hiện chỉ vì bạn đang sử dụng một TypeLiteral. Bạn chỉ có thể làm:

bind(new TypeLiteral<Console<Double>>(){}); 

Tất nhiên, như tôi đã nói ở trên, bạn chỉ có thể bỏ qua rằng trong trường hợp này và lấy Console từ các vòi phun sử dụng một Key dựa trên TypeLiteral và các ràng buộc sẽ là tiềm ẩn.

+0

Cảm ơn. Tôi không chắc chắn làm thế nào để ràng buộc một TypeLitteral để Console bởi vì tôi không thể làm cho một thể hiện của Console mà không có một thể hiện StringOutput. Bạn có thể chi tiết? – paradigmatic

+0

Xem chỉnh sửa của tôi ... bạn không cần sử dụng toInstance(). – ColinD

+0

Tôi vừa thử. Nó hoạt động chỉ khi tôi xác định cả hai loại litterals AND y sử dụng Key để có được thể hiện. Vì vậy, tôi không thể làm cho ràng buộc rõ ràng. – paradigmatic

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