0
# Type System & Keys
1
2
Type-safe dependency identification system supporting generic types and binding annotations for distinguishing multiple bindings of the same type.
3
4
## Capabilities
5
6
### Key Class
7
8
Identifies a dependency that can be resolved by the Injector, combining type information with optional binding annotations.
9
10
```java { .api }
11
/**
12
* Identifies a dependency that can be resolved by the Injector.
13
* A key is composed of a type and optional binding annotation.
14
* @param <T> Type of the dependency
15
*/
16
public class Key<T> {
17
/**
18
* Creates a key for the given type.
19
* @param type Class type
20
* @return Key for the type
21
*/
22
public static <T> Key<T> get(Class<T> type);
23
24
/**
25
* Creates a key for the given type with annotation type.
26
* @param type Class type
27
* @param annotationType Binding annotation type
28
* @return Key for the type with annotation
29
*/
30
public static <T> Key<T> get(Class<T> type, Class<? extends Annotation> annotationType);
31
32
/**
33
* Creates a key for the given type with annotation instance.
34
* @param type Class type
35
* @param annotation Binding annotation instance
36
* @return Key for the type with annotation
37
*/
38
public static <T> Key<T> get(Class<T> type, Annotation annotation);
39
40
/**
41
* Creates a key for the given type.
42
* @param type Type instance
43
* @return Key for the type
44
*/
45
public static Key<?> get(Type type);
46
47
/**
48
* Creates a key for the given type with annotation type.
49
* @param type Type instance
50
* @param annotationType Binding annotation type
51
* @return Key for the type with annotation
52
*/
53
public static Key<?> get(Type type, Class<? extends Annotation> annotationType);
54
55
/**
56
* Creates a key for the given type with annotation instance.
57
* @param type Type instance
58
* @param annotation Binding annotation instance
59
* @return Key for the type with annotation
60
*/
61
public static Key<?> get(Type type, Annotation annotation);
62
63
/**
64
* Creates a key for the given type literal.
65
* @param typeLiteral Type literal
66
* @return Key for the type literal
67
*/
68
public static <T> Key<T> get(TypeLiteral<T> typeLiteral);
69
70
/**
71
* Creates a key for the given type literal with annotation type.
72
* @param typeLiteral Type literal
73
* @param annotationType Binding annotation type
74
* @return Key for the type literal with annotation
75
*/
76
public static <T> Key<T> get(TypeLiteral<T> typeLiteral, Class<? extends Annotation> annotationType);
77
78
/**
79
* Creates a key for the given type literal with annotation instance.
80
* @param typeLiteral Type literal
81
* @param annotation Binding annotation instance
82
* @return Key for the type literal with annotation
83
*/
84
public static <T> Key<T> get(TypeLiteral<T> typeLiteral, Annotation annotation);
85
86
/**
87
* Returns the type literal for this key.
88
* @return TypeLiteral representing the type
89
*/
90
public TypeLiteral<T> getTypeLiteral();
91
92
/**
93
* Returns the binding annotation type, or null if none.
94
* @return Annotation type or null
95
*/
96
public Class<? extends Annotation> getAnnotationType();
97
98
/**
99
* Returns the binding annotation instance, or null if none.
100
* @return Annotation instance or null
101
*/
102
public Annotation getAnnotation();
103
104
/**
105
* Creates a new key with the same annotation but different type.
106
* @param type New type
107
* @return Key with new type
108
*/
109
public <U> Key<U> ofType(Class<U> type);
110
111
/**
112
* Creates a new key with the same annotation but different type.
113
* @param type New type
114
* @return Key with new type
115
* @since 3.0
116
*/
117
public Key<?> ofType(Type type);
118
119
/**
120
* Creates a new key with the same annotation but different type literal.
121
* @param typeLiteral New type literal
122
* @return Key with new type literal
123
* @since 3.0
124
*/
125
public <U> Key<U> ofType(TypeLiteral<U> typeLiteral);
126
127
/**
128
* Returns a new key of the same type with the specified annotation.
129
* @param annotationType Annotation type to use
130
* @return Key with specified annotation
131
* @since 5.0
132
*/
133
public Key<T> withAnnotation(Class<? extends Annotation> annotationType);
134
135
/**
136
* Returns a new key of the same type with the specified annotation.
137
* @param annotation Annotation instance to use
138
* @return Key with specified annotation
139
* @since 5.0
140
*/
141
public Key<T> withAnnotation(Annotation annotation);
142
143
/**
144
* Returns true if this key has binding annotation attributes.
145
* @return true if annotated
146
*/
147
public boolean hasAttributes();
148
149
/**
150
* Returns a key without annotation attributes.
151
* @return Key without attributes
152
*/
153
public Key<T> withoutAttributes();
154
}
155
```
156
157
**Usage Examples:**
158
159
```java
160
import com.google.inject.*;
161
import com.google.inject.name.*;
162
163
// Simple type keys
164
Key<String> stringKey = Key.get(String.class);
165
Key<DatabaseService> dbKey = Key.get(DatabaseService.class);
166
167
// Generic type keys
168
Key<List<String>> listKey = Key.get(new TypeLiteral<List<String>>() {});
169
Key<Map<String, Object>> mapKey = Key.get(new TypeLiteral<Map<String, Object>>() {});
170
171
// Keys with annotations
172
Key<String> namedKey = Key.get(String.class, Names.named("database.url"));
173
Key<Cache> primaryCache = Key.get(Cache.class, Names.named("primary"));
174
175
// Custom annotation keys
176
Key<Logger> loggerKey = Key.get(Logger.class, LoggerFor.class);
177
178
// Using keys with injector
179
DatabaseService db = injector.getInstance(Key.get(DatabaseService.class));
180
String dbUrl = injector.getInstance(Key.get(String.class, Names.named("database.url")));
181
List<String> items = injector.getInstance(Key.get(new TypeLiteral<List<String>>() {}));
182
```
183
184
### TypeLiteral Class
185
186
Represents generic types at runtime, overcoming Java's type erasure limitations.
187
188
```java { .api }
189
/**
190
* Represents a generic type T. Java doesn't yet provide a way to represent
191
* generic types, so this class does. Forces clients to create a subclass
192
* which enables retrieval of the type information even at runtime.
193
* @param <T> Generic type
194
*/
195
public class TypeLiteral<T> {
196
/**
197
* Creates a type literal for the given class.
198
* @param type Class type
199
* @return TypeLiteral for the class
200
*/
201
public static <T> TypeLiteral<T> get(Class<T> type);
202
203
/**
204
* Creates a type literal for the given type.
205
* @param type Type instance
206
* @return TypeLiteral for the type
207
*/
208
public static TypeLiteral<?> get(Type type);
209
210
/**
211
* Returns the raw (non-generic) type for this type.
212
* @return Raw type
213
*/
214
public Class<? super T> getRawType();
215
216
/**
217
* Returns the underlying Type instance.
218
* @return Type instance
219
*/
220
public Type getType();
221
222
/**
223
* Returns the generic form of supertype. For example, if this is
224
* ArrayList<String>, this returns Iterable<String> given the input Iterable.class.
225
* @param supertype a superclass of, or interface implemented by, this
226
* @return TypeLiteral for the supertype
227
* @since 2.0
228
*/
229
public TypeLiteral<?> getSupertype(Class<?> supertype);
230
231
/**
232
* Returns the resolved generic type of field.
233
* @param field a field defined by this or any superclass
234
* @return TypeLiteral for the field type
235
* @since 2.0
236
*/
237
public TypeLiteral<?> getFieldType(Field field);
238
239
/**
240
* Returns the resolved generic parameter types of methodOrConstructor.
241
* @param methodOrConstructor a method or constructor defined by this or any supertype
242
* @return List of TypeLiterals for parameter types
243
* @since 2.0
244
*/
245
public List<TypeLiteral<?>> getParameterTypes(Member methodOrConstructor);
246
247
/**
248
* Returns the resolved generic exception types thrown by methodOrConstructor.
249
* @param methodOrConstructor a method or constructor defined by this or any supertype
250
* @return List of TypeLiterals for exception types
251
* @since 2.0
252
*/
253
public List<TypeLiteral<?>> getExceptionTypes(Member methodOrConstructor);
254
255
/**
256
* Returns the resolved generic return type of method.
257
* @param method a method defined by this or any supertype
258
* @return TypeLiteral for the return type
259
* @since 2.0
260
*/
261
public TypeLiteral<?> getReturnType(Method method);
262
}
263
```
264
265
**Usage Examples:**
266
267
```java
268
import com.google.inject.*;
269
import java.util.*;
270
271
// Create type literals for generic types
272
TypeLiteral<List<String>> stringListType = new TypeLiteral<List<String>>() {};
273
TypeLiteral<Map<String, Integer>> mapType = new TypeLiteral<Map<String, Integer>>() {};
274
TypeLiteral<Set<User>> userSetType = new TypeLiteral<Set<User>>() {};
275
276
// Use with binding
277
public class CollectionModule extends AbstractModule {
278
@Override
279
protected void configure() {
280
bind(new TypeLiteral<List<String>>() {})
281
.toInstance(Arrays.asList("item1", "item2", "item3"));
282
283
bind(new TypeLiteral<Map<String, Integer>>() {})
284
.toProvider(ConfigMapProvider.class);
285
}
286
}
287
288
// Get instances using type literals
289
List<String> strings = injector.getInstance(Key.get(new TypeLiteral<List<String>>() {}));
290
Map<String, Integer> config = injector.getInstance(Key.get(new TypeLiteral<Map<String, Integer>>() {}));
291
292
// Provider methods with type literals
293
@Provides
294
List<DatabaseConnection> provideConnections() {
295
return Arrays.asList(
296
createConnection("primary"),
297
createConnection("secondary")
298
);
299
}
300
```
301
302
## Common Type Patterns
303
304
### Working with Collections
305
306
```java
307
// Binding collections
308
public class CollectionModule extends AbstractModule {
309
@Override
310
protected void configure() {
311
// Bind specific collection types
312
bind(new TypeLiteral<List<String>>() {})
313
.annotatedWith(Names.named("urls"))
314
.toInstance(Arrays.asList("http://api1.com", "http://api2.com"));
315
316
bind(new TypeLiteral<Map<String, DatabaseConfig>>() {})
317
.toProvider(DatabaseConfigProvider.class)
318
.in(Singleton.class);
319
}
320
}
321
322
// Injecting collections
323
public class ApiClient {
324
private final List<String> apiUrls;
325
private final Map<String, DatabaseConfig> dbConfigs;
326
327
@Inject
328
public ApiClient(
329
@Named("urls") List<String> apiUrls,
330
Map<String, DatabaseConfig> dbConfigs
331
) {
332
this.apiUrls = apiUrls;
333
this.dbConfigs = dbConfigs;
334
}
335
}
336
```
337
338
### Working with Wildcards
339
340
```java
341
// Wildcard type literals
342
TypeLiteral<List<? extends Animal>> animalList = new TypeLiteral<List<? extends Animal>>() {};
343
TypeLiteral<Map<String, ? super Number>> numberMap = new TypeLiteral<Map<String, ? super Number>>() {};
344
345
// Bounded type parameters
346
public class GenericService<T extends Serializable> {
347
// Implementation
348
}
349
350
// Binding generic services
351
bind(new TypeLiteral<GenericService<User>>() {})
352
.to(new TypeLiteral<UserGenericService>() {});
353
```
354
355
### Converting Between Keys and TypeLiterals
356
357
```java
358
// From TypeLiteral to Key
359
TypeLiteral<List<String>> typeLiteral = new TypeLiteral<List<String>>() {};
360
Key<List<String>> key = Key.get(typeLiteral);
361
362
// From Key to TypeLiteral
363
Key<Map<String, Object>> mapKey = Key.get(new TypeLiteral<Map<String, Object>>() {});
364
TypeLiteral<Map<String, Object>> extracted = mapKey.getTypeLiteral();
365
366
// Working with generic type information
367
Type type = typeLiteral.getType();
368
Class<?> rawType = typeLiteral.getRawType(); // Returns List.class
369
370
// Type equality
371
TypeLiteral<List<String>> type1 = new TypeLiteral<List<String>>() {};
372
TypeLiteral<List<String>> type2 = new TypeLiteral<List<String>>() {};
373
boolean equal = type1.equals(type2); // true
374
```