Array of Parameter Names in Java

My last post suggested an extension to the Java language that I think will be quite helpful. Until such a feature exists, we can fake it by using annotations.

I created an annotation with a processor that creates a new class, one the contains a single static instance of an array of the parameter names from the constructor.

All code on this page released under the same license as the OpenJDK Libraries: GPL with the classpath exception.

First, the annotation itself.

package com.younglogic.annote;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

public @interface NamedParameters {


Next the annotation processor. This uses the javac API, which really should become part of the Base Java platform. In order to compile I added /usr/lib/jvm/java-1.7.0/lib/tools.jar to the classpath.

package com.younglogic.annote;

import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;


@SupportedAnnotationTypes(value = { "com.younglogic.annote.NamedParameters" })
public class NamedParametersAnnotationProcessor extends AbstractProcessor {

	public boolean process(Set annotations,
			RoundEnvironment roundEnv) {
		for (TypeElement element : annotations) {
			for (Element constructor : roundEnv
					.getElementsAnnotatedWith(element)) {

				ClassSymbol classSymbol = (ClassSymbol) constructor
				PackageElement packageElement = (PackageElement) classSymbol

				JavaFileObject jfo;
				try {
					jfo = processingEnv.getFiler().createSourceFile(
							classSymbol.getQualifiedName() + "ParameterNames");
					BufferedWriter bw = new BufferedWriter(jfo.openWriter());
					bw.append("package ");
					bw.append("public class " + classSymbol.getSimpleName()
							+ "ParameterNames {");
					bw.append("    static String[] instance = {");
					MethodSymbol symbol = (MethodSymbol) constructor;
					int i = 0;
					for (VarSymbol param : symbol.getParameters()) {
						if (i++ > 0) {
						bw.append("            \"" + + "\"");
					bw.append("        };");
					bw.append("    }");
				} catch (IOException e) {
					// TODO Auto-generated catch block


		return true;

A sample class that uses this annotation. Note that this class is immutable.

package com.younglogic.annotetest;

import com.younglogic.annote.NamedParameters;

public class SampleClass {

	final String s1;
	final String s2;
	final Integer i1;

	public SampleClass(String s1, String s2, Integer i1) {
		this.s1 = s1;
		this.s2 = s2;
		this.i1 = i1;

	public String toString() {

		return "SampleClass values are: s1=" + s1 + ", s2=" + s2 + ", i1=" + i1.toString();

Now add some parameters to the compiler.

-processor is the processor we want to explicitly call
-processorpath tells it where to find the new annotation.
-s tells it where to put the generated code

 javac -cp ../NamedParameters/bin/  -processorpath ../NamedParameters/bin/ -s /tmp/generated/ -processor com.younglogic.annote.NamedParametersAnnotationProcessor   src/com/younglogic/annotetest/

This will generate the source file: /tmp/generated/com/younglogic/annotetest/

package com.younglogic.annotetest;

public class SampleClassParameterNames {
    public static String[] instance = {

And compile it to /tmp/generated/com/younglogic/annotetest/SampleClassParameterNames.class

We can use that information to create new instances. I have a file with the values I want to use to create a new instance.


Read it in and populate a new instance dynamically:

package com.younglogic.annotetest;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Properties;

public class UseParamNames {

	public static void main(String[] args) throws IOException,
			InstantiationException, IllegalAccessException,
			IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
		Properties properties = new Properties();

		InputStream instream = UseParamNames.class

		Constructor c = getConstructor();

		Object[] initargs = new Object[SampleClassParameterNames.instance.length];
		int i = 0;
		for (String name : SampleClassParameterNames.instance) {
			Class[] argTypes = { String.class };

			String strvalue = properties.getProperty(name);
			String[] paramArgs = new String[1];
			paramArgs[0] = strvalue;

			initargs[i] = c.getParameterTypes()[i].getConstructor(argTypes)


		Object newInstance = c.newInstance(initargs);


	private static Constructor getConstructor() {
		for (Constructor c : SampleClass.class.getConstructors()) {
			if (c.getAnnotations().length > 0) {
				return c;

		return null;

Which, when run, produces the output:

SampleClass values are: s1="first", s2="next", i1=5

3 thoughts on “Array of Parameter Names in Java

  1. Hey Adam:

    Alternatively you can annotative the method parameters themselves. This is the approach that Spring MVC and JAX-RS (@PathParam) and JAX-WS (@WebParam) use. Then the code to get the parameter names from the annotations via reflection at runtime is straightforward. Or you could use Paranamer (

    — Eric

  2. Eric, seems right on to me.

    If you annotate each parameter name, you end up repeating yourself. You have to tag each parameter.

    I’ve just stumbled across and that seems to me to be the way to go: straightforward manipulations of the AST to provide true Macro functionality in Java. Ideally, I should be able to create immutable objects by simply declaring a list of fields and adding an annotation, which Lombok seems to Support.

Leave a Reply

Your email address will not be published. Required fields are marked *