JavaPoet is a Java API for generating .java source files programmatically with support for modern Java features including records and sealed types
TypeVariableName represents type variables (generic type parameters) such as T, E, K, V in generic declarations. It extends TypeName and provides support for type bounds and is used in class, interface, and method generic declarations.
Factory methods for creating type variable instances.
/**
* Creates a type variable with just a name
* @param name - The type variable name (e.g., "T", "E")
* @return TypeVariableName without bounds
*/
static TypeVariableName get(String name);
/**
* Creates a type variable with bounds using TypeName
* @param name - The type variable name
* @param bounds - Upper bounds for the type variable
* @return TypeVariableName with specified bounds
*/
static TypeVariableName get(String name, TypeName... bounds);
/**
* Creates a type variable with bounds using reflection types
* @param name - The type variable name
* @param bounds - Upper bounds as reflection types
* @return TypeVariableName with specified bounds
*/
static TypeVariableName get(String name, Type... bounds);
/**
* Creates a TypeVariableName from a TypeVariable mirror
* @param mirror - The type variable from annotation processing
* @return TypeVariableName from the mirror
*/
static TypeVariableName get(javax.lang.model.type.TypeVariable mirror);
/**
* Creates a TypeVariableName from a TypeParameterElement
* @param element - The type parameter element from annotation processing
* @return TypeVariableName from the element
*/
static TypeVariableName get(TypeParameterElement element);
/**
* Creates a TypeVariableName from a reflection TypeVariable
* @param type - The reflection type variable
* @return TypeVariableName from the reflection type
*/
static TypeVariableName get(java.lang.reflect.TypeVariable<?> type);Usage Examples:
// Simple unbounded type variable
TypeVariableName t = TypeVariableName.get("T");
TypeVariableName e = TypeVariableName.get("E");
TypeVariableName k = TypeVariableName.get("K");
TypeVariableName v = TypeVariableName.get("V");
// Type variable with single bound
TypeVariableName bounded = TypeVariableName.get("T", ClassName.get(Comparable.class));
// Type variable with multiple bounds
TypeVariableName multiBounded = TypeVariableName.get("T",
ClassName.get(Serializable.class),
ClassName.get(Comparable.class)
);
// Using reflection types
TypeVariableName numberBound = TypeVariableName.get("T", Number.class);
// From annotation processing
TypeParameterElement element = ...;
TypeVariableName fromElement = TypeVariableName.get(element);Get information about the type variable.
/**
* Returns the type variable name
* @return The name (e.g., "T", "E")
*/
String name();
/**
* Returns the upper bounds of this type variable
* @return List of TypeName bounds (empty if unbounded)
*/
List<TypeName> bounds();Usage Examples:
TypeVariableName t = TypeVariableName.get("T", Comparable.class);
String name = t.name(); // "T"
List<TypeName> bounds = t.bounds(); // [Comparable]Create a copy with different bounds.
/**
* Returns a copy with different bounds using reflection types
* @param bounds - New upper bounds
* @return New TypeVariableName with specified bounds
*/
TypeVariableName withBounds(Type... bounds);
/**
* Returns a copy with different bounds using TypeName
* @param bounds - New upper bounds
* @return New TypeVariableName with specified bounds
*/
TypeVariableName withBounds(TypeName... bounds);
/**
* Returns a copy with bounds from a list
* @param bounds - List of new upper bounds
* @return New TypeVariableName with specified bounds
*/
TypeVariableName withBounds(List<? extends TypeName> bounds);Usage Examples:
TypeVariableName t = TypeVariableName.get("T");
// Add bounds
TypeVariableName bounded = t.withBounds(Comparable.class);
// Multiple bounds
TypeVariableName multiBounded = t.withBounds(
ClassName.get(Serializable.class),
ClassName.get(Cloneable.class)
);
// Change bounds
TypeVariableName newBounds = bounded.withBounds(Number.class);Add or remove type annotations.
/**
* Returns a copy with additional annotations
* @param annotations - Annotations to add
* @return New TypeVariableName with annotations
*/
TypeVariableName annotated(AnnotationSpec... annotations);
/**
* Returns a copy with additional annotations from a list
* @param annotations - List of annotations to add
* @return New TypeVariableName with annotations
*/
TypeVariableName annotated(List<AnnotationSpec> annotations);
/**
* Returns a copy without any annotations
* @return New TypeVariableName without annotations
*/
TypeVariableName withoutAnnotations();// class Container<T> { }
TypeVariableName t = TypeVariableName.get("T");
TypeSpec container = TypeSpec.classBuilder("Container")
.addTypeVariable(t)
.addField(t, "value", Modifier.PRIVATE)
.addMethod(MethodSpec.methodBuilder("get")
.returns(t)
.addStatement("return value")
.build())
.build();
// class Pair<K, V> { }
TypeVariableName k = TypeVariableName.get("K");
TypeVariableName v = TypeVariableName.get("V");
TypeSpec pair = TypeSpec.classBuilder("Pair")
.addTypeVariable(k)
.addTypeVariable(v)
.addField(k, "key", Modifier.PRIVATE, Modifier.FINAL)
.addField(v, "value", Modifier.PRIVATE, Modifier.FINAL)
.build();// interface Repository<T> { }
TypeVariableName t = TypeVariableName.get("T");
TypeSpec repository = TypeSpec.interfaceBuilder("Repository")
.addModifiers(Modifier.PUBLIC)
.addTypeVariable(t)
.addMethod(MethodSpec.methodBuilder("save")
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.addParameter(t, "entity")
.build())
.addMethod(MethodSpec.methodBuilder("findById")
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.returns(t)
.addParameter(String.class, "id")
.build())
.build();// class NumberContainer<T extends Number> { }
TypeVariableName tExtendsNumber = TypeVariableName.get("T", Number.class);
TypeSpec numberContainer = TypeSpec.classBuilder("NumberContainer")
.addTypeVariable(tExtendsNumber)
.addField(tExtendsNumber, "value", Modifier.PRIVATE)
.build();
// class ComparableList<T extends Comparable<T>> { }
TypeVariableName t = TypeVariableName.get("T");
ParameterizedTypeName comparableT = ParameterizedTypeName.get(
ClassName.get(Comparable.class),
t
);
TypeVariableName tExtendsComparable = TypeVariableName.get("T", comparableT);
TypeSpec comparableList = TypeSpec.classBuilder("ComparableList")
.addTypeVariable(tExtendsComparable)
.build();// class Handler<T extends Serializable & Comparable<T>> { }
TypeVariableName t = TypeVariableName.get("T");
ParameterizedTypeName comparableT = ParameterizedTypeName.get(
ClassName.get(Comparable.class),
t
);
TypeVariableName bounded = TypeVariableName.get("T",
ClassName.get(Serializable.class),
comparableT
);
TypeSpec handler = TypeSpec.classBuilder("Handler")
.addTypeVariable(bounded)
.build();// public <T> T identity(T value) { }
TypeVariableName t = TypeVariableName.get("T");
MethodSpec identity = MethodSpec.methodBuilder("identity")
.addModifiers(Modifier.PUBLIC)
.addTypeVariable(t)
.returns(t)
.addParameter(t, "value")
.addStatement("return value")
.build();
// public <T extends Comparable<T>> T max(T a, T b) { }
TypeVariableName tComparable = TypeVariableName.get("T",
ParameterizedTypeName.get(ClassName.get(Comparable.class), t)
);
MethodSpec max = MethodSpec.methodBuilder("max")
.addModifiers(Modifier.PUBLIC)
.addTypeVariable(tComparable)
.returns(tComparable)
.addParameter(tComparable, "a")
.addParameter(tComparable, "b")
.addStatement("return a.compareTo(b) > 0 ? a : b")
.build();// public <K, V> Map<K, V> createMap() { }
TypeVariableName k = TypeVariableName.get("K");
TypeVariableName v = TypeVariableName.get("V");
ParameterizedTypeName mapKV = ParameterizedTypeName.get(
ClassName.get(Map.class),
k,
v
);
MethodSpec createMap = MethodSpec.methodBuilder("createMap")
.addModifiers(Modifier.PUBLIC)
.addTypeVariable(k)
.addTypeVariable(v)
.returns(mapKV)
.addStatement("return new $T<>()", HashMap.class)
.build();TypeVariableName t = TypeVariableName.get("T");
TypeSpec container = TypeSpec.classBuilder("Container")
.addTypeVariable(t)
.addField(FieldSpec.builder(t, "value")
.addModifiers(Modifier.PRIVATE)
.build())
.build();TypeVariableName t = TypeVariableName.get("T");
MethodSpec process = MethodSpec.methodBuilder("process")
.addTypeVariable(t)
.addParameter(ParameterSpec.builder(t, "input").build())
.returns(t)
.build();// interface Converter<F, T> {
// T convert(F from);
// }
TypeVariableName f = TypeVariableName.get("F");
TypeVariableName t = TypeVariableName.get("T");
TypeSpec converter = TypeSpec.interfaceBuilder("Converter")
.addModifiers(Modifier.PUBLIC)
.addTypeVariable(f)
.addTypeVariable(t)
.addMethod(MethodSpec.methodBuilder("convert")
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.addParameter(f, "from")
.returns(t)
.build())
.build();// class Builder<T extends Builder<T>> {
// public T withName(String name) { }
// }
TypeVariableName t = TypeVariableName.get("T");
TypeVariableName tExtendsBuilder = TypeVariableName.get("T",
ParameterizedTypeName.get(ClassName.get("com.example", "Builder"), t)
);
TypeSpec builder = TypeSpec.classBuilder("Builder")
.addTypeVariable(tExtendsBuilder)
.addMethod(MethodSpec.methodBuilder("withName")
.addModifiers(Modifier.PUBLIC)
.addParameter(String.class, "name")
.returns(tExtendsBuilder)
.addStatement("this.name = name")
.addStatement("return ($T) this", tExtendsBuilder)
.build())
.build();// public <T> T[] toArray(T[] a) { }
TypeVariableName t = TypeVariableName.get("T");
ArrayTypeName arrayOfT = ArrayTypeName.of(t);
MethodSpec toArray = MethodSpec.methodBuilder("toArray")
.addModifiers(Modifier.PUBLIC)
.addTypeVariable(t)
.addParameter(arrayOfT, "a")
.returns(arrayOfT)
.addStatement("return a")
.build();// class MyList<E> implements List<E> { }
TypeVariableName e = TypeVariableName.get("E");
TypeSpec myList = TypeSpec.classBuilder("MyList")
.addTypeVariable(e)
.addSuperinterface(ParameterizedTypeName.get(
ClassName.get(List.class),
e
))
.build();class TypeVariableName extends TypeName {
static TypeVariableName get(String name);
static TypeVariableName get(String name, TypeName... bounds);
static TypeVariableName get(String name, Type... bounds);
static TypeVariableName get(javax.lang.model.type.TypeVariable mirror);
static TypeVariableName get(TypeParameterElement element);
static TypeVariableName get(java.lang.reflect.TypeVariable<?> type);
String name();
List<TypeName> bounds();
TypeVariableName withBounds(Type... bounds);
TypeVariableName withBounds(TypeName... bounds);
TypeVariableName withBounds(List<? extends TypeName> bounds);
TypeVariableName annotated(AnnotationSpec... annotations);
TypeVariableName annotated(List<AnnotationSpec> annotations);
TypeVariableName withoutAnnotations();
}Install with Tessl CLI
npx tessl i tessl/maven-com-palantir-javapoet--javapoetdocs