0
# Advanced Type System
1
2
Advanced type representations for complex generic scenarios including parameterized types, arrays, type variables, and wildcards. These types enable full support for Java's generic type system.
3
4
## Capabilities
5
6
### ParameterizedTypeName
7
8
Represents parameterized types like `List<String>`, `Map<String, Integer>`, or `Optional<? extends Number>`. Handles generic type arguments and nested parameterization.
9
10
```java { .api }
11
/**
12
* Represents parameterized types like List<String>, Map<K,V>
13
*/
14
public final class ParameterizedTypeName extends TypeName {
15
// Public fields
16
public final ClassName rawType;
17
public final List<TypeName> typeArguments;
18
19
// Static factory methods
20
public static ParameterizedTypeName get(ClassName rawType, TypeName... typeArguments);
21
public static ParameterizedTypeName get(Class<?> rawType, Type... typeArguments);
22
public static ParameterizedTypeName get(ParameterizedType type);
23
24
// Instance methods
25
public ParameterizedTypeName annotated(List<AnnotationSpec> annotations);
26
public TypeName withoutAnnotations();
27
public ParameterizedTypeName nestedClass(String name);
28
public ParameterizedTypeName nestedClass(String name, List<TypeName> typeArguments);
29
}
30
```
31
32
**Usage Examples:**
33
34
```java
35
// Simple parameterized types
36
ParameterizedTypeName listString = ParameterizedTypeName.get(List.class, String.class);
37
ParameterizedTypeName setInteger = ParameterizedTypeName.get(Set.class, Integer.class);
38
39
// Map with key-value types
40
ParameterizedTypeName mapStringInt = ParameterizedTypeName.get(
41
ClassName.get(Map.class),
42
ClassName.get(String.class),
43
ClassName.get(Integer.class)
44
);
45
46
// Nested parameterization
47
ParameterizedTypeName listOfMaps = ParameterizedTypeName.get(
48
List.class,
49
ParameterizedTypeName.get(Map.class, String.class, Object.class)
50
); // List<Map<String, Object>>
51
52
// Complex generic types
53
ParameterizedTypeName functionType = ParameterizedTypeName.get(
54
Function.class,
55
String.class,
56
ParameterizedTypeName.get(Optional.class, Integer.class)
57
); // Function<String, Optional<Integer>>
58
59
// Using with wildcards
60
ParameterizedTypeName wildcardList = ParameterizedTypeName.get(
61
List.class,
62
WildcardTypeName.subtypeOf(Number.class)
63
); // List<? extends Number>
64
65
// From reflection
66
ParameterizedType reflectionType = ...; // obtained from reflection
67
ParameterizedTypeName fromReflection = ParameterizedTypeName.get(reflectionType);
68
```
69
70
### ArrayTypeName
71
72
Represents array types like `String[]`, `int[][]`, or `List<String>[]`. Supports multi-dimensional arrays and arrays of complex types.
73
74
```java { .api }
75
/**
76
* Represents array types like String[], int[][], List<String>[]
77
*/
78
public final class ArrayTypeName extends TypeName {
79
// Public fields
80
public final TypeName componentType;
81
82
// Static factory methods
83
public static ArrayTypeName of(TypeName componentType);
84
public static ArrayTypeName of(Type componentType);
85
public static ArrayTypeName get(ArrayType mirror);
86
public static ArrayTypeName get(GenericArrayType type);
87
88
// Instance methods
89
public ArrayTypeName annotated(List<AnnotationSpec> annotations);
90
public TypeName withoutAnnotations();
91
}
92
```
93
94
**Usage Examples:**
95
96
```java
97
// Primitive arrays
98
ArrayTypeName intArray = ArrayTypeName.of(TypeName.INT); // int[]
99
ArrayTypeName byteArray = ArrayTypeName.of(TypeName.BYTE); // byte[]
100
101
// Object arrays
102
ArrayTypeName stringArray = ArrayTypeName.of(String.class); // String[]
103
ArrayTypeName objectArray = ArrayTypeName.of(Object.class); // Object[]
104
105
// Multi-dimensional arrays
106
ArrayTypeName intMatrix = ArrayTypeName.of(
107
ArrayTypeName.of(TypeName.INT)
108
); // int[][]
109
110
ArrayTypeName stringMatrix = ArrayTypeName.of(
111
ArrayTypeName.of(String.class)
112
); // String[][]
113
114
// Arrays of parameterized types
115
ArrayTypeName listArray = ArrayTypeName.of(
116
ParameterizedTypeName.get(List.class, String.class)
117
); // List<String>[]
118
119
// Arrays of custom types
120
ClassName customType = ClassName.get("com.example", "CustomClass");
121
ArrayTypeName customArray = ArrayTypeName.of(customType); // CustomClass[]
122
123
// Using in method signatures
124
MethodSpec method = MethodSpec.methodBuilder("processArrays")
125
.addParameter(ArrayTypeName.of(String.class), "names")
126
.addParameter(ArrayTypeName.of(ArrayTypeName.of(TypeName.INT)), "matrix")
127
.returns(ArrayTypeName.of(Object.class))
128
.addStatement("// Process arrays")
129
.build();
130
131
// From reflection
132
Method reflectionMethod = SomeClass.class.getMethod("arrayMethod", String[].class);
133
Type arrayType = reflectionMethod.getGenericParameterTypes()[0];
134
ArrayTypeName fromReflection = (ArrayTypeName) TypeName.get(arrayType);
135
```
136
137
### TypeVariableName
138
139
Represents type variables like `T`, `E`, `K`, `V` used in generic class and method declarations. Supports bounded type variables.
140
141
```java { .api }
142
/**
143
* Represents type variables like T, E, K, V in generic declarations
144
*/
145
public final class TypeVariableName extends TypeName {
146
// Public fields
147
public final String name;
148
public final List<TypeName> bounds;
149
150
// Static factory methods
151
public static TypeVariableName get(String name);
152
public static TypeVariableName get(String name, TypeName... bounds);
153
public static TypeVariableName get(String name, Type... bounds);
154
public static TypeVariableName get(TypeVariable mirror);
155
public static TypeVariableName get(TypeParameterElement element);
156
public static TypeVariableName get(java.lang.reflect.TypeVariable<?> type);
157
158
// Instance methods
159
public TypeVariableName annotated(List<AnnotationSpec> annotations);
160
public TypeName withoutAnnotations();
161
public TypeVariableName withBounds(Type... bounds);
162
public TypeVariableName withBounds(TypeName... bounds);
163
public TypeVariableName withBounds(List<? extends TypeName> bounds);
164
}
165
```
166
167
**Usage Examples:**
168
169
```java
170
// Simple unbounded type variables
171
TypeVariableName T = TypeVariableName.get("T");
172
TypeVariableName E = TypeVariableName.get("E");
173
TypeVariableName K = TypeVariableName.get("K");
174
TypeVariableName V = TypeVariableName.get("V");
175
176
// Bounded type variables
177
TypeVariableName numberT = TypeVariableName.get("T", Number.class);
178
TypeVariableName comparableT = TypeVariableName.get("T", Comparable.class);
179
180
// Multiple bounds
181
TypeVariableName multibound = TypeVariableName.get("T",
182
ClassName.get(Serializable.class),
183
ClassName.get(Comparable.class)
184
); // T extends Serializable & Comparable
185
186
// Complex bounds with parameterized types
187
TypeVariableName complexBound = TypeVariableName.get("T",
188
ParameterizedTypeName.get(Comparable.class, TypeVariableName.get("T"))
189
); // T extends Comparable<T>
190
191
// Using in generic class
192
TypeSpec genericClass = TypeSpec.classBuilder("Container")
193
.addTypeVariable(TypeVariableName.get("T"))
194
.addField(TypeVariableName.get("T"), "value", Modifier.PRIVATE)
195
.addMethod(MethodSpec.methodBuilder("getValue")
196
.addModifiers(Modifier.PUBLIC)
197
.returns(TypeVariableName.get("T"))
198
.addStatement("return value")
199
.build())
200
.addMethod(MethodSpec.methodBuilder("setValue")
201
.addModifiers(Modifier.PUBLIC)
202
.addParameter(TypeVariableName.get("T"), "value")
203
.addStatement("this.value = value")
204
.build())
205
.build();
206
207
// Using in generic method
208
MethodSpec genericMethod = MethodSpec.methodBuilder("swap")
209
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
210
.addTypeVariable(TypeVariableName.get("T"))
211
.addParameter(ArrayTypeName.of(TypeVariableName.get("T")), "array")
212
.addParameter(TypeName.INT, "i")
213
.addParameter(TypeName.INT, "j")
214
.addStatement("T temp = array[i]")
215
.addStatement("array[i] = array[j]")
216
.addStatement("array[j] = temp")
217
.build();
218
219
// Bounded generic method
220
MethodSpec boundedMethod = MethodSpec.methodBuilder("max")
221
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
222
.addTypeVariable(TypeVariableName.get("T",
223
ParameterizedTypeName.get(Comparable.class, TypeVariableName.get("T"))))
224
.addParameter(TypeVariableName.get("T"), "a")
225
.addParameter(TypeVariableName.get("T"), "b")
226
.returns(TypeVariableName.get("T"))
227
.addStatement("return a.compareTo(b) > 0 ? a : b")
228
.build();
229
```
230
231
### WildcardTypeName
232
233
Represents wildcard types like `? extends String`, `? super Integer`, or unbounded `?`. Essential for flexible generic APIs.
234
235
```java { .api }
236
/**
237
* Represents wildcard types like ? extends String, ? super Integer
238
*/
239
public final class WildcardTypeName extends TypeName {
240
// Public fields
241
public final List<TypeName> upperBounds;
242
public final List<TypeName> lowerBounds;
243
244
// Static factory methods
245
public static WildcardTypeName subtypeOf(TypeName upperBound);
246
public static WildcardTypeName subtypeOf(Type upperBound);
247
public static WildcardTypeName supertypeOf(TypeName lowerBound);
248
public static WildcardTypeName supertypeOf(Type lowerBound);
249
public static TypeName get(javax.lang.model.type.WildcardType mirror);
250
public static TypeName get(WildcardType wildcardName);
251
252
// Instance methods
253
public WildcardTypeName annotated(List<AnnotationSpec> annotations);
254
public TypeName withoutAnnotations();
255
}
256
```
257
258
**Usage Examples:**
259
260
```java
261
// Upper bounded wildcards (? extends Type)
262
WildcardTypeName extendsNumber = WildcardTypeName.subtypeOf(Number.class);
263
WildcardTypeName extendsString = WildcardTypeName.subtypeOf(String.class);
264
265
// Lower bounded wildcards (? super Type)
266
WildcardTypeName superInteger = WildcardTypeName.supertypeOf(Integer.class);
267
WildcardTypeName superString = WildcardTypeName.supertypeOf(String.class);
268
269
// Using with parameterized types
270
ParameterizedTypeName listExtendsNumber = ParameterizedTypeName.get(
271
List.class,
272
WildcardTypeName.subtypeOf(Number.class)
273
); // List<? extends Number>
274
275
ParameterizedTypeName listSuperInteger = ParameterizedTypeName.get(
276
List.class,
277
WildcardTypeName.supertypeOf(Integer.class)
278
); // List<? super Integer>
279
280
// Consumer/Producer patterns (PECS - Producer Extends, Consumer Super)
281
MethodSpec copyMethod = MethodSpec.methodBuilder("copy")
282
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
283
.addTypeVariable(TypeVariableName.get("T"))
284
.addParameter(ParameterizedTypeName.get(List.class,
285
WildcardTypeName.subtypeOf(TypeVariableName.get("T"))), "src") // Producer
286
.addParameter(ParameterizedTypeName.get(List.class,
287
WildcardTypeName.supertypeOf(TypeVariableName.get("T"))), "dest") // Consumer
288
.addStatement("for (T item : src) dest.add(item)")
289
.build();
290
291
// Complex wildcard scenarios
292
ParameterizedTypeName complexWildcard = ParameterizedTypeName.get(
293
Map.class,
294
WildcardTypeName.subtypeOf(String.class),
295
WildcardTypeName.supertypeOf(
296
ParameterizedTypeName.get(List.class, Integer.class)
297
)
298
); // Map<? extends String, ? super List<Integer>>
299
300
// Unbounded wildcard (? - rarely used directly)
301
// Usually represented as WildcardTypeName.subtypeOf(Object.class)
302
WildcardTypeName unbounded = WildcardTypeName.subtypeOf(Object.class);
303
304
// Method accepting flexible collections
305
MethodSpec printAll = MethodSpec.methodBuilder("printAll")
306
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
307
.addParameter(ParameterizedTypeName.get(Collection.class,
308
WildcardTypeName.subtypeOf(Object.class)), "items")
309
.addStatement("for (Object item : items) $T.out.println(item)", System.class)
310
.build();
311
```
312
313
### Type Composition and Complex Scenarios
314
315
Combining multiple advanced types for complex generic scenarios:
316
317
```java
318
// Repository pattern with complex generics
319
TypeVariableName entityT = TypeVariableName.get("T");
320
TypeVariableName idT = TypeVariableName.get("ID", Serializable.class);
321
322
TypeSpec repository = TypeSpec.interfaceBuilder("Repository")
323
.addModifiers(Modifier.PUBLIC)
324
.addTypeVariable(entityT)
325
.addTypeVariable(idT)
326
.addMethod(MethodSpec.methodBuilder("findById")
327
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
328
.addParameter(idT, "id")
329
.returns(ParameterizedTypeName.get(Optional.class, entityT))
330
.build())
331
.addMethod(MethodSpec.methodBuilder("findAll")
332
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
333
.returns(ParameterizedTypeName.get(List.class, entityT))
334
.build())
335
.addMethod(MethodSpec.methodBuilder("save")
336
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
337
.addParameter(entityT, "entity")
338
.returns(entityT)
339
.build())
340
.build();
341
342
// Event handler with complex type relationships
343
TypeVariableName eventT = TypeVariableName.get("E",
344
ClassName.get("com.example", "Event"));
345
346
MethodSpec handleEvents = MethodSpec.methodBuilder("handleEvents")
347
.addModifiers(Modifier.PUBLIC)
348
.addTypeVariable(eventT)
349
.addParameter(ParameterizedTypeName.get(List.class,
350
WildcardTypeName.subtypeOf(eventT)), "events")
351
.addParameter(ParameterizedTypeName.get(Consumer.class,
352
WildcardTypeName.supertypeOf(eventT)), "handler")
353
.addStatement("events.forEach(handler)")
354
.build();
355
356
// Generic builder pattern
357
TypeVariableName builderT = TypeVariableName.get("T");
358
TypeVariableName builderB = TypeVariableName.get("B",
359
ParameterizedTypeName.get(ClassName.get("Builder"), builderT));
360
361
TypeSpec builder = TypeSpec.classBuilder("Builder")
362
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
363
.addTypeVariable(builderT)
364
.addTypeVariable(builderB)
365
.addMethod(MethodSpec.methodBuilder("build")
366
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
367
.returns(builderT)
368
.build())
369
.build();
370
```
371
372
### Working with Annotations on Advanced Types
373
374
Advanced types support type annotations:
375
376
```java
377
// Annotated type parameters
378
TypeVariableName annotatedT = TypeVariableName.get("T")
379
.annotated(AnnotationSpec.builder(NonNull.class).build());
380
381
// Annotated parameterized types
382
ParameterizedTypeName annotatedList = ParameterizedTypeName.get(List.class, String.class)
383
.annotated(AnnotationSpec.builder(Immutable.class).build());
384
385
// Annotated wildcards
386
WildcardTypeName annotatedWildcard = WildcardTypeName.subtypeOf(String.class)
387
.annotated(AnnotationSpec.builder(NonNull.class).build());
388
389
// Using annotated types in method signatures
390
MethodSpec annotatedMethod = MethodSpec.methodBuilder("processData")
391
.addParameter(annotatedList, "data")
392
.addParameter(ParameterizedTypeName.get(Optional.class, annotatedT), "context")
393
.returns(ArrayTypeName.of(annotatedT).annotated(
394
AnnotationSpec.builder(NonNull.class).build()))
395
.build();
396
```