Tuesday, May 3, 2011

Enforce presence of no-argument constructor at compile time (Java)

I've got a class somewhat like this:

public class Test {

    private final List<ISomeType> things = new LinkedList<ISomeType>();

    public <T extends ISomeType> Test(Class<T> clazz, int order) {
        for (int i = 0; i < order; i++) {
            try {
                this.things.add(clazz.newInstance());
            } catch (Exception e) { 
                // stackoverflowers use your imagination
            }
        }
    }
}

Where I expect and hope the Class clazz has an accessible no-argument constructor. Is there any way I can enforce presence of it at compile time?

From stackoverflow
  • Reflection is about doing things at runtime instead of compile time. Don't use reflection if you want your code to work.

    Ridcully : -1 Your code will work, also with Reflection, as long as you really understand what you are doing. But you're right, one should not use Reflection without need, as you lose compile time safety.
  • There is no way to enforce constructor requirements at compile time. At runtime you can check class.getConstructors() and ensure there is one that has no args (or just catch the exception like you are in the sample code).

    Usually the no-arg constructor requirement is just listed in the Javadoc of the base class or interface.

  • Your best bet is to create a unit test that checks this for each class you care about, and then run the unit tests at build time. Alternately, you can create a test class -- not distributed with your code -- that does nothing but exercise the no-arg constructors of the classes you care about. Not a great option.

  • There are some tools for code style validation that can be extended to check for this type of requirement. For eclipse (and others), PMD may help you. By looking at the tutorial I think you should be able to write an specific rule to check for constructors without any parameters.

  • What about this?

    interface Provider<T> {
       T get();
    }
    
    public class Test {
    
        private final List<ISomeType> things = new LinkedList<ISomeType>();
    
        public <T extends ISomeType> Test(Provider<T> provider, int order) {
            for (int i = 0; i < order; i++) {
                try {
                    this.things.add(provider.get());
                } catch (Exception e) { 
                    // stackoverflowers use your imagination
                }
            }
        }
    }
    
  • One off-topic tip: It's advisable to follow the official Java naming conventions found at http://java.sun.com/docs/codeconv/html/CodeConventions.doc8.html#367.

  • The link below shows how to solve a similar situation (checking whether the subclasses of a particular class all have no-argument constructor) using Java 6 and the Annotation Processing Tool:

    Annotation Processing Tool

    Maybe you can adapt their solution to solve your problem.

    Michael Myers : Good link. That might very well be the answer.

0 comments:

Post a Comment