JavaPoet is a Java API for generating .java source files programmatically with support for modern Java features including records and sealed types
NameAllocator manages unique Java identifiers and helps avoid name collisions when generating code. It automatically suggests unique names by appending numeric suffixes when names conflict, and can convert arbitrary strings into valid Java identifiers.
/**
* Creates a new NameAllocator instance
*/
public NameAllocator();Usage Example:
NameAllocator allocator = new NameAllocator();Convert arbitrary strings to valid Java identifiers.
/**
* Converts a string to a valid Java identifier
* @param suggestion - The string to convert
* @return Valid Java identifier derived from the suggestion
*/
static String toJavaIdentifier(String suggestion);Usage Examples:
// Convert strings with special characters
String id1 = NameAllocator.toJavaIdentifier("my-variable"); // "my_variable"
String id2 = NameAllocator.toJavaIdentifier("user name"); // "user_name"
String id3 = NameAllocator.toJavaIdentifier("123abc"); // "_123abc"
String id4 = NameAllocator.toJavaIdentifier("class"); // "class_" (reserved word)Allocate unique names that won't collide with each other.
/**
* Allocates a new unique name based on a suggestion
* @param suggestion - Suggested name
* @return Unique name (may have numeric suffix if suggestion conflicts)
*/
String newName(String suggestion);
/**
* Allocates a new unique name with an associated tag
* @param suggestion - Suggested name
* @param tag - Object to associate with this name for later retrieval
* @return Unique name (may have numeric suffix if suggestion conflicts)
*/
String newName(String suggestion, Object tag);Usage Examples:
NameAllocator allocator = new NameAllocator();
// Simple allocation
String var1 = allocator.newName("value"); // "value"
String var2 = allocator.newName("value"); // "value_" (conflict avoided)
String var3 = allocator.newName("value"); // "value__" (conflict avoided)
// Using tags
String userId = allocator.newName("id", "userId"); // "id"
String productId = allocator.newName("id", "productId"); // "id_"
// Can retrieve by tag later
String retrievedUserId = allocator.get("userId"); // "id"
String retrievedProductId = allocator.get("productId"); // "id_"Retrieve previously allocated names by their tag.
/**
* Retrieves a previously allocated name by its tag
* @param tag - The tag associated with the name
* @return The allocated name for this tag
* @throws IllegalArgumentException if tag not found
*/
String get(Object tag);Usage Example:
NameAllocator allocator = new NameAllocator();
allocator.newName("user", "currentUser");
allocator.newName("user", "activeUser");
String current = allocator.get("currentUser"); // "user"
String active = allocator.get("activeUser"); // "user_"Create a copy of the allocator with its current state.
/**
* Creates a clone of this NameAllocator
* @return Cloned NameAllocator with same allocated names
*/
NameAllocator clone();Usage Example:
NameAllocator original = new NameAllocator();
original.newName("value");
original.newName("count");
NameAllocator copy = original.clone();
String name = copy.newName("value"); // "value_" (knows about original allocation)NameAllocator allocator = new NameAllocator();
// Java keywords are automatically avoided
String className = allocator.newName("class"); // "class_"
String ifVar = allocator.newName("if"); // "if_"
String forVar = allocator.newName("for"); // "for_"
String returnVar = allocator.newName("return"); // "return_"NameAllocator allocator = new NameAllocator();
// Generate unique parameter names
String param1 = allocator.newName("value"); // "value"
String param2 = allocator.newName("value"); // "value_"
String param3 = allocator.newName("result"); // "result"
MethodSpec method = MethodSpec.methodBuilder("process")
.addParameter(String.class, param1)
.addParameter(int.class, param2)
.addParameter(boolean.class, param3)
.build();NameAllocator allocator = new NameAllocator();
// Generate unique field names
List<FieldSpec> fields = new ArrayList<>();
for (String name : Arrays.asList("id", "name", "id", "value")) {
String uniqueName = allocator.newName(name);
fields.add(FieldSpec.builder(String.class, uniqueName)
.addModifiers(Modifier.PRIVATE)
.build());
}
// Results in fields: id, name, id_, valueNameAllocator allocator = new NameAllocator();
CodeBlock.Builder code = CodeBlock.builder();
// Generate unique local variable names
String counter = allocator.newName("i");
String temp = allocator.newName("temp");
String result = allocator.newName("result");
code.addStatement("int $N = 0", counter);
code.beginControlFlow("for (int $N = 0; $N < 10; $N++)", counter, counter, counter);
code.addStatement("$T $N = process($N)", String.class, temp, counter);
code.addStatement("$N.add($N)", result, temp);
code.endControlFlow();NameAllocator allocator = new NameAllocator();
// Map database columns to Java field names
Map<String, String> columnToField = new HashMap<>();
columnToField.put("user_name", allocator.newName("userName", "user_name"));
columnToField.put("user_id", allocator.newName("userId", "user_id"));
columnToField.put("user-email", allocator.newName("userEmail", "user-email"));
// Generate fields
for (Map.Entry<String, String> entry : columnToField.entrySet()) {
String fieldName = allocator.get(entry.getValue());
FieldSpec field = FieldSpec.builder(String.class, fieldName)
.addModifiers(Modifier.PRIVATE)
.build();
}NameAllocator allocator = new NameAllocator();
// Ensure unique nested class names
String builderClass = allocator.newName("Builder");
String nodeClass = allocator.newName("Node");
String entryClass = allocator.newName("Entry");
TypeSpec outer = TypeSpec.classBuilder("Container")
.addType(TypeSpec.classBuilder(builderClass).build())
.addType(TypeSpec.classBuilder(nodeClass).build())
.addType(TypeSpec.classBuilder(entryClass).build())
.build();// Create allocator for method scope
NameAllocator methodScope = new NameAllocator();
// Add parameter names to scope
methodScope.newName("input", "param1");
methodScope.newName("output", "param2");
// Clone for nested scope (e.g., lambda or anonymous class)
NameAllocator nestedScope = methodScope.clone();
// Add local variables in nested scope
String local = nestedScope.newName("temp"); // "temp"
String local2 = nestedScope.newName("input"); // "input_" (avoids parameter)NameAllocator allocator = new NameAllocator();
// Generate unique import aliases for classes with same simple name
Map<String, String> imports = new HashMap<>();
imports.put("java.util.Date", allocator.newName("Date", "java.util.Date"));
imports.put("java.sql.Date", allocator.newName("Date", "java.sql.Date"));
String utilDate = allocator.get("java.util.Date"); // "Date"
String sqlDate = allocator.get("java.sql.Date"); // "Date_"NameAllocator allocator = new NameAllocator();
String fieldName = "userName";
String getterName = allocator.newName("get" + capitalize(fieldName));
String setterName = allocator.newName("set" + capitalize(fieldName));
MethodSpec getter = MethodSpec.methodBuilder(getterName)
.addModifiers(Modifier.PUBLIC)
.returns(String.class)
.addStatement("return $N", fieldName)
.build();
MethodSpec setter = MethodSpec.methodBuilder(setterName)
.addModifiers(Modifier.PUBLIC)
.addParameter(String.class, fieldName)
.addStatement("this.$N = $N", fieldName, fieldName)
.build();NameAllocator allocator = new NameAllocator();
// Convert database column names with special characters
String id = allocator.newName(NameAllocator.toJavaIdentifier("user-id"));
String email = allocator.newName(NameAllocator.toJavaIdentifier("email_address"));
String created = allocator.newName(NameAllocator.toJavaIdentifier("created at"));
// Results: user_id, email_address, created_atNameAllocator allocator = new NameAllocator();
// Generate multiple similar methods
List<String> operations = Arrays.asList("create", "read", "update", "delete");
List<MethodSpec> methods = new ArrayList<>();
for (String op : operations) {
String methodName = allocator.newName(op + "User");
methods.add(MethodSpec.methodBuilder(methodName)
.addModifiers(Modifier.PUBLIC)
.returns(void.class)
.build());
}NameAllocator allocator = new NameAllocator();
// Generate names with consistent patterns
String field = allocator.newName("m" + "value"); // "mValue"
String getter = allocator.newName("getValue"); // "getValue"
String setter = allocator.newName("setValue"); // "setValue"
String local = allocator.newName("value"); // "value"// In annotation processor
NameAllocator allocator = new NameAllocator();
for (Element element : roundEnv.getElementsAnnotatedWith(MyAnnotation.class)) {
String fieldName = element.getSimpleName().toString();
String uniqueName = allocator.newName(fieldName, element);
// Generate code using unique name
FieldSpec field = FieldSpec.builder(String.class, uniqueName)
.addModifiers(Modifier.PRIVATE)
.build();
}
// Later retrieve by element
Element someElement = ...;
String allocatedName = allocator.get(someElement);toJavaIdentifier() for user input or external data before allocationclass NameAllocator implements Cloneable {
NameAllocator();
static String toJavaIdentifier(String suggestion);
String newName(String suggestion);
String newName(String suggestion, Object tag);
String get(Object tag);
NameAllocator clone();
}Install with Tessl CLI
npx tessl i tessl/maven-com-palantir-javapoet--javapoet@0.11.0docs