CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-palantir-javapoet--javapoet

JavaPoet is a Java API for generating .java source files programmatically with support for modern Java features including records and sealed types

Overview
Eval results
Files

type-variable-names.mddocs/

Type Variable Names

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.

Capabilities

Creating Type Variables

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);

Accessing Type Variable Properties

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]

Modifying Bounds

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);

Working with Annotations

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();

Common Patterns

Generic Class Declaration

// 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();

Generic Interface Declaration

// 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();

Bounded Type Variables

// 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();

Multiple Bounds

// 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();

Generic Methods

// 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();

Generic Method with Multiple Type Parameters

// 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();

Type Variable in Field

TypeVariableName t = TypeVariableName.get("T");

TypeSpec container = TypeSpec.classBuilder("Container")
    .addTypeVariable(t)
    .addField(FieldSpec.builder(t, "value")
        .addModifiers(Modifier.PRIVATE)
        .build())
    .build();

Type Variable in Parameters

TypeVariableName t = TypeVariableName.get("T");

MethodSpec process = MethodSpec.methodBuilder("process")
    .addTypeVariable(t)
    .addParameter(ParameterSpec.builder(t, "input").build())
    .returns(t)
    .build();

Converter Pattern

// 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();

Builder Pattern with Generics

// 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();

Generic Array Component

// 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();

Collection-like Classes

// 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();

Types

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--javapoet

docs

annotation-specifications.md

array-type-names.md

class-names.md

code-blocks.md

field-specifications.md

index.md

java-files.md

method-specifications.md

name-allocator.md

parameter-specifications.md

parameterized-type-names.md

type-names.md

type-specifications.md

type-variable-names.md

wildcard-type-names.md

tile.json