Please provide some basic information of how TypeLiteral
in Google Guice or Java EE is used, It will be very helpful if it would be explained using a simple code, thanks in advance
The purpose of TypeLiteral
in Guice is to allow you to bind classes and instances to generic types (with type parameters specified) avoiding the problems stemming from the fact that generics are not reified in Java, i.e. from the fact that erasure hides the difference between SomeInterface<String>
and SomeInterface<Integer>
at runtime. TypeLiteral
allows the value of a generic parameter survive erasure by creating an ad hoc subclass of the generic type.
Example usage of TypeLiteral
:
bind(new TypeLiteral<SomeInterface<String>>(){})
.to(SomeImplementation.class);
This binds a parameter of type SomeInterface<String>
to SomeImplementation
class.
For some background information have a look at this blog post on super type tokens and then this one on type literals.
This is a way how guys bypass generics erasure in java. You need it, when you want ot bind some implementation to parametrized(generic) interface. Found some usage in Guice docs:
bind(new TypeLiteral<PaymentService<CreditCard>>() {})
.to(CreditCardPaymentService.class);
This admittedly odd construct is the way to bind a parameterized type. It tells Guice how to honor an injection request for an element of type PaymentService. The class CreditCardPaymentService must implement the PaymentService interface. Guice cannot currently bind or inject a generic type, such as Set; all type parameters must be fully specified.
Like anything in Guice - modularity, reusability, and removal of boilerplate are core concepts of all utilities.
Of course, anything you do in Guice can be mimicked in Java - at the cost of lots of boilerplate So... the real question is :
How can we USE TypeLiterals to write more modular/reusable components ?
The power of TypeLiterals in Guice is that it allows you to refernce implementations of a service without defining what that service is.
Lets start with a simple list in a program where we have many types of lists that are processed differntly :
List<String> myStringList = new ArrayList<String>();
Now, how should I process these Strings ? At runtime, there is no way to "know" that its a String list. So, often times I might create a factory, like so , that gets processing objects for me :
ProcessorFactory.get(String.class).process(myStringList);
Thus, I might use a factory (with a bunch of if/else or case statements) to define processors for different data types. My constructor, for the object which uses these processors, and which needs access to various Processor Implementations, might look like this :
public MyClass(Processor<String> strProcessor, Processor<Integer> intProcessor)P
{
//Simple enough, but alot of boiler plate is required to launch this constructor.
}
//and to invoke
new MyClass(PRocessorFactory.get(....), ProcessorFactory.get(...));
All good so far... Until we realize that there is a better way :
In the Guice world, I can forget about writing this factory - rather, I can explicitly BIND classes to processors. The advantage of this is that there are no static dependencies - the class which needs to USE processor implementations DOES NOT need any static dependency on a factory -rather, the classes are directly injected. Thus, I can easily define a class which uses complex dependencies, without having to build a factory aware class builder... Thus, I have far less boilerplate :
@Inject
public MyClass(Processor<String> implStr, Processor<Integer> implInt)
{
//Now , this method will work magically, because Guice is capable of
//Using the loaded modules, which define bindings between generics and their implementations
}
//Elsewhere I simply define a single guice module that does the binding, and make sure to load it before my application launches.
There is a good tutorial on this with interface implementations and binding examples, here : http://thejavablog.wordpress.com/2008/11/17/how-to-inject-a-generic-interface-using-guice/
The TypeLiteral
class is a workaround for the fact that you cannot have class literals for generic types. The API doc of Binder
(this is from Google Guice, but the Java EE class of the same name has exactly the same purpose) gives an example for how it's used:
bind(new TypeLiteral<PaymentService<CreditCard>>() {})
.to(CreditCardPaymentService.class);
This specifies that any auto-injected reference of type PaymentService<CreditCard>
will be implemented by the concrete class CreditCardPaymentService
, leaving the option for PaymentService<Coupon>
to be implemented by a different class. Without TypeLiteral
, this would not be possible because the Java compiler will accept PaymentService<CreditCard>.class
, only PaymentService.class
.
Note that this also requires the use of anonymous subclasses (the {}
after new TypeLiteral<PaymentService<CreditCard>>()
) in order to work around type erasure.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With